Read data from a url behind a proxy - node.js

WEB Server I want to connect to
I have a web service running in a private network. This server is a web service which I can see working in the browser if I set the socks proxy in the browser.
My Service
I need node.js server on my machine to use the socks proxy to connect and call the web server
My UseCase
I need to do post requests for xml data as well as do some get requests.
My Problem
My app is not able to connect to the server hidden behind the socks proxy.
I do not want to set the global proxy for node or anything, only for one part of the app.
Updated : Working Solution
While the answer directs in the correct direction, I will include the final working solution here for reference as it needed a few modifications to the examples on github
var shttp = require('socks5-http-client');
var options = {} ;
options.host = 'ip.of.web.service';
options.port = 1919; //port of webservice
options.path = '/control/getjson'; //path on webservice to get
options.socksPort = 8778; //socks proxy port
options.socksHost = 'ip.of.socks.proxy';
var req = shttp.get(options, function (res) {
res.setEncoding('utf8');
res.on('readable', function () {
callback(res); //send response to my function for further processing.
});
});

Using socks proxy is not natively supported in the built in http client object.
Following 2 libraries makes it easy to connect to http endpoints through a socks proxy. Give it a try
Use socks5-http-client for connecting to http endpoints
Use socks5-https-client for connecting to https endpoints

Related

how can i use wss in node.js, if the https server is a separate node.js application?

I've created a multiplayer game with websockets in nodejs (using the ws lib), which works just fine. For debugging, I connected to the websocket server with my client webpage by just opening the html file via file:// protocol.
I wanted to have the page hosted on my web-server which uses https. This web-server also uses nodejs, but because the webpage is served via https, it cannot create a connection via ws and needs wss. Security downgrading and so on.
My problem is that I've got two separate programs: the https webserver and the websocket "game" server.
When i try connecting to the ws server i get:
Uncaught DOMException: The operation is insecure.
I only found instructions on how to set up wss by creating a https server, but i already have one.
Do i need to combine the two programs?
Could i maybe just serve the single page for the game with http?
Is there some other technology, which doesn't have these security restrictions? (i don't care about encryption for the websockets)
I was able to make it work:
Instead of wanting to use the https server from the web-server, i "upgraded" my http-server for the "gameserver" to https. I didn't want to "create" another https server, because i thought it would cause errors, but i already made a http server indirectly anyways, with new WebSocketServer.Server({ port: PORT });.
To create the https server and use it for the WebSocketServer i used this code:
let cert = fs.readFileSync(pathtocertkey, "utf8");
let key = fs.readFileSync(pathtopublickey, "utf8");
let options = {key: key, cert: cert};
let server = require("https").createServer(options);
const wss = new WebSocketServer.Server({ server: server});
After that i could listen to any port with server.listen(PORT,callback).
I also wasn't sure how or if i could get the cert i got with greenlock. But I found it undergreenlock.d/live/[yourdomain]/
With greenlock.d being the configDir specified in greenlock.init(options).
For the client i need to connect like this :
ws = new WebSocket("wss://mydomain:"+PORT);'

Creating A HTTP proxy server with https support and use another proxy server to serve the response using nodejs

I need help creating a proxy server using node js to use with firefox.
the end goal is to create a proxy server that will tunnel the traffic through another proxy server (HTTP/SOCKS) and return the response back to firefox. like this
I wanna keep the original response received from the proxy server and also wanna support https websites as well.
Here is the code I came up with.
var http = require('http');
var request = require("request");
http.createServer(function(req, res){
const resu = request(req.url, {
// I wanna Fetch the proxy From database and use it here
proxy: "<Proxy URL>"
})
req.pipe(resu);
resu.pipe(res);
}).listen(8080);
But it has 2 problems.
It does not support https requests.
It also does not supports SOCKS 4/5 proxies.
EDIT: I tried to create a proxy server using this module. https://github.com/http-party/node-http-proxy
but the problem is we cannot specify any external proxy server to send connections through.
I have found a really super simple solution to the problem. We can just forward all packets as it is to the proxy server. and still can handle the server logic with ease.
var net = require('net');
const server = net.createServer()
server.on('connection', function(socket){
var laddr = socket.remoteAddress;
console.log(laddr)
var to = net.createConnection({
host: "<Proxy IP>",
port: <Proxy Port>
});
socket.pipe(to);
to.pipe(socket);
});
server.listen(3000, "0.0.0.0");
You have to use some middleware like http-proxy module.
Documentation here: https://www.npmjs.com/package/http-proxy
Install it using npm install node-http-proxy
This might help too: How to create a simple http proxy in node.js?

Why hook an httpserver in a websocket server in node/express?

I see a lot of examples hooking an http server during the creation of a WS server, more or less like the following
var server = http.createServer(function(request, response) {
// process HTTP request. Since we're writing just WebSockets
// server we don't have to implement anything.
});
server.listen(1337, function() { });
// create the server
wsServer = new WebSocketServer({
httpServer: server
});
or
var httpServer = http.createServer().listen(websocketport);
/*
* Hook websockets in to http server
*/
socketServer.installHandlers(httpServer, { prefix: '/websockets' });
I dont understand the reason why. Is there any benefit from that?
What is wrong with the classic WS setup, like so
const WebSocket = require('ws')
const wss = new WebSocket.Server({ port: 8080 })
wss.on('connection', ws => {....
Why shouldn't I just use a WS server with no http server at all?
This depends entirely on the project.
Typically, most examples you will see are not pure websocket server examples and instead will assume that you are incorporating websocket functionality into a larger application stack.
If you have no need for an HTTP server, then you shouldn't attach your websocket listener to an instance of one. If you do need an HTTP server, then you are best off attaching your websocket listener in the following situations:
If your HTTP server and your WebSocket listener are on the same domain
You want to be able to manage or push to your socket connections when some HTTP requests are made.
This is most likely because usually, you would provide some REST APIs which uses the HTTP server along with your WS server.
If you are trying to use the same host and port for both of them (HTTP & WS) together, you need to sort of combine or encapsulate one of them into another so that it can accept and handle both kinds of protocol.
However, if you are only trying to use WS without HTTP, then you probably do not need the HTTP server, just the WS server will do, as you have shown in your classic WS setup.
On the other hand, if you only need the HTTP server without WS, then you do not need to implement WS, just HTTP server will do.

How to proxy websocket connections to other websockets in NodeJS

I need to create a small authentication layer on top of a 3rd party web-socket based chat application. I have a simple API (get) that can validate api tokens from requests. What I want to do is essentially validate their token (which I know how to do) then proxy the websocket connection to the actual chat server.
I've been looking for solutions and this thread seems to give some pointers in the right direction however I can't get any of the solutions to work.
var http = require('http'),
WebSocket = require('faye-websocket'),
conf = require('./conf.json');
var server = http.createServer();
server.on('upgrade', function(request, socket, body) {
console.log('upgrade fired');
var frontend = new WebSocket(request, socket, body),
backend = new WebSocket.Client('ws://echo.websocket.org');
frontend.pipe(backend).pipe(frontend);
});
server.on('connection', function(socket) {
console.log('connection')
backend = new WebSocket.Client('ws://echo.websocket.org');
console.log(backend);
socket.pipe(backend).pipe(socket);
})
server.listen(conf.port);
console.log('Listening on '+port.conf);
The connection event is fired, however the upgrade event which is supposed to be fired on a ws connection never is.
The goal is to first authenticate a api key to an external server, then open a proxy to the chat websocket all through a request to this node server via a websocket connection. I'll most likely pass the api key as a get parameter for simplicity. I also looked at this package and attempted using it however it didn't work as well.
The issue ended up being with nginx. I forgot I was proxying requests through the reverse proxy and by default nginx does not support the ws:// connection so it drops it.

How to use JavaScript socket.io-client library via socks5 proxy?

I haven't found anything in the documentation of socket.io about proxy.
But maybe is it possible to set proxy via some options settings?
Are there any workarounds to work this socket.io via socks5 proxy in Node?
SocketIO does not support proxies out of the box. What you need is a custom http agent which tunnels through the proxy. Fortunately there is socks-proxy-agent for that. Here's a demo:
const ProxyAgent = require('socks-proxy-agent')
const IO = require('socket.io-client')
// agent for a local socks5 proxy
const Agent = new ProxyAgent('socks5://127.0.0.1:9050')
// connect to domain.com via Agent
const SocketClient = IO('http://domain', {
agent: Agent,
})
SocketClient.on('connect', ()=>{
console.log('connected via proxy!')
})

Resources