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
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
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