node-tcp-proxy
Advanced tools
Comparing version 0.0.11 to 0.0.12
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "0.0.11", | ||
"version": "0.0.12", | ||
"main": "index.js", | ||
@@ -8,0 +8,0 @@ "repository": { |
@@ -6,6 +6,6 @@ # node-tcp-proxy [![Build Status](https://semaphoreci.com/api/v1/tewarid/node-tcp-proxy/branches/master/badge.svg)](https://semaphoreci.com/tewarid/node-tcp-proxy) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/3e3d035c4b78445bbec6fb348cf027e1)](https://www.codacy.com/app/tewarid/node-tcp-proxy?utm_source=github.com&utm_medium=referral&utm_content=tewarid/node-tcp-proxy&utm_campaign=Badge_Grade) [![Maintainability](https://api.codeclimate.com/v1/badges/119038e281e93a7d5d05/maintainability)](https://codeclimate.com/github/tewarid/node-tcp-proxy/maintainability) | ||
```bash | ||
socat TCP-LISTEN:port1,fork TCP:host:port2 | ||
socat TCP-LISTEN:port,fork TCP:host:port | ||
``` | ||
`port1` is where socat listens for incoming requests. `host` and `port2` are the host and port where the actual service is listening at. | ||
`port` is where socat listens for incoming requests. `host:port` are the host and port where the actual service is listening at. | ||
@@ -15,6 +15,6 @@ To achieve the same with node-tcp-proxy | ||
```bash | ||
tcpproxy --proxyPort port1 [--hostname [IP]] --serviceHost host --servicePort port2 [--q] [--tls [both]] [--pfx file] [--passphrase secret] | ||
tcpproxy --proxyPort port [--hostname <name or IP>] --serviceHost host1,host2 --servicePort port1,port2 [--q] [--tls [both]] [--pfx file] [--passphrase secret] | ||
``` | ||
Optionally, `hostname` specifies the IP address to listen at. Node.js listens on unspecified IPv6 address `::` by default. | ||
Optionally, `hostname` specifies the IP address to listen at. Node.js listens on unspecified IPv6 address `::` by default. If `serviceHost` and `servicePort` specify a comma separated list, the proxy will perform load balancing on a round-robin basis. | ||
@@ -21,0 +21,0 @@ TLS can be enabled at the proxy port using the `tls` option. If followed by `both`, TLS is also used with the service. Use `pfx` option to specify server certificate, and `passphrase` to provide the password required to access it. |
@@ -10,4 +10,9 @@ #!/usr/bin/env node | ||
.option("-h, --hostname [name]", "Name or IP address of host") | ||
.option("-n, --serviceHost <name>", "Name or IP address of service host") | ||
.option("-s, --servicePort <number>", "Service port number", parseInt) | ||
.option("-n, --serviceHost <name>", | ||
"Name or IP address of service host(s); " + | ||
"if this is a comma separated list, " + | ||
"proxy performs round-robin load balancing") | ||
.option("-s, --servicePort <number>", "Service port number(s); " + | ||
"if this a comma separated list," + | ||
"it should have as many entries as serviceHost") | ||
.option("-q, --q", "Be quiet") | ||
@@ -33,5 +38,4 @@ .option("-t, --tls [both]", "Use TLS 1.2 with clients; " + | ||
const proxy = require("./tcp-proxy.js") | ||
.createProxy(argv.proxyPort, argv.serviceHost, | ||
argv.servicePort, options); | ||
const proxy = require("./tcp-proxy.js").createProxy(argv.proxyPort, | ||
argv.serviceHost, argv.servicePort, options); | ||
@@ -38,0 +42,0 @@ process.on("uncaughtException", function(err) { |
@@ -5,2 +5,7 @@ var net = require("net"); | ||
module.exports.createProxy = function(proxyPort, | ||
serviceHost, servicePort, options) { | ||
return new TcpProxy(proxyPort, serviceHost, servicePort, options); | ||
}; | ||
function uniqueKey(socket) { | ||
@@ -13,39 +18,44 @@ var key = socket.remoteAddress + ":" + socket.remotePort; | ||
this.proxyPort = proxyPort; | ||
this.serviceHost = serviceHost; | ||
this.servicePort = servicePort; | ||
this.serviceHosts = serviceHost.split(","); | ||
this.servicePorts = servicePort.split(","); | ||
this.serviceHostIndex = -1; | ||
if (options === undefined) { | ||
this.options = { | ||
quiet: false | ||
}; | ||
this.options = {quiet: false}; | ||
} else { | ||
this.options = options; | ||
} | ||
this.proxyTlsOptions = { | ||
passphrase: this.options.passphrase, | ||
secureProtocol: "TLSv1_2_method" | ||
}; | ||
if (this.options.tls !== false) { | ||
this.proxyTlsOptions.pfx = fs.readFileSync(this.options.pfx); | ||
} | ||
this.serviceTlsOptions = { | ||
rejectUnauthorized: this.options.rejectUnauthorized, | ||
secureProtocol: "TLSv1_2_method" | ||
}; | ||
this.proxySockets = {}; | ||
this.createProxy(); | ||
this.createListener(); | ||
} | ||
TcpProxy.prototype.createProxy = function() { | ||
const proxy = this; | ||
if (proxy.options.tls !== false) { | ||
var tlsOptions = { | ||
pfx: fs.readFileSync(proxy.options.pfx), | ||
passphrase: proxy.options.passphrase, | ||
secureProtocol: "TLSv1_2_method" | ||
}; | ||
proxy.server = tls.createServer(tlsOptions, function(socket) { | ||
proxy.handleClient(socket); | ||
TcpProxy.prototype.createListener = function() { | ||
const self = this; | ||
if (self.options.tls !== false) { | ||
self.server = tls.createServer(self.proxyTlsOptions, function(socket) { | ||
self.handleClient(socket); | ||
}); | ||
} else { | ||
proxy.server = net.createServer(function(socket) { | ||
proxy.handleClient(socket); | ||
self.server = net.createServer(function(socket) { | ||
self.handleClient(socket); | ||
}); | ||
} | ||
proxy.server.listen(proxy.proxyPort, proxy.options.hostname); | ||
self.server.listen(self.proxyPort, self.options.hostname); | ||
}; | ||
TcpProxy.prototype.handleClient = function(proxySocket) { | ||
const proxy = this; | ||
const self = this; | ||
var key = uniqueKey(proxySocket); | ||
proxy.proxySockets[key] = proxySocket; | ||
self.proxySockets[key] = proxySocket; | ||
var context = { | ||
@@ -56,3 +66,3 @@ buffers: [], | ||
}; | ||
proxy.createServiceSocket(context); | ||
self.createServiceSocket(context); | ||
proxySocket.on("data", function(data) { | ||
@@ -66,3 +76,3 @@ if (context.connected) { | ||
proxySocket.on("close", function(hadError) { | ||
delete proxy.proxySockets[uniqueKey(proxySocket)]; | ||
delete self.proxySockets[uniqueKey(proxySocket)]; | ||
context.serviceSocket.destroy(); | ||
@@ -73,17 +83,15 @@ }); | ||
TcpProxy.prototype.createServiceSocket = function(context) { | ||
const proxy = this; | ||
if (proxy.options.tls === "both") { | ||
context.serviceSocket = | ||
tls.connect(proxy.servicePort, proxy.serviceHost, { | ||
rejectUnauthorized: proxy.options.rejectUnauthorized, | ||
secureProtocol: "TLSv1_2_method" | ||
}, function() { | ||
proxy.writeBuffer(context); | ||
}); | ||
const self = this; | ||
var i = self.getServiceHostIndex(); | ||
if (self.options.tls === "both") { | ||
context.serviceSocket = tls.connect(self.servicePorts[i], | ||
self.serviceHosts[i], self.serviceTlsOptions, function() { | ||
self.writeBuffer(context); | ||
}); | ||
} else { | ||
context.serviceSocket = new net.Socket(); | ||
context.serviceSocket.connect(proxy.servicePort, proxy.serviceHost, | ||
function() { | ||
proxy.writeBuffer(context); | ||
}); | ||
context.serviceSocket.connect(self.servicePorts[i], | ||
self.serviceHosts[i], function() { | ||
self.writeBuffer(context); | ||
}); | ||
} | ||
@@ -101,2 +109,10 @@ context.serviceSocket.on("data", function(data) { | ||
TcpProxy.prototype.getServiceHostIndex = function() { | ||
this.serviceHostIndex++; | ||
if (this.serviceHostIndex == this.serviceHosts.length) { | ||
this.serviceHostIndex = 0; | ||
} | ||
return this.serviceHostIndex; | ||
}; | ||
TcpProxy.prototype.writeBuffer = function(context) { | ||
@@ -124,6 +140,1 @@ context.connected = true; | ||
}; | ||
module.exports.createProxy = function(proxyPort, | ||
serviceHost, servicePort, options) { | ||
return new TcpProxy(proxyPort, serviceHost, servicePort, options); | ||
}; |
13120
182