NodeJS: Simple Socks Proxy Server

Image for post
Image for post

During development of a VueJS application you sometimes need a local proxy to avoid the CORS problematic. With VueJS using the CLI the solution is something like this in your vue.config.js:

module.exports = {
...
devServer: {
proxy: {
'^/sta': {
target: https://service.tereno.net',
changeOrigin: true
},
...

The last time I want to use this pattern, it simply does not fit to my current development environment — using a tunnel into my workplace network. So I tried to find the correct settings for this case, but was not able to figure it out or maybe it is almost not possible.

My last resort then was to create another proxy that handles this for me.

Using google to find a running solution, I found socks-proxy-agent is the right base for doing this. So I created a simple server with express like this:

import express from 'express'
import axios from 'axios'
import SocksProxyAgent from 'socks-proxy-agent'
const proxyOptions = 'socks5://<your proxy to work>:<and port>'
const httpsAgent = new SocksProxyAgent(proxyOptions)

const app = express()

app.get('/sta/*', async (req, res, next) => {
// console.log(req)
const { data } = await axios({
httpsAgent,
method: 'GET',
url: `https://service.tereno.net${req.path}`,
})
// console.log(data)
res.send(data)
})
app.listen(3000)

Modifiying the vue.config.js using this proxy:

module.exports = {
...
devServer: {
proxy: {
'^/sta': {
target: 'http://localhost:3000',
changeOrigin: true
},
...

gives me what I want, a working solution.

In this szenario I only proxied get request below /sta/, so if you need more, you have to investigate a little bit to support post and the like.

Further development …

To support more than one URL you can add more entries into vue.confi.js and start a server for each, but there is a smarter solution to this problem: Create one to rule them all, like this.

vue.config.js:

devServer: {
proxy: {
'^/api1': {
target: 'http://localhost:3000/https://api1',
changeOrigin: true,
// logLevel: 'debug',
},
'^/api2': {
target: 'http://localhost:3000/https://api2',
changeOrigin: true,
// logLevel: 'debug',
},

Each entry has a target containing the target URL itself, so we can use this information from the request to delegate to the right target, that’s it.

index.js:

import express from 'express'
import axios from 'axios'
import SocksProxyAgent from 'socks-proxy-agent'
const proxyOptions = 'socks5://127.0.0.1:1234'
const httpsAgent = new SocksProxyAgent(proxyOptions)

const app = express()

app.get('/*', async (req, res, next) => {
const { data } = await axios({
httpsAgent,
method: 'GET',
url: `${req.params[0]}`,
})
// console.log(data)
res.send(data)
})
app.listen(3000)

The target url is given in request parameter where you can access it. The additionally given request parameters are in req.query.

As always this is only a start point. When you need more, you have to investigate further.

See you

Developer since the 80'th, working at Forschungszentrum Jülich (http://www.fz-juelich.de) …

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store