Beispiel #1
0
    def parse_udp_msg(self, *msg):
        """
        Return (main_pw, sha1, num, port, ip, [certs_str or None]).

        `certs_str` is available only when ptproxy is enabled.

        The message should be
            (
                required_connection_number (HEX, 2 bytes) +
                    used_remote_listening_port (HEX, 4 bytes) +
                    sha1(cert_pub),
                pyotp.TOTP(pri_sha1 + ip_in_hex_form + salt),   # TODO: client identity must be checked
                main_pw,
                ip_in_hex_form,
                salt,
                [cert1,
                cert2   (only when obfs4 is enabled)],
                [some random string (only when meek is enabled)],
                type + version
            )
        """

        assert len(msg[0]) == 48  # 2 + 4 + 40 + 2

        if msg[4] in self.recentsalt:
            raise BlacklistReq
        num_hex, port_hex, client_sha1 = msg[0][:2], msg[0][2:6], msg[0][6:46]
        h = hashlib.sha256()
        cert = self.certs_db.query(client_sha1)
        if cert is None:
            raise CorruptedReq
        h.update(cert[1] + msg[3] + msg[4] + num_hex)
        assert msg[1] == pyotp.TOTP(h.hexdigest()).now()
        if msg[3][-1:] != 'G':
            remote_ip = str(ipaddress.ip_address(int(msg[3], 36)))
        else:
            remote_ip = str(ipaddress.IPv6Address(int(msg[3][:-1], 36)))
        main_pw = binascii.unhexlify(msg[2])
        number = int(num_hex, 16)
        if number <= 0:
            raise CorruptedReq
        remote_port = int(port_hex, 16)
        if len(self.recentsalt) >= MAX_SALT_BUFFER:
            self.recentsalt.pop(0)
        self.recentsalt.append(msg[4])
        if (client_sha1 + main_pw) in self.blacklist:
            raise BlacklistReq
        if number > MAX_CONN_PER_CLIENT:
            raise IllegalReq

        if 1 <= self.obfs_level <= 2:
            # obfs4 enabled
            certs_original = msg[5] + msg[6]
            certs_original += '=' * ((160 - len(certs_original)) % 4)
            certs_str = urlsafe_b64_short_decode(certs_original)
        else:
            assert msg[5][:2] == "0001"
            certs_str = None
        signature_to_client = int2base(self.pri.sign(main_pw, None)[0])
        return main_pw, client_sha1, number, remote_port, remote_ip, certs_str, signature_to_client
Beispiel #2
0
    def parse_udp_msg(self, *msg):
        """
        Return (main_pw, sha1, num, port, ip, [certs_str or None]).

        `certs_str` is available only when ptproxy is enabled.

        The message should be
            (
                required_connection_number (HEX, 2 bytes) +
                    used_remote_listening_port (HEX, 4 bytes) +
                    sha1(cert_pub),
                pyotp.TOTP(pri_sha1 + ip_in_hex_form + salt),   # TODO: client identity must be checked
                main_pw,
                ip_in_hex_form,
                salt,
                [cert1,
                cert2   (only when obfs4 is enabled)],
                [some random string (only when meek is enabled)]
            )
        """

        assert len(msg[0]) == 46    # 2 + 4 + 40

        if msg[4] in self.recentsalt:
            return None

        num_hex, port_hex, client_sha1 = msg[0][:2], msg[0][2:6], msg[0][6:46]
        h = hashlib.sha256()
        h.update(self.certs[client_sha1][1] + msg[3] + msg[4] + num_hex)
        assert msg[1] == pyotp.TOTP(h.hexdigest()).now()
        if msg[3][-1:] != 'G':
            remote_ip = str(ipaddress.ip_address(int(msg[3], 36)))
        else:
            remote_ip = str(ipaddress.IPv6Address(int(msg[3][:-1], 36)))
        main_pw = binascii.unhexlify(msg[2])
        number = int(num_hex, 16)
        remote_port = int(port_hex, 16)
        if len(self.recentsalt) >= MAX_SALT_BUFFER:
            self.recentsalt.pop(0)
        self.recentsalt.append(msg[4])

        if 1 <= self.obfs_level <= 2:
            # obfs4 enabled
            certs_original = msg[5] + msg[6]
            certs_original += '=' * ((160 - len(certs_original)) % 4)
            certs_str = urlsafe_b64_short_decode(certs_original)
        else:
            certs_str = None

        return main_pw, client_sha1, number, remote_port, remote_ip, certs_str
Beispiel #3
0
    def parse_udp_msg(self, *msg):
        """
        Return (main_pw, sha1, num, port, ip, [certs_str or None]).

        `certs_str` is available only when ptproxy is enabled.

        The message should be
            (
                required_connection_number (HEX, 2 bytes) +
                    used_remote_listening_port (HEX, 4 bytes) +
                    sha1(cert_pub),
                pyotp.TOTP(pri_sha1 + ip_in_hex_form + salt),   # TODO: client identity must be checked
                main_pw,
                ip_in_hex_form,
                salt,
                [cert1,
                cert2   (only when obfs4 is enabled)],
                [some random string (only when meek is enabled)],
                type + version
            )
        """

        assert len(msg[0]) == 48    # 2 + 4 + 40 + 2

        if msg[4] in self.recentsalt:
            raise BlacklistReq
        num_hex, port_hex, client_sha1 = msg[0][
            :2], msg[0][2:6], msg[0][6:46]
        h = hashlib.sha256()
        cert = self.certs_db.query(client_sha1)
        if cert is None:
            raise CorruptedReq
        h.update(cert[1] + msg[3] + msg[4] + num_hex)
        assert msg[1] == pyotp.TOTP(h.hexdigest()).now()
        if msg[3][-1:] != 'G':
            remote_ip = str(ipaddress.ip_address(int(msg[3], 36)))
        else:
            remote_ip = str(ipaddress.IPv6Address(int(msg[3][:-1], 36)))
        main_pw = binascii.unhexlify(msg[2])
        number = int(num_hex, 16)
        if number <= 0:
            raise CorruptedReq
        remote_port = int(port_hex, 16)
        if len(self.recentsalt) >= MAX_SALT_BUFFER:
            self.recentsalt.pop(0)
        self.recentsalt.append(msg[4])
        if (client_sha1 + main_pw) in self.blacklist:
            raise BlacklistReq
        if number > MAX_CONN_PER_CLIENT:
            raise IllegalReq

        if 1 <= self.obfs_level <= 2:
            # obfs4 enabled
            certs_original = msg[5] + msg[6]
            certs_original += '=' * ((160 - len(certs_original)) % 4)
            certs_str = urlsafe_b64_short_decode(certs_original)
        else:
            assert msg[5][:2] == "0001"
            certs_str = None
        signature_to_client = int2base(self.pri.sign(main_pw, None)[0])
        return main_pw, client_sha1, number, remote_port, remote_ip, certs_str, signature_to_client