Only listen on loopback interfaces (#3666)

* https-proxy, server: only listen on loopback for ipv4/v6

* server: use supplied port

* https-proxy, server: remove ::1 listener

* server: add test that all servers only listen on lo, not other interfaces
This commit is contained in:
Zach Bloomquist
2019-03-15 01:01:50 -04:00
committed by Brian Mann
parent 9b8d4c2810
commit 19a63a0f25
4 changed files with 39 additions and 10 deletions

View File

@@ -164,7 +164,7 @@ class Server
@_sniServer.on "upgrade", @_onUpgrade.bind(@, options.onUpgrade)
@_sniServer.on "request", @_onRequest.bind(@, options.onRequest)
@_sniServer.listen =>
@_sniServer.listen 0, '127.0.0.1', =>
## store the port of our current sniServer
@_sniPort = @_sniServer.address().port

View File

@@ -40,7 +40,7 @@ module.exports = {
allowDestroy(srv)
srv.listen ->
srv.listen 0, '127.0.0.1', ->
resolve({
port: ->
srv.address().port
@@ -50,5 +50,5 @@ module.exports = {
close: ->
srv.destroyAsync()
})
})
}

View File

@@ -255,20 +255,17 @@ class Server
_listen: (port, onError) ->
new Promise (resolve) =>
listener = =>
port = @_server.address().port
address = @_server.address()
@isListening = true
debug("Server listening on port %s", port)
debug("Server listening on ", address)
@_server.removeListener "error", onError
resolve(port)
resolve(address.port)
## nuke port from our args if its falsy
args = _.compact([port, listener])
@_server.listen.apply(@_server, args)
@_server.listen(port || 0, '127.0.0.1', listener)
_getRemoteState: ->
# {

View File

@@ -1,6 +1,7 @@
require("../spec_helper")
_ = require("lodash")
os = require("os")
http = require("http")
express = require("express")
Promise = require("bluebird")
@@ -29,6 +30,7 @@ describe "lib/server", ->
@config = cfg
@server = Server()
@oldFileServer = @server._fileServer
@server._fileServer = @fileServer
afterEach ->
@@ -114,6 +116,36 @@ describe "lib/server", ->
.spread (port) =>
expect(port).to.eq(@port)
it "all servers listen only on localhost and no other interface", ->
fileServer.create.restore()
@server._fileServer = @oldFileServer
interfaces = _.flatten(_.values(os.networkInterfaces()))
nonLoopback = interfaces.find (iface) =>
iface.family == "IPv4" && iface.address != "127.0.0.1"
## verify that we can connect to `port` over loopback
## and not over another configured IPv4 address
tryOnlyLoopbackConnect = (port) =>
Promise.all([
connect.byPortAndAddress(port, "127.0.0.1")
connect.byPortAndAddress(port, nonLoopback)
.then ->
throw new Error("Shouldn't be able to connect on #{nonLoopback.address}:#{port}")
.catch { errno: "ECONNREFUSED" }, ->
])
@server.createServer(@app, {})
.spread (port) =>
Promise.map(
[
port
@server._fileServer.port()
@server._httpsProxy._sniPort
],
tryOnlyLoopbackConnect
)
it "resolves with warning if cannot connect to baseUrl", ->
sinon.stub(connect, "ensureUrl").rejects()
@server.createServer(@app, {port: @port, baseUrl: "http://localhost:#{@port}"})