Пример #1
0
    def onConnect(self, request):
        # ----- init decryptor -----
        if not config.tun_ssl:
            if config.compatible:
                cookie = request.headers['cookie']
                if cookie.count(';') > 0:
                    raise ConnectionDeny(400)
                if not cookie.startswith(config.cookie_key + '='):
                    raise ConnectionDeny(400)
                nonceB64 = cookie.lstrip(config.cookie_key + '=')
            else:
                nonceB64 = request.headers['sec-websocket-key']
            try:
                nonce = base64.b64decode(nonceB64)
                self.initCipher(nonce, decryptor=True)
            except Exception as e:
                logging.error('failed to initialize cipher: %s' % e)
                raise ConnectionDeny(400)
        else:
            nonceB64 = nonce = None  # for decrypting

        # ----- extract header -----
        path = self.http_request_path
        try:
            if path.startswith(factory.path):
                path = path[len(factory.path):]
            dat = base64.urlsafe_b64decode(
                path[1:] if path.startswith('/') else path)
            cmd = ord(self.decrypt(dat[:1]))
            addr, port, remainData, timestamp = self.parseRelayHeader(dat)
            if cmd != self.CMD_REQ:
                raise ValueError('wrong command %s' % cmd)
        except (ValueError, Base64Error) as e:
            logging.error('invalid request: %s (from %s), path: %s' %
                          (e, self.peer, path))
            raise ConnectionDeny(400)

        if not config.tun_ssl:
            # filter replay attack
            seen = seenNonceByTime[timestamp // 10]
            if nonce in seen:
                logging.warning('replay attack detected (from %s)' % self.peer)
                raise ConnectionDeny(400)
            seen.add(nonce)

            if config.compatible:
                # avoid generating a new random nonce for encrypting, and client will do same
                # calculating to get this nonce
                encNonce = get_sha1(nonce)[:16]
            else:
                # repeat calculation in websocket library so that key in WS handshake reply
                # is the same as this one
                encNonce = get_sha1(
                    nonceB64.encode() +
                    b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")[:16]
            self.initCipher(encNonce, encryptor=True)

        self.tunOpen.set_result(None)
        self.connectTargetTask = async_(
            self.connectTarget(addr, port, remainData))
Пример #2
0
    def onConnect(self, request):
        self.clientInfo = '{0}:{1}'.format(*self.transport.get_extra_info('peername'))
        # ----- init decryptor -----
        if not config.tun_ssl:
            if config.compatible:
                cookie = request.headers['cookie']
                if cookie.count(';') > 0:
                    raise ConnectionDeny(400)
                if not cookie.startswith(config.cookie_key + '='):
                    raise ConnectionDeny(400)
                nonceB64 = cookie.lstrip(config.cookie_key + '=')
            else:
                nonceB64 = request.headers['sec-websocket-key']
            try:
                nonce = base64.b64decode(nonceB64)
                self.initCipher(nonce, decryptor=True)
            except Exception as e:
                logging.error('failed to initialize cipher: %s' % e)
                raise ConnectionDeny(400)
        else:
            nonceB64 = nonce = None  # for decrypting

        # ----- extract header -----
        try:
            dat = base64.urlsafe_b64decode(self.http_request_path[1:])
            cmd = ord(self.decrypt(dat[:1]))
            addr, port, remainData, timestamp = self.parseRelayHeader(dat)
            if cmd != self.CMD_REQ:
                raise ValueError('wrong command %s' % cmd)
        except (ValueError, Base64Error) as e:
            logging.error('invalid request: %s (from %s), path: %s' %
                          (e, self.clientInfo, self.http_request_path))
            raise ConnectionDeny(400)

        if not config.tun_ssl:
            # filter replay attack
            seen = seenNonceByTime[timestamp // 10]
            if nonce in seen:
                logging.warning('replay attack detected (from %s)' % self.clientInfo)
                raise ConnectionDeny(400)
            seen.add(nonce)

            if config.compatible:
                # avoid generating a new random nonce for encrypting, and client will do same
                # calculating to get this nonce
                encNonce = get_sha1(nonce)[:16]
            else:
                # repeat calculation in websocket library so that key in WS handshake reply
                # is the same as this one
                encNonce = get_sha1(nonceB64.encode() + b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")[:16]
            self.initCipher(encNonce, encryptor=True)

        self.tunOpen.set_result(None)
        self.connectTargetTask = async_(self.connectTarget(addr, port, remainData))
Пример #3
0
 def onOpen(self):
     self.tunOpen.set_result(None)
     self.lastIdleTime = time.time()
     if not config.debug:
         self.customUriPath = None  # save memory
     if not config.tun_ssl:
         if config.compatible:
             nonce = get_sha1(base64.b64decode(self.customWsKey))[:16]
         else:
             # SHA-1 has 20 bytes
             nonce = base64.b64decode(self.http_headers['sec-websocket-accept'])[:16]
         self.initCipher(nonce, decryptor=True)
Пример #4
0
 def onOpen(self):
     self.tunOpen.set_result(None)
     self.lastIdleTime = time.time()
     self.setAutoPing(self.TUN_AUTO_PING_INTERVAL,
                      self.TUN_AUTO_PING_TIMEOUT)
     if not config.debug:
         self.customUriPath = None  # save memory
     if not config.tun_ssl:
         if config.compatible:
             nonce = get_sha1(base64.b64decode(self.customWsKey))[:16]
         else:
             # SHA-1 has 20 bytes
             nonce = base64.b64decode(
                 self.http_headers['sec-websocket-accept'])[:16]
         self.initCipher(nonce, decryptor=True)
Пример #5
0
    def onOpen(self):
        self.tunOpen.set_result(None)
        now = time.time()
        self.lastIdleTime = now

        # measure RTT
        rtt = now - self.handshakeSentTime
        if WSTunClientProtocol.rtt is None:
            WSTunClientProtocol.rtt = rtt
        else:
            WSTunClientProtocol.rtt = 0.8 * WSTunClientProtocol.rtt + 0.2 * rtt

        assert not self._pushToTunTask
        self._pushToTunTask = async_(self._pushToTunnelLoop())
        self.setAutoPing(self.TUN_AUTO_PING_INTERVAL, self.TUN_AUTO_PING_TIMEOUT)
        if not config.debug:
            self.customUriPath = None  # save memory
        if not config.tun_ssl:
            if config.compatible:
                nonce = get_sha1(base64.b64decode(self.customWsKey))[:16]
            else:
                # SHA-1 has 20 bytes
                nonce = base64.b64decode(self.http_headers['sec-websocket-accept'])[:16]
            self.initCipher(nonce, decryptor=True)