websockets with javascript and nginx on docker - javascript

i have a docker compose that contains 3 containers " node-red , influxdb , a html with JavaScript webpage with nginx:alpine image "
in the html and JavaScript webpage i have a list of images and i change the image according to the data that come from node red via websockets
and i receive my data with this JavaScript function
function startConnect() {
document.getElementById('dt').click();
socket = new WebSocket("ws://mywebsite.com:1880/ws/test");
socket.onmessage = function(e) {onMessageArrived(e.data)}
console.log("connected");
socket.onopen = function() {socket.send("1")};
}
// Called when a message arrives
function onMessageArrived(message) {
console.log("onMessageArrived: " + message);
var obj = JSON.parse(message);
document.getElementById("image1").src = "myimage/" + obj.L + "_DL.png";
document.getElementById("image2").src = "myimage/" + obj.M + obj.F + obj.S + "_" + obj.Z48_70 + "_M.png";
document.getElementById("image3").src = "myimage"+ obj.V + obj.V + "_X";
}
every thing worked fine until i have decided to use docker for "node-red and influx and the html webpage" and use nginxwithout docker with letsencrypt certifacts to handle the reverse proxy of my 3 containers.
The problem that i am facing is that i cannot receive data with websockets even though i change the socket = new WebSocket("ws://mywebsite.com:1880/ws/test") to socket = new WebSocket("ws://mywebsite.com:6100/ws/test") the port 6100 used by my webpage contain with this i am having an https error and with socket = new WebSocket("ws://192.170.0.6:6100/ws/test") the IP address of my webpage container and also with new WebSocket("ws://mywebsite/webpage/ws/test") this is handeled by nginx to route it the IP and the port used by my webpage container

If you are connecting to a WebSocket address that is being boot strapped via HTTPS then you need to use the wss: scheme rather than ws:
So if you have enabled https on port 6100 then you need to use wss://mywebsite.com:6100/ws/test
(also if you are using nginx as a reverse proxy is there any reason not to use the default ports of 80 and 443 for http/https respectively?)
EDIT:
If your proxy is presenting the default ports of 80/443 for http/https respectively then you should be using something like the following:
function startConnect() {
document.getElementById('dt').click();
if (location.scheme === 'http:' ) {
socket = new WebSocket("ws://mywebsite.com/ws/test");
} else {
socket = new WebSocket("wss://mywebsite.com/ws/test");
}
socket.onmessage = function(e) {onMessageArrived(e.data)}
console.log("connected");
socket.onopen = function() {socket.send("1")};
}
This will pick ws:// or wss:// depending on how the page is loaded (http vs https)

Related

secure websocket connection between javascript client and netty server

I am developing websocket server with netty frame work version 4.1.6.
I am using the sample code from netty example site
This is my server source code:
public class WebSocketServer
{
static final int PORT = 4466;
public static void main(String[] args)
{
final SslContext sslCtx;
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new WebSocketServerInitializer(sslCtx));
Channel ch = b.bind(PORT).sync().channel();
System.out.println("Open your web browser and navigate to " +
"http://127.0.0.1:" + PORT + '/');
ch.closeFuture().sync();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
An WebSocketServerInitializer source code:
public class WebSocketServerInitializer extends ChannelInitializer<SocketChannel>
{
private static final String WEBSOCKET_PATH = "/websocket";
private final SslContext sslCtx;
public WebSocketServerInitializer(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
#Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(sslCtx.newHandler(ch.alloc()));
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(65536));
pipeline.addLast(new WebSocketServerCompressionHandler());
pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
// pipeline.addLast(new WebSocketIndexPageHandler(WEBSOCKET_PATH));
pipeline.addLast(new WebSocketFrameHandler());
}
}
This is my Html code:
<html>
<head>
<script type="text/javascript">
// Let us open a web socket
var ws = null;
function WebSocketTest()
{
if ("WebSocket" in window)
{
alert("WebSocket is supported by your Browser!");
// Let us open a web socket
ws = new WebSocket("wss://localhost:4466/websocket");
ws.onopen = function()
{
// Web Socket is connected, send data using send()
ws.send("Message to send");
alert("Message is sent...");
};
ws.onmessage = function (evt)
{
var received_msg = evt.data;
alert(received_msg);
//alert("Message is received...");
};
ws.onclose = function()
{
// websocket is closed.
alert("Connection is closed...");
};
window.onbeforeunload = function(event) {
socket.close();
};
}
else
{
// The browser doesn't support WebSocket
alert("WebSocket NOT supported by your Browser!");
}
}
</script>
</head>
<body>
<div id="sse">
Run WebSocket
</div>
</body>
</html>
I browse the page using Chrome browser and got the following message when I click on the link in the web page.
WebSocket connection to 'wss://localhost:4466/websocket' failed: Error in connection establishment: net::ERR_INSECURE_RESPONSE
According to some discussions here, and the netty websocket sample code, wss must be forwarded by HTTPS. However, when I change the following javascript statement in my web page:
ws = new WebSocket("wss://localhost:4466/websocket");
to
ws = new WebSocket("wss://echo.websocket.org");
It works fine. It make me confusing, Why the site echo.websocket.org can working without https? Why my server cannot? are there something missing in my server source code?
PS: the echo.websocket.org example found in the following url:
http://jsbin.com/muqamiqimu/edit?js,console
Your browser is failing to connect to your websocket server, because it detected it is insecure.
This happens because when the browser tries to connect to your server, it will check the SSL certificate. This certificate is basically a proof that says your server is claiming to be the authoritative server for localhost.
Your server claims this by its certificate, what in your case is signed by itself, that's basically the SelfSignedCertificate class, and it's claiming to be "example.com".
This creates 2 issues:
Your browser connects to localhost, but instead of getting a certificate for localhost, it gets 1 for example.com
Your browser does not trust the signer of the certificate to have the authority to make certificates, causing it to be rejected.
There are multiple ways to solve this:
Getting a valid certificate and hosting your application on a server
This would be the recommended solution for production, depending where you get your valid certificate, it may or may not cost money.
Bypass the certificate warning
By manually going to http://localhost:4466/ you can skip past the certificate warning, and basically this adds a 1 time exception for the certificate rule, till you restart your browser
Configuring google chrome to accept invalid certificates for localhost
While this can be insecure (but not as insecure as turning off all certificate validation), it can be a great way to test ssl on development machines.
You can turn ssl validation of for localhost by going to chrome://flags/#allow-insecure-localhost and turning that option on. Notice that you might be required to set the domain of your certificate to localhost when using this option by calling the new SelfSignedCertificate("localhost"); contructor.

Websockets won't start on live server - ssl error 303

Hey there I have a huge issue. I created a web socket system using the Ratchet framework for pho. It works perfectly fine on my local server but for some reason it won't work on my live server. My server is on digital ocean so I'm pretty familiar with the server. I use Apache also. But this is how my we sockets JavaScript code look right now for connecting:
if(typeof(WebSocket) == "function")
{
var host = "wss://www.frindse.com:8181/?chathash=" + mainChatId;
var conn = new WebSocket(host);
conn.onopen = function(e) {
console.log("Connection established!");
// Send back the chat id
conn.send(JSON.stringify({event: "supplyChatHash", data: mainChatId}));
// Add this new user to the connection
conn.send(JSON.stringify({event: "connectNewUserToChat", data: {userId: logged, connectedTo: mainChatId}}));
};
conn.onclose = function(e) {
alert('Disconnected');
};
}
And here is the code for starting the server:
$server = IoServer::factory(
new HttpServer(
new WsServer(
new ChatServerBackend($_GET['chathash'])
)
),
8181
);
For some reason my we sockets server won't start on my live site. Does it have to do with a port? Or anything else?

Laravel Homestead , Socket.io Connection Refused

I`m using laravel Event broadcasting , socket.io , node.js , and redis to pass notifications to the client side in real time.
The code is fairly simple, when i make a get request to '/' on the server an event will be fired and some data will be broadcast to all browsers(client side) which listening to this event on a channel(test-Channel).
The Routes.php content:
Route::get('/', 'uses' => function () {
Event::fire( new App\Events\UserHasRegistered('DummyData') );
return view('test');
}]);
The UserHasRegistered Event class :
class UserHasRegistered extends Event implements ShouldBroadcast{
use SerializesModels;
public $name;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($name){
$this->name = $name;
}
/**
* Get the channels the event should be broadcast on.
*
* #return array
*/
public function broadcastOn(){
return ['test-channel'];
}
}
The node Server file content :
/*General Configurations :
- Setting up the node Server
- Server side Socket.io
- node js Redis Client
- instance of ioredis
*/
var server = require('http').Server();
var io = require('socket.io')(server);
var Redis = require('ioredis');
var redis = new Redis();
/*listen to a channel , and when a Message Arrives we send it to All Listening clients via socket.io*/
redis.subscribe('test-channel');
redis.on('message' , function(channel , message){
message = JSON.parse(message);
// The Client Side Channel naming conversion => channelName:EventPublishedToServer => testChannel:UserHasRegistered
io.emit(channel + ':' + message.event , message.data );
});
/*Booting Up the Server : port 3000 */
server.listen(3000 , function(){
console.log('The Server Is Running');
});
Every thing is working fine and the data is passed to the the node server through redis but on the client side where i use socket.io to listen to a specific channel , i get this weird error
GET http://192.168.10.10:3000/socket.io/?EIO=3&transport=polling&t=1446018378941-633 net::ERR_CONNECTION_REFUSED
The Client side :
<script type="text/javascript" src="/js/socket.io.js"></script>
<script>
/*Homestead IP Address , Port:3000 Node Server Port*/
var socket = io('http://192.168.10.10:3000');
/*When Data is sent to client side*/
socket.on('test-channel:App\\Events\\UserHasRegistered' , function(data){
console.log(data);
//$('ul').append('<li><h5>'+ data.name +'</h5></li>');
});
</script>
I`m Using Windows 10 and Homestead virtual box.
any Help ?
i had this same issue and i solved it opening port 3000 in VirtualBox. For that, you should go into homestead settings inside adn then Network->Port Forwarding and there put 3000 on both ports.
did you try to ssh by "vagrant ssh" to your virtual machine and start your server-file from there? A had the same problem while i was starting my server file from windows- or git-command
Did you try
<script type="text/javascript" src="/js/socket.io.js"></script>
<script>
/*Homestead IP Address , Port:3000 Node Server Port*/
var socket = io.connect('http://192.168.10.10:3000');
/*When Data is sent to client side*/
socket.on('test-channel:App\\Events\\UserHasRegistered' , function(data){
console.log(data);
//$('ul').append('<li><h5>'+ data.name +'</h5></li>');
});
</script>

Client unable to connect to server websocket using gevent-websocket

I am trying to stream data from a background server application to a client-side web-page using gevent-websocket.
When using localhost or leaving ('',8999) I am able to connect to the web-socket, but when trying to access from off the server I cannot seem to connect with the error 'Firefox can't establish a connection to the server at ws://SERVER-IP:8999/.'
I have tried other browsers with the same issue (well I tried chrome as well)
def app(environ, start_response):
ws = environ['wsgi.websocket']
stream_listener.add_socket(ws)
while not ws.closed:
gevent.sleep(0.1)
server = pywsgi.WSGIServer(
('0.0.0.0', 8999), app, handler_class=WebSocketHandler)
server.serve_forever()
As I said I have tried leaving it blank - putting in '0.0.0.0' in hopes that would bind it to all interfaces, but still no luck.
Here is the client side script that works from localhost - but trying to put in the SERVER-IP:8999 fails.
var ws = new WebSocket("ws://SERVER-IP:8999/");
ws.onopen = function() {
ws.send("Hello, world")
}, ws.onmessage = function(a) {
var b = JSON.parse(a.data);
//do something with b
};

See if a server port is open using JavaScript

I can't find any information on this and I was wondering if this was even possible?
I have a Minecraft server that I want to ping to find out if it is on at a specific port. I want to do this in Javascript but from what I can see that you cant really do that or it hasn't been done before. Are there any plugins or 3rd party Javascript vendors that can accomplish this?
For example:
mc.mydomain.net:25565
Javascript pings the server and it changes the text from online to offline, depending on if it can connect.
Server is: Online
Or
Server is: Offline
If it happened that the Minecraft server actually speak plains HTTP on that port (which is unlikely), then it could work.
Otherwise, no, it can't be done, at least not with current specifications.
Browsers can only talk HTTP (i.e. to web servers) and WebSockets, and the SSL variants thereof. I don't know whether the upcoming WebRTC protocol would help.
The alternative is to use Flash - AIUI that has a plain TCP socket capability that can be exposed to JS code that might help in these circumstances.
First of all you can't ping ports, as Ping is using ICMP which doesn't have the concept of ports. Ports belong to the transport layer protocols like TCP and UDP.
So, a solution can be the use of a server side language like PHP to perform the query and then you can make an AJAX request to this page in order to retrieve the result. Here is an example in PHP:
<?php
error_reporting(E_ERROR);
$fp = fsockopen('mc.mydomain.net', 25565, $errno, $errstr, 1);
if (!$fp) {
echo 'no';
} else {
echo 'yes';
fclose($fp);
}
?>
Moreover, to keep your requests fast, you can imagine to cache the result of the above query into a file or a database and refresh its value every couple of minutes (for example by using a cron job) and then serve the cached result to the AJAX request.
From http://www.gnucitizen.org/static/blog/2006/08/jsportscanner.js , the first hit when you search for "javascript portscan":
var AttackAPI = {
version: '0.1',
author: 'Petko Petkov (architect)',
homepage: 'http://www.gnucitizen.org'};
AttackAPI.PortScanner = {};
AttackAPI.PortScanner.scanPort = function (callback, target, port, timeout) {
var timeout = (timeout == null)?100:timeout;
var img = new Image();
img.onerror = function () {
if (!img) return;
img = undefined;
callback(target, port, 'open');
};
img.onload = img.onerror;
img.src = 'http://' + target + ':' + port;
setTimeout(function () {
if (!img) return;
img = undefined;
callback(target, port, 'closed');
}, timeout);
};
AttackAPI.PortScanner.scanTarget = function (callback, target, ports, timeout)
{
for (index = 0; index < ports.length; index++)
AttackAPI.PortScanner.scanPort(callback, target, ports[index], timeout);
};
You can only send HTTP(S) or WS(S) request to the domain you are on with JavaScript. A Ping is much too low-level.
If the minecraft server supports HTTP, you can try to use that.

Categories