Просмотр исходного кода

Merge pull request #5109 from overleaf/bg-fix-handshake-exception

fix handshake exception

GitOrigin-RevId: 917518ccac3f5fddf4029f1b1ec3e3806dde9a29
Brian Gough 5 лет назад
Родитель
Сommit
6cece12369

+ 18 - 9
services/real-time/app/js/WebsocketAddressManager.js

@@ -11,17 +11,26 @@ module.exports = class WebsocketAddressManager {
   }
 
   getRemoteIp(clientHandshake) {
-    if (this.trust) {
+    if (!clientHandshake) {
+      return 'client-handshake-missing'
+    } else if (this.trust) {
       // create a dummy req object using the client handshake and
       // connection.remoteAddress for the proxy-addr module to parse
-      const addressPort = clientHandshake.address
-      const req = Object.create(clientHandshake, {
-        connection: {
-          value: { remoteAddress: addressPort && addressPort.address },
-        },
-      })
-      // return the address parsed from x-forwarded-for
-      return proxyaddr(req, this.trust)
+      try {
+        const addressPort = clientHandshake.address
+        const req = {
+          headers: {
+            'x-forwarded-for':
+              clientHandshake.headers &&
+              clientHandshake.headers['x-forwarded-for'],
+          },
+          connection: { remoteAddress: addressPort && addressPort.address },
+        }
+        // return the address parsed from x-forwarded-for
+        return proxyaddr(req, this.trust)
+      } catch (err) {
+        return 'client-handshake-invalid'
+      }
     } else {
       // return the address from the client handshake itself
       return clientHandshake.address && clientHandshake.address.address

+ 100 - 0
services/real-time/test/unit/js/WebsocketAddressManagerTests.js

@@ -0,0 +1,100 @@
+const SandboxedModule = require('sandboxed-module')
+const { expect } = require('chai')
+const modulePath = require('path').join(
+  __dirname,
+  '../../../app/js/WebsocketAddressManager'
+)
+
+describe('WebsocketAddressManager', function () {
+  beforeEach(function () {
+    this.WebsocketAddressManager = SandboxedModule.require(modulePath, {
+      requires: {},
+    })
+  })
+
+  describe('with a proxy configuration', function () {
+    beforeEach(function () {
+      this.websocketAddressManager = new this.WebsocketAddressManager(
+        true,
+        '127.0.0.1'
+      )
+    })
+
+    it('should return the client ip address when behind a proxy', function () {
+      expect(
+        this.websocketAddressManager.getRemoteIp({
+          headers: {
+            'x-forwarded-proto': 'https',
+            'x-forwarded-for': '123.45.67.89',
+          },
+          address: { address: '127.0.0.1' },
+        })
+      ).to.equal('123.45.67.89')
+    })
+
+    it('should return the client ip address for a direct connection', function () {
+      expect(
+        this.websocketAddressManager.getRemoteIp({
+          headers: {},
+          address: { address: '123.45.67.89' },
+        })
+      ).to.equal('123.45.67.89')
+    })
+
+    it('should return the client ip address when there are no headers in the handshake', function () {
+      expect(
+        this.websocketAddressManager.getRemoteIp({
+          address: { address: '123.45.67.89' },
+        })
+      ).to.equal('123.45.67.89')
+    })
+
+    it('should return a "client-handshake-missing" response when the handshake is missing', function () {
+      expect(this.websocketAddressManager.getRemoteIp()).to.equal(
+        'client-handshake-missing'
+      )
+    })
+  })
+
+  describe('without a proxy configuration', function () {
+    beforeEach(function () {
+      this.websocketAddressManager = new this.WebsocketAddressManager(false)
+    })
+
+    it('should return the client ip address for a direct connection', function () {
+      expect(
+        this.websocketAddressManager.getRemoteIp({
+          headers: {},
+          address: { address: '123.45.67.89' },
+        })
+      ).to.equal('123.45.67.89')
+    })
+
+    it('should return undefined if the client ip address is not present', function () {
+      expect(
+        this.websocketAddressManager.getRemoteIp({
+          headers: {},
+          address: { otherAddressProperty: '123.45.67.89' },
+        })
+      ).to.be.undefined
+    })
+
+    it('should return the proxy ip address if there is actually a proxy', function () {
+      expect(
+        this.websocketAddressManager.getRemoteIp({
+          headers: {
+            'x-forwarded-proto': 'https',
+            'x-forwarded-for': '123.45.67.89',
+          },
+          address: { address: '127.0.0.1' },
+        })
+      ).to.equal('127.0.0.1')
+    })
+
+    it('should return a "client-handshake-missing" response when the handshake is missing', function () {
+      expect(this.websocketAddressManager.getRemoteIp()).to.equal(
+        'client-handshake-missing'
+      )
+    })
+  })
+})