def create_key(cls, user, client_pkey, klen): if cls.notvalid(user, client_pkey): return 0, 0 if len(cls.userpkeys[user]) > 3: cls.del_key(cls.userpkeys[user][0]) dh = ECC(klen) shared_secret = dh.get_dh_key(client_pkey) client_pkey = hashlib.md5(client_pkey).digest() cls.userpkeys[user].append(client_pkey) cls.pkeyuser[client_pkey] = user cls.pkeykey[client_pkey] = shared_secret cls.pkeytime[client_pkey] = time.time() return dh.get_pub_key(), USER_PASS[user]
def main(): logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S', filemode='a+') hello = 'hxsocks-server %s' % __version__ if gevent: hello += ' with gevent %s' % gevent.__version__ print(hello) print('by v3aqb') global SERVER_CERT try: SERVER_CERT = ECC(from_file=os.path.join( os.path.dirname(os.path.abspath(__file__)), 'cert.pem')) except: logging.warning('server cert not found, creating...') SERVER_CERT = ECC(key_len=32) SERVER_CERT.save( os.path.join(os.path.dirname(os.path.abspath(__file__)), 'cert.pem')) servers = ['hxs://0.0.0.0:9000'] forward = [] if os.path.exists( os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.json')): global USER_PASS d = json.loads( open( os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.json')).read()) USER_PASS = d['users'] servers = d['servers'] forward = d.get('forward', []) for s in servers: logging.info('starting server: %s' % s) ssserver = HXSocksServer(s, forward, HXSocksHandler) threading.Thread(target=ssserver.serve_forever).start()
def getKey(self): with newkey_lock[self.serverid]: if self.serverid not in keys: for _ in range(2): logger.debug('hxsocks getKey') host, port, usn, psw = (self.hxsServer.hostname, self.hxsServer.port, self.hxsServer.username, self.hxsServer.password) if self._sock is None: logger.debug('hxsocks connect') from connection import create_connection self._sock = create_connection( (host, port), self.timeout, parentproxy=self.parentproxy, tunnel=True) self.pskcipher = encrypt.Encryptor( self.PSK, self.method) self._rfile = self._sock.makefile('rb') self._header_sent = False self._header_received = False acipher = ECC(self.pskcipher.key_len) pubk = acipher.get_pub_key() logger.debug('hxsocks send key exchange request') ts = struct.pack('>I', int(time.time())) padding_len = random.randint(64, 255) data = b''.join([ ts, chr(len(pubk)).encode('latin1'), pubk, hmac.new(psw.encode(), ts + pubk + usn.encode(), hashlib.sha256).digest(), b'\x00' * padding_len ]) data = chr(10).encode() + struct.pack('>H', len(data)) + data self._sock_sendall(self.pskcipher.encrypt(data)) resp_len = 2 if self.pskcipher.decipher else self.pskcipher.iv_len + 2 resp_len = self.pskcipher.decrypt( self._rfile_read(resp_len)) resp_len = struct.unpack('>H', resp_len)[0] data = self.pskcipher.decrypt(self._rfile_read(resp_len)) data = io.BytesIO(data) resp_code = byte2int(data.read(1)) if resp_code == 0: logger.debug('hxsocks read key exchange respond') pklen = byte2int(data.read(1)) scertlen = byte2int(data.read(1)) siglen = byte2int(data.read(1)) server_key = data.read(pklen) auth = data.read(32) server_cert = data.read(scertlen) signature = data.read(siglen) # TODO: ask user if a certificate should be accepted or not. if host not in known_hosts: logger.info( 'hxs: server %s new cert %s saved.' % (host, hashlib.sha256(server_cert).hexdigest()[:8])) with open('./.hxs_known_hosts/' + host + '.cert', 'wb') as f: f.write(server_cert) known_hosts[host] = server_cert elif known_hosts[host] != server_cert: logger.error( 'hxs: server %s certificate mismatch! PLEASE CHECK!' % host) raise OSError(0, 'hxs: bad certificate') if auth == hmac.new(psw.encode(), pubk + server_key + usn.encode(), hashlib.sha256).digest(): if ECC.verify_with_pub_key(server_cert, auth, signature, self.hash_algo): shared_secret = acipher.get_dh_key(server_key) keys[self.serverid] = ( hashlib.md5(pubk).digest(), shared_secret) self.cipher = encrypt.AEncryptor( keys[self.serverid][1], self.method, SALT, CTX, 0, MAC_LEN) logger.debug('hxs key exchange success') return else: logger.error( 'hxs getKey Error: server auth failed, bad signature' ) else: logger.error( 'hxs getKey Error: server auth failed, bad username or password' ) else: logger.error( 'hxs getKey Error. bad password or timestamp.') else: raise IOError(0, 'hxs getKey Error') else: self.cipher = encrypt.AEncryptor(keys[self.serverid][1], self.method, SALT, CTX, 0, MAC_LEN)
def getKey(self): logger.debug('hxsocks2 getKey') host, port, usn, psw = (self.hxsServer.hostname, self.hxsServer.port, self.hxsServer.username, self.hxsServer.password) logger.debug('hxsocks2 connect to server') from connection import create_connection self._sock = create_connection((host, port), self.timeout, parentproxy=self.parentproxy, tunnel=True) self._rfile = self._sock.makefile('rb') acipher = ECC(self.__pskcipher._key_len) pubk = acipher.get_pub_key() logger.debug('hxsocks2 send key exchange request') ts = int(time.time()) // 30 ts = struct.pack('>I', ts) padding_len = random.randint(64, 255) data = b''.join([chr(len(pubk)).encode('latin1'), pubk, hmac.new(psw.encode(), ts + pubk + usn.encode(), hashlib.sha256).digest(), b'\x00' * padding_len]) data = chr(20).encode() + struct.pack('>H', len(data)) + data ct = self.__pskcipher.encrypt(data) self._sock.sendall(ct) self.__pskcipher.decrypt(self._rfile.read(self.__pskcipher._iv_len)) if encrypt.is_aead(self.method): ct_len = self.__pskcipher.decrypt(self._rfile.read(18)) ct_len, = struct.unpack('!H', ct_len) ct = self.__pskcipher.decrypt(self._rfile.read(ct_len + 16)) data = ct[2:] else: resp_len = self.__pskcipher.decrypt(self._rfile.read(2)) resp_len, = struct.unpack('>H', resp_len) data = self.__pskcipher.decrypt(self._rfile.read(resp_len)) data = io.BytesIO(data) resp_code = byte2int(data.read(1)) if resp_code == 0: logger.debug('hxsocks read key exchange respond') pklen = byte2int(data.read(1)) scertlen = byte2int(data.read(1)) siglen = byte2int(data.read(1)) server_key = data.read(pklen) auth = data.read(32) server_cert = data.read(scertlen) signature = data.read(siglen) # TODO: ask user if a certificate should be accepted or not. server_id = '%s_%d' % (host, port) if server_id not in known_hosts: logger.info('hxs: server %s new cert %s saved.' % (server_id, hashlib.sha256(server_cert).hexdigest()[:8])) with open('./.hxs_known_hosts/' + server_id + '.cert', 'wb') as f: f.write(server_cert) known_hosts[server_id] = server_cert elif known_hosts[server_id] != server_cert: logger.error('hxs: server %s certificate mismatch! PLEASE CHECK!' % server_id) raise OSError(0, 'hxs: bad certificate') if auth == hmac.new(psw.encode(), pubk + server_key + usn.encode(), hashlib.sha256).digest(): if ECC.verify_with_pub_key(server_cert, auth, signature, self.hash_algo): shared_secret = acipher.get_dh_key(server_key) logger.debug('hxs key exchange success') self.__cipher = AEncryptor(shared_secret, self.method, CTX) return else: logger.error('hxs getKey Error: server auth failed, bad signature') else: logger.error('hxs getKey Error: server auth failed, bad username or password') else: logger.error('hxs getKey Error. bad password or timestamp.') raise OSError(0, 'hxs getKey Error')