I need to make tcp socket connection to smtp server. Is it possible to connect through proxy server on nodejs? Is there any npm modules available to use? I couldn't find any at all.
var net = require('net');
var HOST = '127.0.0.1';
var PORT = 6969;
var client = new net.Socket();
client.connect(PORT, HOST, function() {
console.log('CONNECTED TO: ' + HOST + ':' + PORT);
client.write('I am here!');
});
// Add a 'data' event handler for the client socket
// data is what the server sent to this socket
client.on('data', function(data) {
console.log('DATA: ' + data);
});
// Add a 'close' event handler for the client socket
client.on('close', function() {
console.log('Connection closed');
});
net.socket, tls.connect and dgram have no proxy support.
The simplest way to use it with proxy is to replace some libc functions with proxychains or something similar.
var client = require('tls')
.connect(443, 'www.facebook.com', function() {
console.log('connected');
client.write('hello');
})
.on('data', function(data) {
console.log('received', data.toString());
})
.on('close', function() {
console.log('closed');
});
proxychains node fit.js
connected
received HTTP/1.1 400 Bad Request
...
closed
Other than 'net' you don't need another module to make a socket connect to a host through a proxy server as long at the proxy server supports HTTPS traffic.
Create a socket connection to the proxy server
Send an HTTP CONNECT message to inform the proxy server of the host and port you want to connect to
If the proxy server responds with an HTTP 200 response then the proxy server established a socket connection to your desired target and is now relaying the traffic between the sockets
If the proxy server responded with any HTTP response other than 200 then the connection was not established.
Even though this process starts with HTTP it doesn't mean it wouldn't work for SMTP traffic. The initial HTTP message is just used to negotiate the connection, after that its just raw traffic. A proxy server might look at the port or host you want to connect to and disallow it. For example, block connections to ports below 80 or below 443 such as port 25 so it really depends on the proxy server if the connection will be allowed.
Yes, it is possible with one of these NPM modules:
http-proxy-agent: An HTTP(s) proxy http.Agent implementation for HTTP endpoints
https-proxy-agent: An HTTP(s) proxy http.Agent implementation for HTTPS endpoints
pac-proxy-agent: A PAC file proxy http.Agent implementation for HTTP and HTTPS
socks-proxy-agent: A SOCKS (v4a) proxy http.Agent implementation for HTTP and HTTPS
HTTPS Proxy Example:
var url = require('url');
var WebSocket = require('ws');
var HttpsProxyAgent = require('https-proxy-agent');
// HTTP/HTTPS proxy to connect to
var proxy = process.env.http_proxy || 'http://168.63.76.32:3128';
console.log('using proxy server %j', proxy);
// WebSocket endpoint for the proxy to connect to
var endpoint = process.argv[2] || 'ws://echo.websocket.org';
var parsed = url.parse(endpoint);
console.log('attempting to connect to WebSocket %j', endpoint);
// create an instance of the `HttpsProxyAgent` class with the proxy server information
var opts = url.parse(proxy);
var agent = new HttpsProxyAgent(opts);
// finally, initiate the WebSocket connection
var socket = new WebSocket(endpoint, { agent: agent });
socket.on('open', function () {
console.log('"open" event!');
socket.send('hello world');
});
socket.on('message', function (data, flags) {
console.log('"message" event! %j %j', data, flags);
socket.close();
});
I hope this helps.
Related
Could not connect to localhost:3000
17:02:53
Error: Unexpected server response: 404
Handshake Details
Request URL: http://localhost:3000/socket.io/?EIO=3&transport=websocket
Request Method: GET
Status Code: 404 Not Found
My express server listen on 3000 port and socketio http on 443 port, i am able to connect socket by hosting this on ec2 instance and using ec2 ip with port number on postman socket connection ui, but on localhost connection always failed with above error on postman socket beta ui.
You need to call listen only once. If you pass your http/https server to express, app.listen() is enough. (except you want to listen on 2 different ports.. For testing, let's call it only once.)
For accessing it on localhost try setting it explicitly with the parameter hostname in app.listen().
Example:
async function startServer() {
const app = express();
const credentials = {key: key, cert: crt};
const httpsServer = createServer(credentials,app);
const io = socketIO(httpsServer);
await require('./loaders').default({ expressApp: app, socketIO: io });
// Let's only call listen once for testing purposes. If you call
// listen on the express app, your https server will automatically listen
// to the same configuration.
// httpsServer.listen(4000);
const port = 3000
const hostname = 'localhost'
// explicitly let the app listen on localhost. If hostname is not
// provided, it will take the first found ipv4 interface
app.listen(port, hostname, err => {
if (err) {
Logger.error(err);
process.exit(1);
return;
}
Logger.info(`
################################################
🛡️ Server listening on https://${hostname}:${port} 🛡️
################################################
`);
});
}
Now you should be able to connect your socket. If it still does not work try
to use http module instead of https for better isolating your problem.
Note that your server now only will be accessible using localhost and not over ip. Both may only be possible when running 2 server instances with different hostnames.
async function startServer() {
const app = express();
const credentials = {key: key, cert: crt};
const httpsServer = createServer(credentials,app);
const io = socketIO(httpsServer);
await require('./loaders').default({ expressApp: app, socketIO: io });
httpsServer.listen(443);
app.listen(config.port, err => {
if (err) {
Logger.error(err);
process.exit(1);
return;
}
Logger.info(`
################################################
🛡️ Server listening on port: ${config.port} 🛡️
################################################
`);
});
}
This is my app.ts file, I am using Ubuntu. so 443 port is not allowed, i changed this port to 4000, now the app listen on the 3000 and socket http server on 4000, but socketio not able to connect with socket url localhost:3000
i'm making a game that use WebSockets and this is the code that i use to start a WebSocket server:
const server = require("http").Server(app);
const port = 3005;
server.listen(port, () => {
console.log('Server started on port: ' + port);
});
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ server })
wss.on('connection', function connection(ws) {});
And this code i use for connecting a user to the WebSocket:
this.SERVER_URL ='ws://localhost/?fvukovic'; <-- fvukovic is the user
this.ws = new WebSocket(this.SERVER_URL, ["test"]);
this.ws.onopen = () => {
console.log('open');
};
This works perfectly, but when i push that on server and i change the ip address to 195.201.119.221 which is the ip of the server, port is still 3005, i cant connect to it anymore..
I get this error:
WebSocket connection to 'ws://195.201.119.221:3005/?fvukovic' failed: Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT
Do i need something more when i put the the app on a real server?
I'm building an web app(nodejs, port: xxx0) which interacts with an another app(nodejs, port:xxx5) which is serving as the socket.io server. My socket.io client code goes well in my web app. All works well in my local as the connections refers to the server as io.connect('http://localhost:xxx5/')
But the same is not working when i promote it to higher env as the connection string is as io.connect('https://domainName/')
When my app is trying to connect, I'm receiving the below error:
websocket.js:112 WebSocket connection to 'wss://domainName/socket.io/?EIO=3&transport=websocket' failed: Connection closed before receiving a handshake response
Am I missing anything?
When I try hitting the server(higher env) via socket.io tester, I get the response as No sockets Found and immediately then An error occurred while reconnecting
NOTE:. The server instances are registered in an api gateway in higher env.
Server.js
const app = require('express')()
const port = process.env.PORT || xxx5
const server = app.listen(port)
const io = require('socket.io').listen(server)
let ns = io.of('/namespace')
ns.on('connection', (socket) => {
logger.info('User connected')
socket.emit('messages', {new:2,[{title:'Hi'},{title:'Test'}]})
})
Client.js
import io from 'socket.io-client'
const socket = io(`https://domainName/namespace`, { transports:
['websocket'], rejectUnauthorized: true})
// const socket = io('http://localhost:xxx5/namespace', { transports:
['websocket'], rejectUnauthorized: true})
// above commented url is in local
socket.on('connect', () => {
logger.info("Connected")
})
socket.on('messages', (data) => {
logger.info(`New messages : ${data.new}`)
})
socket.on('error', (error) => {
logger.error(`Error encountered : ${error}`)
})
Is your application running as a priveleged user? Any TCP/UDP socket less than 1024 is considered and IANA reserved port and required elevated priveleges to bind as a listening service.
Using cURL can also aid in providing the necessary handshake: (See reference of websocket handshake process here; https://en.m.wikipedia.org/wiki/WebSocket#Protocol_handshake)
sh
$ curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: echo.websocket.org" -H "Origin: http://domainname " http://domainname
I have a socket.io server only using the 'xhr-polling' transport running at port 5000 on a system with nginx configured to pass requests that start with '/api' to that port.
In my client, on connect, I specify the socket.io resource as 'api/socket.io' which appears to correctly forward the initial connection request to the server and trigger a connection event. However, responses sent from the server using socket.emit do not reach the client.
If I connect the client directly to port 5000, leave off the 'resource' option, and bypass nginx forwarding, everything seems to work ok.
Server:
var io = require('socket.io').listen(5000, {transports: ['xhr-polling']});
io.sockets.on('connection', function (socket) {
console.log('Connection spotted!');
socket.emit('connected', 'hi');
});
Client (not working):
var socket = io.connect(window.location.hostname, {resource:'api/socket.io'});
socket.on('connected', function(data) {
alert('Connected!!!');
});
Client (working):
var socket = io.connect(window.location.hostname, {port: 5000});
socket.on('connected', function(data) {
alert('Connected!!!');
});
nginx:
location / {
proxy_pass http://localhost:5000/;
}
In both cases I see the "Connection spotted!" log message on the server, but client gets data and alerts when connected directly to the port.
These are the versions of node and required modules I am using:
Node.js: 0.10.16
Websocket Library: einaros/ws ws#0.4.28
Proxy server: nodejitsu/node-http-proxy http-proxy#0.10.3
When I run the following program my console output looks like this, and doesn't move beyond this point:
$ node app.js
proxy: got upgrade, proxying web request
wss: got connection
Here's the code:
// app.js
// A simple proxying example
//
// Setup websocket server on port 19000
// Setup proxy on port 9000 to proxy to 19000
// Make a websocket request to 9000
//
var WebSocket = require('ws'),
WebSocketServer = WebSocket.Server,
proxy = require('http-proxy');
// goes in a loop sending messages to the server as soon as
// the servers are setup
var triggerClient = function() {
var ws = new WebSocket('ws://localhost:9090/');
ws.on('open', function() {
console.log('ws: connection open');
setInterval(function() {
ws.send("Hello");
}, 1000);
});
ws.on('message', function(data) {
console.log('ws: got ' + data);
});
}
// setup websocket server and a proxy
//
var go = function() {
// setup a websocket server on port 19000
//
var wss = new WebSocketServer({ port: 19000 });
wss.on('connection', function(ws) {
console.log('wss: got connection');
ws.on('message', function(data) {
console.log('wss: got ' + data);
ws.send('wss response: ' + data);
});
});
// setup a proxy server
var server = proxy.createServer(function (req, res, proxy) {
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 19000
});
});
server.on('upgrade', function (req, socket, head) {
console.log('proxy: got upgrade, proxying web request');
server.proxy.proxyWebSocketRequest(req, socket, head, {
host: 'localhost',
port: 19000
});
});
server.listen(9090, triggerClient);
};
process.nextTick(go);
My problem eventually started when I was trying to use hipache, I then simplified things to node-http-proxy and then finally to this piece of code.
If you change the port the WebSocket client is connecting to from 9090 to 19000 (thereby bypassing the proxy), things seem to work fine.
Any suggestions, pointers, feedback would be greatly appreciated.
Thanks!
The core problem is that the master branch of node-http-proxy is only compatible with node <= 0.8.x (see https://github.com/nodejitsu/node-http-proxy#when-to-use-node-http-proxy): there's a tree that implements support for 0.10.x (see https://github.com/nodejitsu/node-http-proxy/tree/caronte) but it isn't the mainline branch and I haven't found any indication of when it will be merged in and available.