def pack_auth_data(self, auth_data, buf): if len(buf) == 0: return b'' if len(buf) > 400: rnd_len = struct.unpack('<H', os.urandom(2))[0] % 512 else: rnd_len = struct.unpack('<H', os.urandom(2))[0] % 1024 data = auth_data data_len = 7 + 4 + 16 + 4 + len(buf) + rnd_len + 4 data = data + struct.pack('<H', data_len) + struct.pack('<H', rnd_len) mac_key = self.server_info.iv + self.server_info.key uid = os.urandom(4) if b':' in to_bytes(self.server_info.protocol_param): try: items = to_bytes(self.server_info.protocol_param).split(b':') self.user_key = self.hashfunc(items[1]).digest() uid = struct.pack('<I', int(items[0])) except: pass if self.user_key is None: self.user_key = self.server_info.key encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(self.user_key)) + self.salt, 'aes-128-cbc', b'\x00' * 16) data = uid + encryptor.encrypt(data)[16:] data += hmac.new(mac_key, data, self.hashfunc).digest()[:4] check_head = os.urandom(1) check_head += hmac.new(mac_key, check_head, self.hashfunc).digest()[:6] data = check_head + data + os.urandom(rnd_len) + buf data += hmac.new(self.user_key, data, self.hashfunc).digest()[:4] return data
def client_udp_pre_encrypt(self, buf): if self.user_key is None: if b':' in to_bytes(self.server_info.protocol_param): try: items = to_bytes( self.server_info.protocol_param).split(':') self.user_key = self.hashfunc(items[1]).digest() self.user_id = struct.pack('<I', int(items[0])) except: pass if self.user_key is None: self.user_id = os.urandom(4) self.user_key = self.server_info.key authdata = os.urandom(3) mac_key = self.server_info.key md5data = hmac.new(mac_key, authdata, self.hashfunc).digest() uid = struct.unpack('<I', self.user_id)[0] ^ struct.unpack( '<I', md5data[:4])[0] uid = struct.pack('<I', uid) rand_len = self.udp_rnd_data_len(md5data, self.random_client) encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(self.user_key)) + to_bytes(base64.b64encode(md5data)), 'rc4') out_buf = encryptor.encrypt(buf) buf = out_buf + os.urandom(rand_len) + authdata + uid return buf + hmac.new(self.user_key, buf, self.hashfunc).digest()[:1]
def decrypt_data(data): if g.config.encrypt_data: if isinstance(data, memoryview): data = data.tobytes() return encrypt.Encryptor(g.config.encrypt_password, g.config.encrypt_method).decrypt(data) else: return data
def handle(self): try: self.encryptor = encrypt.Encryptor(self.server.key, self.server.method) sock = self.connection iv_len = self.encryptor.iv_len() if iv_len: self.decrypt(sock.recv(iv_len)) addrtype = ord(self.decrypt(sock.recv(1))) if addrtype == 1: addr = socket.inet_ntoa(self.decrypt(self.rfile.read(4))) elif addrtype == 3: addr = self.decrypt( self.rfile.read(ord(self.decrypt(sock.recv(1))))) elif addrtype == 4: addr = socket.inet_ntop(socket.AF_INET6, self.decrypt(self.rfile.read(16))) else: # not supported logging.warn('addr_type not supported, maybe wrong password') return port = struct.unpack('>H', self.decrypt(self.rfile.read(2))) try: logging.info('connecting %s:%d' % (addr, port[0])) remote = socket.create_connection((addr, port[0])) except socket.error, e: # Connection refused logging.warn(e) return self.handle_tcp(sock, remote)
def __init__(self, server, fd_to_handlers, loop, local_sock, config, dns_resolver, is_local): self._server = server self._fd_to_handlers = fd_to_handlers self._loop = loop self._local_sock = local_sock self._remote_sock = None self._config = config self._dns_resolver = dns_resolver self._is_local = is_local self._stage = STAGE_INIT self._encryptor = encrypt.Encryptor(config['password'], config['method']) self._fastopen_connected = False self._data_to_write_to_local = [] self._data_to_write_to_remote = [] self._upstream_status = WAIT_STATUS_READING self._downstream_status = WAIT_STATUS_INIT self._client_address = local_sock.getpeername()[:2] self._remote_address = None if is_local: self._chosen_server = self._get_a_server() fd_to_handlers[local_sock.fileno()] = self local_sock.setblocking(False) local_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) loop.add(local_sock, eventloop.POLL_IN | eventloop.POLL_ERR) self.last_activity = 0 self._update_activity()
def handle(self): try: self.encryptor = encrypt.Encryptor(KEY, METHOD) sock = self.connection sock.recv(262) sock.send("\x05\x00") data = self.rfile.read(4) or '\x00' * 4 mode = ord(data[1]) if mode != 1: logging.warn('mode != 1') return addrtype = ord(data[3]) addr_to_send = data[3] print addrtype if addrtype == 1: addr_ip = self.rfile.read(4) addr = socket.inet_ntoa(addr_ip) addr_to_send += addr_ip elif addrtype == 3: addr_len = self.rfile.read(1) addr = self.rfile.read(ord(addr_len)) addr_to_send += addr_len + addr elif addrtype == 4: addr_ip = self.rfile.read(16) addr = socket.inet_ntop(socket.AF_INET6, addr_ip) addr_to_send += addr_ip else: logging.warn('addr_type not support') # not support return addr_port = self.rfile.read(2) addr_to_send += addr_port port = struct.unpack('>H', addr_port) try: reply = "\x05\x00\x00\x01" reply += socket.inet_aton('0.0.0.0') + struct.pack(">H", 2222) self.wfile.write(reply) # reply immediately if '-6' in sys.argv[1:]: remote = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) remote.connect((SERVER, REMOTE_PORT, 0, 0)) else: remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) remote.connect((SERVER, REMOTE_PORT)) self.send_encrypt(remote, addr_to_send) logging.info('connecting %s:%d' % (addr, port[0])) except socket.error, e: logging.warn(e) return self.handle_tcp(sock, remote)
def _connect(self): self.connected = 0 self.getKey() if self._sock is None: from connection import create_connection host, port = self.hxsServer.hostname, self.hxsServer.port self._sock = create_connection((host, port), self.timeout, parentproxy=self.parentproxy, tunnel=True) self.pskcipher = encrypt.Encryptor(self.PSK, self.method)
def pack_auth_data(self, auth_data, buf): data = auth_data data_len = 12 + 4 + 16 + 4 data = data + (struct.pack('<H', self.server_info.overhead) + struct.pack('<H', 0)) mac_key = self.server_info.iv + self.server_info.key check_head = os.urandom(4) self.last_client_hash = hmac.new(mac_key, check_head, self.hashfunc).digest() check_head += self.last_client_hash[:8] if b':' in to_bytes(self.server_info.protocol_param): try: items = to_bytes(self.server_info.protocol_param).split(b':') self.user_key = items[1] uid = struct.pack('<I', int(items[0])) except: uid = os.urandom(4) else: uid = os.urandom(4) if self.user_key is None: self.user_key = self.server_info.key encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(self.user_key)) + self.salt, 'aes-128-cbc', b'\x00' * 16) uid = struct.unpack('<I', uid)[0] ^ struct.unpack( '<I', self.last_client_hash[8:12])[0] uid = struct.pack('<I', uid) data = uid + encryptor.encrypt(data)[16:] self.last_server_hash = hmac.new(self.user_key, data, self.hashfunc).digest() data = check_head + data + self.last_server_hash[:4] self.encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(self.user_key)) + to_bytes(base64.b64encode(self.last_client_hash)), 'rc4') return data + self.pack_client_data(buf)
def client_udp_post_decrypt(self, buf): if len(buf) <= 8: return (b'', None) if hmac.new(self.user_key, buf[:-1], self.hashfunc).digest()[:1] != buf[-1:]: return (b'', None) mac_key = self.server_info.key md5data = hmac.new(mac_key, buf[-8:-1], self.hashfunc).digest() rand_len = self.udp_rnd_data_len(md5data, self.random_server) encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(self.user_key)) + to_bytes(base64.b64encode(md5data)), 'rc4') return encryptor.decrypt(buf[:-8 - rand_len])
def connect(self, address): self._address = address self.getKey() if self._sock is None: from connection import create_connection host, port = self.hxsServer.hostname, self.hxsServer.port 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 logger.debug('hxsocks send connect request') padding_len = random.randint(64, 255) pt = b''.join([ struct.pack('>I', int(time.time())), chr(len(self._address[0])).encode('latin1'), self._address[0].encode(), struct.pack('>H', self._address[1]), b'\x00' * padding_len ]) ct, mac = self.cipher.encrypt(pt) self._sock_sendall( self.pskcipher.encrypt(b''.join([ chr(11).encode(), keys[self.serverid][0], struct.pack('>H', len(ct)) ])) + ct + mac) resp_len = 2 if self.pskcipher.decipher else self.pskcipher.iv_len + 2 data = self._rfile_read(resp_len) if not data: raise IOError(0, 'hxsocks Error: connection closed.') resp_len = self.pskcipher.decrypt(data) resp_len = struct.unpack('>H', resp_len)[0] resp = self.pskcipher.decrypt(self._rfile_read(resp_len)) d = byte2int(resp) if resp else None if d == 0: logger.debug('hxsocks connected') self.readable = 1 self.writeable = 1 return elif d == 2: raise IOError(0, 'hxsocks Error: remote connect timed out. code 2') else: if self.serverid in keys: del keys[self.serverid] raise IOError(0, 'hxsocks Error: invalid shared key. code %d' % d)
def __init__(self): self.server = config['server'] self.server_port = config['server_port'] self.timeout = config['timeout'] self.data_to_send = [] self.state = STATE_INITIAL self.buf = "" self.supportedAuthMechs = [AUTHMECH_ANON, AUTHMECH_USERPASS] self.supportedAddrs = [ADDR_IPV4, ADDR_DOMAINNAME] self.enabledCommands = [CMD_CONNECT, CMD_UDPASSOC] self.peersock = None self.addressType = 0 self.requestType = 0 self.encryptor = encrypt.Encryptor(config['password'], config['method'])
def handle(self): KEY = self.server.config.get("password") METHOD = self.server.config.get("method") REMOTE_PORT = self.server.config.get("server_port") SERVER = self.server.config.get("server") try: self.encryptor = encrypt.Encryptor(KEY, METHOD) sock = self.connection sock.recv(262) sock.send("\x05\x00") data = self.rfile.read(4) or '\x00' * 4 mode = ord(data[1]) if mode != 1: logging.warn('mode != 1') return addrtype = ord(data[3]) addr_to_send = data[3] if addrtype == 1: addr_ip = self.rfile.read(4) addr = socket.inet_ntoa(addr_ip) addr_to_send += addr_ip elif addrtype == 3: addr_len = self.rfile.read(1) addr = self.rfile.read(ord(addr_len)) addr_to_send += addr_len + addr elif addrtype == 4: addr_ip = self.rfile.read(16) addr = socket.inet_ntop(socket.AF_INET6, addr_ip) addr_to_send += addr_ip else: logging.warn('addr_type not support') # not support return addr_port = self.rfile.read(2) addr_to_send += addr_port port = struct.unpack('>H', addr_port) try: reply = "\x05\x00\x00\x01" reply += socket.inet_aton('0.0.0.0') + struct.pack(">H", 2222) self.wfile.write(reply) # reply immediately remote = socket.create_connection((SERVER, REMOTE_PORT)) self.send_encrypt(remote, addr_to_send) logging.debug('connecting %s:%d' % (addr, port[0])) except socket.error, e: logging.warn(e) return self.handle_tcp(sock, remote)
def __init__(self, server, fd_to_handlers, loop, local_sock, config, dns_resolver, is_local): self._server = server self._fd_to_handlers = fd_to_handlers self._loop = loop self._local_sock = local_sock self._remote_sock = None self._config = config self._dns_resolver = dns_resolver # TCP Relay works as either sslocal or ssserver # if is_local, this is sslocal self._is_local = is_local self._stage = STAGE_INIT self._encryptor = encrypt.Encryptor(config['password'], config['method']) if 'one_time_auth' in config and config['one_time_auth']: self._ota_enable = True else: self._ota_enable = False self._ota_buff_head = b'' self._ota_buff_data = b'' self._ota_len = 0 self._ota_chunk_idx = 0 self._fastopen_connected = False self._data_to_write_to_local = [] self._data_to_write_to_remote = [] # upstream 数据从client->sserver->web,为WRITING输出到remote_sock,为READING读取local_sock self._upstream_status = WAIT_STATUS_READING # downstream 数据从web->ssserver->client,为WRITTING输出到local_sock,为READING读取remote_sock self._downstream_status = WAIT_STATUS_INIT self._client_address = local_sock.getpeername()[:2] self._remote_address = None if 'forbidden_ip' in config: self._forbidden_iplist = config['forbidden_ip'] else: self._forbidden_iplist = None if is_local: self._chosen_server = self._get_a_server() fd_to_handlers[local_sock.fileno()] = self # 注册socket local_sock.setblocking(False) local_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) # 添加到事件循环loop loop.add(local_sock, eventloop.POLL_IN | eventloop.POLL_ERR, self._server) self.last_activity = 0 # 上一次活动的时间 # 下面的函数就是更新这个变量 self._update_activity()
def connect(self, address): self.__address = address sshost, ssport, ssmethod, sspassword = (self.ssServer.hostname, self.ssServer.port, self.ssServer.username.lower(), self.ssServer.password) from connection import create_connection if ssmethod.endswith('-auth'): self.__ota = True ssmethod = ssmethod[:-5] self._sock = create_connection((sshost, ssport), self.timeout, parentproxy=self.parentproxy, tunnel=True) self._rfile = self._sock.makefile('rb') self.crypto = encrypt.Encryptor(sspassword, ssmethod)
def server_udp_pre_encrypt(self, buf, uid): if uid in self.server_info.users: user_key = self.server_info.users[uid] else: uid = None if not self.server_info.users: user_key = self.server_info.key else: user_key = self.server_info.recv_iv authdata = os.urandom(7) mac_key = self.server_info.key md5data = hmac.new(mac_key, authdata, self.hashfunc).digest() rand_len = self.udp_rnd_data_len(md5data, self.random_server) encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(user_key)) + to_bytes(base64.b64encode(md5data)), 'rc4') out_buf = encryptor.encrypt(buf) buf = out_buf + os.urandom(rand_len) + authdata return buf + hmac.new(user_key, buf, self.hashfunc).digest()[:1]
def handle(self): try: self.encryptor = encrypt.Encryptor(self.server.key, self.server.method) sock = self.connection sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) iv_len = self.encryptor.iv_len() data = sock.recv(iv_len) if iv_len > 0 and not data: sock.close() return if iv_len: self.decrypt(data) data = sock.recv(1) if not data: sock.close() return addrtype = ord(self.decrypt(data)) if addrtype == 1: addr = socket.inet_ntoa(self.decrypt(self.rfile.read(4))) elif addrtype == 3: addr = self.decrypt( self.rfile.read(ord(self.decrypt(sock.recv(1))))) elif addrtype == 4: addr = socket.inet_ntop(socket.AF_INET6, self.decrypt(self.rfile.read(16))) else: # not supported logging.warn('addr_type not supported, maybe wrong password') return port = struct.unpack('>H', self.decrypt(self.rfile.read(2))) try: logging.info('connecting %s:%d' % (addr, port[0])) remote = socket.create_connection((addr, port[0]), timeout=config_timeout) remote.settimeout(config_timeout) remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) except socket.error, e: # Connection refused logging.warn(e) return self.handle_tcp(sock, remote)
def server_udp_post_decrypt(self, buf): mac_key = self.server_info.key md5data = hmac.new(mac_key, buf[-8:-5], self.hashfunc).digest() uid = struct.unpack('<I', buf[-5:-1])[0] ^ struct.unpack( '<I', md5data[:4])[0] uid = struct.pack('<I', uid) if uid in self.server_info.users: user_key = self.server_info.users[uid] else: uid = None if not self.server_info.users: user_key = self.server_info.key else: user_key = self.server_info.recv_iv if hmac.new(user_key, buf[:-1], self.hashfunc).digest()[:1] != buf[-1:]: return (b'', None) rand_len = self.udp_rnd_data_len(md5data, self.random_client) encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(user_key)) + to_bytes(base64.b64encode(md5data)), 'rc4') out_buf = encryptor.decrypt(buf[:-8 - rand_len]) return (out_buf, uid)
def connect(self, address): self.__address = address sshost, ssport, ssmethod, sspassword = (self.ssServer.hostname, self.ssServer.port, self.ssServer.username.lower(), self.ssServer.password) from connection import create_connection self._sock = create_connection((sshost, ssport), self.timeout, parentproxy=self.parentproxy, tunnel=True) self._rfile = self._sock.makefile('rb') self.aead = encrypt.is_aead(ssmethod) self.crypto = encrypt.Encryptor(sspassword, ssmethod) self._connected = False # start forward thread here self._thread = Thread(target=self.forward_tcp, args=(self._socketpair_b, self._sock, self.crypto, 60)) self._thread.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) 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())) data = chr(10) + ts + chr(len(pubk)) + pubk + hmac.new( psw.encode(), ts + pubk + usn.encode(), hashlib.sha256).digest() self._sock.sendall(self.pskcipher.encrypt(data)) fp = self._sock.makefile('rb', 0) resp_len = 1 if self.pskcipher.decipher else self.pskcipher.iv_len + 1 resp = ord(self.pskcipher.decrypt(fp.read(resp_len))) if resp == 0: logger.debug('hxsocks read key exchange respond') pklen = ord(self.pskcipher.decrypt(fp.read(1))) server_key = self.pskcipher.decrypt(fp.read(pklen)) auth = self.pskcipher.decrypt(fp.read(32)) pklen = ord(self.pskcipher.decrypt(fp.read(1))) server_cert = self.pskcipher.decrypt(fp.read(pklen)) rlen = ord(self.pskcipher.decrypt(fp.read(1))) r = self.pskcipher.decrypt(fp.read(rlen)) s = self.pskcipher.decrypt(fp.read(rlen)) # 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!' ) 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, r, s): shared_secret = acipher.get_dh_key(server_key) keys[self.serverid] = ( hashlib.md5(pubk).digest(), shared_secret) 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: fp.read(ord(self.pskcipher.decrypt(fp.read(1)))) logger.error( 'hxs getKey Error. bad password or timestamp.') else: raise IOError(0, 'hxs getKey Error')
def handle(self): self.remote = None try: self.encryptor = encrypt.Encryptor(self.server.key, self.server.method, servermode=True) sock = self.connection # sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) iv_len = self.encryptor.iv_len() if iv_len: try: self.decrypt(self.rfile.read(iv_len)) except ValueError: logging.warn('server %s:%d iv reused, possible replay attrack. closing...' % self.server.server_address) return data = sock.recv(1) if not data: return addrtype = ord(self.decrypt(data)) if addrtype == 1: addr = socket.inet_ntoa(self.decrypt(self.rfile.read(4))) elif addrtype == 3: addr = self.decrypt(self.rfile.read(ord(self.decrypt(self.rfile.read(1))))) elif addrtype == 4: addr = socket.inet_ntop(socket.AF_INET6, self.decrypt(self.rfile.read(16))) else: # not supported logging.warn('server %s:%d addr_type not supported, maybe wrong password' % self.server.server_address) return port = struct.unpack('>H', self.decrypt(self.rfile.read(2)))[0] if self.server.aports and port not in self.server.aports: logging.info('server %s:%d port %d not allowed' % (self.server.server_address[0], self.server.server_address[1], port)) return if self._request_is_loopback((addr, port)): logging.info('server %s:%d localhost access denied' % self.server.server_address) return try: logging.info('server %s:%d request %s:%d from %s:%d' % (self.server.server_address[0], self.server.server_address[1], addr, port, self.client_address[0], self.client_address[1])) data = self.decrypt(sock.recv(self.bufsize)) if self.server.reverse: if data.startswith((b'GET', b'POST', b'HEAD', b'PUT', b'DELETE', b'TRACE', b'OPTIONS', b'PATCH', b'CONNECT')) and b'HTTP/1' in data and b'\r\n' in data: data = data.decode('latin1') data = data.replace('\r\n', '\r\nss-realip: %s:%s\r\nss-client: %s\r\n' % (self.client_address[0], self.client_address[1], self.server.key), 1) self.remote = create_connection(self.server.reverse, timeout=10) else: a = 'CONNECT %s:%d HTTP/1.0\r\nss-realip: %s:%s\r\nss-client: %s\r\n\r\n' % (addr, port, self.client_address[0], self.client_address[1], self.server.key) self.remote = create_connection(self.server.reverse, timeout=10) self.remote.sendall(a.encode('latin1')) remoterfile = self.remote.makefile('rb', 0) d = remoterfile.readline() while d not in (b'\r\n', b'\n', b'\r'): if not d: raise IOError(0, 'remote closed') d = remoterfile.readline() if not self.remote: self.remote = create_connection((addr, port), timeout=10) self.remote.sendall(data) # self.remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) except (IOError, OSError) as e: # Connection refused logging.warn('server %s:%d %r on connecting %s:%d' % (self.server.server_address[0], self.server.server_address[1], e, addr, port)) return self.handle_tcp(sock, self.remote) except socket.error as e: logging.warn('server %s:%d %r' % (self.server.server_address[0], self.server.server_address[1], e))
def server_post_decrypt(self, buf): if self.raw_trans: return (buf, False) self.recv_buf += buf out_buf = b'' sendback = False if not self.has_recv_header: if len(self.recv_buf) >= 12 or len(self.recv_buf) in [7, 8]: recv_len = min(len(self.recv_buf), 12) mac_key = self.server_info.recv_iv + self.server_info.key md5data = hmac.new(mac_key, self.recv_buf[:4], self.hashfunc).digest() if md5data[:recv_len - 4] != self.recv_buf[4:recv_len]: return self.not_match_return(self.recv_buf) if len(self.recv_buf) < 12 + 24: return (b'', False) self.last_client_hash = md5data self.user_key = self.server_info.key md5data = hmac.new(self.user_key, self.recv_buf[12:12 + 20], self.hashfunc).digest() if md5data[:4] != self.recv_buf[32:36]: logging.error( '%s data uncorrect auth HMAC-MD5 from %s:%d, data %s' % (self.no_compatible_method, self.server_info.client, self.server_info.client_port, binascii.hexlify(self.recv_buf))) if len(self.recv_buf) < 36: return (b'', False) return self.not_match_return(self.recv_buf) self.last_server_hash = md5data encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(self.user_key)) + self.salt, 'aes-128-cbc') head = encryptor.decrypt( b'\x00' * 16 + self.recv_buf[16:32] + b'\x00') # need an extra byte or recv empty self.client_over_head = struct.unpack('<H', head[12:14])[0] utc_time = struct.unpack('<I', head[:4])[0] client_id = struct.unpack('<I', head[4:8])[0] connection_id = struct.unpack('<I', head[8:12])[0] time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff)) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif: logging.info('%s: wrong timestamp, time_dif %d, data %s' % (self.no_compatible_method, time_dif, binascii.hexlify(head))) return self.not_match_return(self.recv_buf) elif self.server_info.data.insert(self.user_id, client_id, connection_id): self.has_recv_header = True self.client_id = client_id self.connection_id = connection_id else: logging.info( '%s: auth fail, data %s' % (self.no_compatible_method, binascii.hexlify(out_buf))) return self.not_match_return(self.recv_buf) self.encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(self.user_key)) + to_bytes(base64.b64encode(self.last_client_hash)), 'rc4') self.recv_buf = self.recv_buf[36:] self.has_recv_header = True sendback = True while len(self.recv_buf) > 4: mac_key = self.user_key + struct.pack('<I', self.recv_id) data_len = struct.unpack('<H', self.recv_buf[:2])[0] ^ struct.unpack( '<H', self.last_client_hash[14:16])[0] rand_len = self.rnd_data_len(data_len, self.last_client_hash, self.random_client) length = data_len + rand_len if length >= 4096: self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: logging.info(self.no_compatible_method + ': over size') return (b'E' * 2048, False) else: raise Exception('server_post_decrype data error') if length + 4 > len(self.recv_buf): break client_hash = hmac.new(mac_key, self.recv_buf[:length + 2], self.hashfunc).digest() if client_hash[:2] != self.recv_buf[length + 2:length + 4]: logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: return (b'E' * 2048, False) else: raise Exception( 'server_post_decrype data uncorrect checksum') self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF pos = 2 if data_len > 0 and rand_len > 0: pos = 2 + self.rnd_start_pos(rand_len, self.random_client) out_buf += self.encryptor.decrypt(self.recv_buf[pos:data_len + pos]) self.last_client_hash = client_hash self.recv_buf = self.recv_buf[length + 4:] if data_len == 0: sendback = True if out_buf: self.server_info.data.update(self.user_id, self.client_id, self.connection_id) return (out_buf, sendback)
def server_post_decrypt(self, buf): if self.raw_trans: return (buf, False) self.recv_buf += buf out_buf = b'' sendback = False if not self.has_recv_header: if len(self.recv_buf) >= 7 or len(self.recv_buf) in [2, 3]: recv_len = min(len(self.recv_buf), 7) mac_key = self.server_info.recv_iv + self.server_info.key sha1data = hmac.new(mac_key, self.recv_buf[:1], self.hashfunc).digest()[:recv_len - 1] if sha1data != self.recv_buf[1:recv_len]: return self.not_match_return(self.recv_buf) if len(self.recv_buf) < 31: return (b'', False) sha1data = hmac.new(mac_key, self.recv_buf[7:27], self.hashfunc).digest()[:4] if sha1data != self.recv_buf[27:31]: logging.error( '%s data uncorrect auth HMAC-SHA1 from %s:%d, data %s' % (self.no_compatible_method, self.server_info.client, self.server_info.client_port, binascii.hexlify(self.recv_buf))) if len(self.recv_buf) < 31 + self.extra_wait_size: return (b'', False) return self.not_match_return(self.recv_buf) self.user_key = self.server_info.key encryptor = encrypt.Encryptor( to_bytes(base64.b64encode(self.user_key)) + self.salt, 'aes-128-cbc') head = encryptor.decrypt( b'\x00' * 16 + self.recv_buf[11:27] + b'\x00') # need an extra byte or recv empty length = struct.unpack('<H', head[12:14])[0] if len(self.recv_buf) < length: return (b'', False) utc_time = struct.unpack('<I', head[:4])[0] client_id = struct.unpack('<I', head[4:8])[0] connection_id = struct.unpack('<I', head[8:12])[0] rnd_len = struct.unpack('<H', head[14:16])[0] if hmac.new(self.user_key, self.recv_buf[:length - 4], self.hashfunc).digest()[:4] != self.recv_buf[length - 4:length]: logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) return self.not_match_return(self.recv_buf) time_dif = common.int32(utc_time - (int(time.time()) & 0xffffffff)) if time_dif < -self.max_time_dif or time_dif > self.max_time_dif: logging.info('%s: wrong timestamp, time_dif %d, data %s' % (self.no_compatible_method, time_dif, binascii.hexlify(head))) return self.not_match_return(self.recv_buf) elif self.server_info.data.insert(self.user_id, client_id, connection_id): self.has_recv_header = True out_buf = self.recv_buf[31 + rnd_len:length - 4] self.client_id = client_id self.connection_id = connection_id else: logging.info( '%s: auth fail, data %s' % (self.no_compatible_method, binascii.hexlify(out_buf))) return self.not_match_return(self.recv_buf) self.recv_buf = self.recv_buf[length:] self.has_recv_header = True sendback = True while len(self.recv_buf) > 4: mac_key = self.user_key + struct.pack('<I', self.recv_id) mac = hmac.new(mac_key, self.recv_buf[:2], self.hashfunc).digest()[:2] if mac != self.recv_buf[2:4]: self.raw_trans = True logging.info(self.no_compatible_method + ': wrong crc') if self.recv_id == 0: logging.info(self.no_compatible_method + ': wrong crc') return (b'E' * 2048, False) else: raise Exception('server_post_decrype data error') length = struct.unpack('<H', self.recv_buf[:2])[0] if length >= 8192 or length < 7: self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: logging.info(self.no_compatible_method + ': over size') return (b'E' * 2048, False) else: raise Exception('server_post_decrype data error') if length > len(self.recv_buf): break if hmac.new(mac_key, self.recv_buf[:length - 4], self.hashfunc).digest()[:4] != self.recv_buf[length - 4:length]: logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) self.raw_trans = True self.recv_buf = b'' if self.recv_id == 0: return (b'E' * 2048, False) else: raise Exception( 'server_post_decrype data uncorrect checksum') self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF pos = common.ord(self.recv_buf[4]) if pos < 255: pos += 4 else: pos = struct.unpack('<H', self.recv_buf[5:7])[0] + 4 out_buf += self.recv_buf[pos:length - 4] self.recv_buf = self.recv_buf[length:] if pos == length - 4: sendback = True if out_buf: self.server_info.data.update(self.user_id, self.client_id, self.connection_id) return (out_buf, sendback)
def decrypt_data(data): if g.config.encrypt_data: return encrypt.Encryptor(g.config.encrypt_password, g.config.encrypt_method).decrypt(data) else: return data
def handle(self): try: encryptor = encrypt.Encryptor(config_password, config_method) sock = self.connection sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) data = sock.recv(262) if not data: sock.close() return if len(data) < 3: return method = ord(data[2]) if method == 2: logging.warn( 'client tries to use username/password auth, prete' 'nding the password is OK') sock.send('\x05\x02') try: ver_ulen = sock.recv(2) ulen = ord(ver_ulen[1]) if ulen: username = sock.recv(ulen) assert (ulen == len(username)) plen = ord(sock.recv(1)) if plen: _password = sock.recv(plen) assert (plen == len(_password)) sock.send('\x01\x00') except Exception as e: logging.error(e) return elif method == 0: sock.send("\x05\x00") else: logging.error('unsupported method %d' % method) return data = self.rfile.read(4) or '\x00' * 4 mode = ord(data[1]) if mode == 1: pass elif mode == 3: # UDP logging.debug('UDP assc request') if sock.family == socket.AF_INET6: header = '\x05\x00\x00\x04' else: header = '\x05\x00\x00\x01' addr, port = sock.getsockname() addr_to_send = socket.inet_pton(sock.family, addr) port_to_send = struct.pack('>H', port) sock.send(header + addr_to_send + port_to_send) while True: data = sock.recv(4096) if not data: break return else: logging.warn('unknown mode %d' % mode) return addrtype = ord(data[3]) addr_to_send = data[3] if addrtype == 1: addr_ip = self.rfile.read(4) addr = socket.inet_ntoa(addr_ip) addr_to_send += addr_ip elif addrtype == 3: addr_len = self.rfile.read(1) addr = self.rfile.read(ord(addr_len)) addr_to_send += addr_len + addr elif addrtype == 4: addr_ip = self.rfile.read(16) addr = socket.inet_ntop(socket.AF_INET6, addr_ip) addr_to_send += addr_ip else: logging.warn('addr_type not supported') # not supported return addr_port = self.rfile.read(2) addr_to_send += addr_port port = struct.unpack('>H', addr_port) try: reply = "\x05\x00\x00\x01" reply += socket.inet_aton('0.0.0.0') + struct.pack(">H", 2222) self.wfile.write(reply) # reply immediately a_server, a_port = Socks5Server.get_server() addrs = socket.getaddrinfo(a_server, a_port) if addrs: af, socktype, proto, canonname, sa = addrs[0] if config_fast_open: remote = socket.socket(af, socktype, proto) remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) Socks5Server.handle_tcp(sock, remote, encryptor, addr_to_send, a_server, a_port) else: logging.info('connecting %s:%d' % (addr, port[0])) remote = socket.create_connection( (a_server, a_port), timeout=config_timeout) remote.settimeout(config_timeout) remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) Socks5Server.handle_tcp(sock, remote, encryptor, addr_to_send) except (OSError, IOError) as e: logging.warn(e) return except (OSError, IOError) as e: raise e logging.warn(e)
def connect(self, address): self._address = address for _ in range(2): self.getKey() if self._sock is None: from connection import create_connection host, port = self.hxsServer.hostname, self.hxsServer.port 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 logger.debug('hxsocks send connect request') padding_len = random.randint(64, 255) pt = b''.join([ struct.pack('>I', int(time.time())), chr(len(self._address[0])).encode('latin1'), self._address[0].encode(), struct.pack('>H', self._address[1]), b'\x00' * padding_len ]) ct = self.cipher.encrypt(pt) if self.pskcipher._encryptor: ct = self.pskcipher.encrypt(b''.join([ chr(11).encode(), keys[self.serverid][0], struct.pack('>H', len(ct)), ct ])) self._sock.sendall(struct.pack('>H', len(ct)) + ct) else: self._sock.sendall( self.pskcipher.encrypt(b''.join([ chr(11).encode(), keys[self.serverid][0], struct.pack('>H', len(ct)), ct ]))) self._sock.settimeout(8) resp_len = self._rfile.read(2) if not resp_len: self._sock.close() self._sock = None continue self._sock.settimeout(self.timeout) resp_len, = struct.unpack('>H', resp_len) ct = self._rfile.read(resp_len) try: resp = self.cipher.decrypt(ct) except InvalidTag: if self.serverid in keys: del keys[self.serverid] continue except BufEmptyError: self._sock.close() self._sock = None continue d = byte2int(resp) if resp else None if d == 0: logger.debug('hxsocks connected') self.readable = 1 self.writeable = 1 self.pre_close = 0 # start forwarding self._thread = Thread(target=self.forward_tcp, args=(self._socketpair_b, self._sock, self.cipher, 60)) self._thread.start() return else: raise IOError( 0, 'hxsocks Error: remote connect failed. code %d' % d) raise IOError(0, 'hxsocks Error: remote connect failed.')
def connect(self, address): self.__address = address sshost, ssport, ssmethod, sspassword = (self.ssServer.hostname, self.ssServer.port, self.ssServer.username.lower(), self.ssServer.password) from connection import create_connection self._sock = create_connection((sshost, ssport), self.timeout, parentproxy=self.parentproxy, tunnel=True) self.crypto = encrypt.Encryptor(sspassword, ssmethod)
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 __init__(self, ntsk): self.ntsk = ntsk self.CharQuery = data.character_query.CharacterQuery() self.scoreReact = score_react.ScoreReact() self.messageEncryptor = encrypt.Encryptor() self.kanjiQuiz = kanji_quiz.KanjiQuiz() self.googleSearcher = google_search.googleimagesdownload() self.searchArgs = { "keywords": "neko", "safe_search": False, "metadata": False, "limit": 5, "no_directory": True, "output_directory": "birdy", "keywords_from_file": None, "size": None, "format": None, "time": None, "time_range": None, 'suffix_keywords': None, 'prefix_keywords': None, 'url': None, 'similar_images': None, 'specific_site': None, 'single_image': None, 'proxy': None, 'image_directory': None, 'thumbnail': None, 'language': None, 'exact_size': None, 'color': None, 'color_type': None, 'usage_rights': None, 'type': None, 'aspect_ratio': None, 'offset': None } danbooru_config = json.load( open('data/config.json', 'r', encoding="utf-8_sig")) self.danbooruRequest = data.danbooru_request.DanbooruRequest( danbooru_config['danbooru_user'], danbooru_config['danbooru_key']) self.danbooruQuery = data.danbooru_query.DanbooruQuery( servers=list(map(lambda s: s.id, self.ntsk.servers))) self.timerHolder = timer.TimerHolder( servers=list(map(lambda s: s.id, self.ntsk.servers))) self.atejiMatcher = ateji_to_word.AtejiMatcher() #self.timerHolder = timer_holder.TimerHolder() # holds timers for each server, each with info on the user who created it, etc... #self.scheduler = sched.scheduler() # scheduler(time.time, time.sleep) implied ((wow, asyncio.sleep() seems good for now)) self.f_dict = dict() self.f_dict[pfx + 'info'] = self.display_info self.f_dict[pfx + 'commands'] = self.get_commands self.f_dict[pfx + 'count'] = self.db_count self.f_dict[pfx + 'stats'] = self.display_top_words self.f_dict[pfx + 'logs'] = self.get_logs self.f_dict[pfx + 'bin'] = self.encode_bin self.f_dict[pfx + 'unbin'] = self.decode_bin self.f_dict[pfx + 'qr'] = self.create_qr self.f_dict[pfx + 'enc'] = self.get_encryption self.f_dict[pfx + 'dec'] = self.get_decryption self.f_dict[pfx + 'trans'] = self.translate self.f_dict[pfx + 'danbo'] = self.post_danbooru self.f_dict[pfx + 'google'] = self.google_images self.f_dict[pfx + 'vgoogle'] = self.google_videos self.f_dict[pfx + 'setquote'] = self.set_quote self.f_dict[pfx + 'quote'] = self.get_quote self.f_dict[pfx + 'points'] = self.show_points self.f_dict[pfx + 'automata'] = self.automata self.f_dict[pfx + 'trivia'] = self.ask_trivia self.f_dict[pfx + 'kanji'] = self.ask_kanji_quiz self.f_dict[pfx + 'kmatch'] = self.match_ateji self.f_dict[pfx + 'futuresay'] = self.future_say self.f_dict[pfx + 'matrix'] = self.matrix self.f_dict[pfx + 'lmgtfy'] = self.lmgtfy self.f_dict[pfx + 'score'] = self.display_score self.f_dict[pfx + '😂'] = self.ok_hand self.f_dict[pfx + 'yuri'] = self.yuri self.f_dict[pfx + '!db'] = self.do_nothing self.f_dict[pfx + '!inspire'] = self.do_nothing self.f_dict[pfx + '!info'] = self.do_nothing self.f_dict[pfx + 'initdata'] = self.init_data self.f_dict[pfx + 'leaveserver'] = self.leave_server
def handle(self): try: self.connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) pskcipher = encrypt.Encryptor(self.server.PSK, self.server.method) self.connection.settimeout(self.timeout) data = self.rfile.read(pskcipher.iv_len) pskcipher.decrypt(data) while True: try: data = self.rfile.read(1) self.connection.settimeout(self.timeout) cmd = ord(pskcipher.decrypt(data)) except Exception as e: logging.error( 'cmd Exception: server %s %r from %s:%s' % (self.server.server_address[1], e, self.client_address[0], self.client_address[1])) break if cmd == 10: # client key exchange rint = random.randint(64, 255) req_len = pskcipher.decrypt(self.rfile.read(2)) req_len = struct.unpack('>H', req_len)[0] data = pskcipher.decrypt(self.rfile.read(req_len)) data = io.BytesIO(data) ts = data.read(4) if abs(struct.unpack('>I', ts)[0] - time.time()) > 120: # possible replay attack logging.error('bad timestamp. client_ip: %s' % self.client_address[0]) break pklen = ord(data.read(1)) client_pkey = data.read(pklen) client_auth = data.read(32) def _send(data): data = struct.pack('>H', len(data)) + data self.wfile.write(pskcipher.encrypt(data)) client = None for user, passwd in USER_PASS.items(): h = hmac.new(passwd.encode(), ts + client_pkey + user.encode(), hashlib.sha256).digest() if compare_digest(h, client_auth): client = user break else: logging.error('user not found. client_ip: %s' % self.client_address[0]) break pkey, passwd = KeyManager.create_key( client, client_pkey, pskcipher.key_len) if pkey: logging.info('new key exchange. client: %s, ip: %s' % (client, self.client_address[0])) h = hmac.new(passwd.encode(), client_pkey + pkey + client.encode(), hashlib.sha256).digest() scert = SERVER_CERT.get_pub_key() signature = SERVER_CERT.sign(h, self.server.hash_algo) data = chr(0) + chr(len(pkey)) + chr(len(scert)) + chr( len(signature) ) + pkey + h + scert + signature + os.urandom(rint) _send(data) continue else: logging.error( 'Private_key already registered. client: %s, ip: %s' % (client, self.client_address[0])) # KeyManager.del_key(hashlib.md5(client_pkey).digest()) break elif cmd == 11: # a connect request client_pkey = pskcipher.decrypt(self.rfile.read(16)) rint = random.randint(64, 2048) def _send(code, cipher): if code == 1: data = os.urandom(rint) data = pskcipher.encrypt(struct.pack('>H', rint)) + data self.wfile.write(data) else: ct = cipher.encrypt( chr(code) + os.urandom(rint - 1)) data = pskcipher.encrypt(struct.pack( '>H', len(ct))) + ct self.wfile.write(data) if KeyManager.check_key(client_pkey): logging.error( 'client key not exist or expired. client ip: %s' % self.client_address[0]) ctlen = struct.unpack( '>H', pskcipher.decrypt(self.rfile.read(2)))[0] self.rfile.read(ctlen) _send(1, None) continue user = KeyManager.get_user_by_pubkey(client_pkey) cipher = encrypt.AEncryptor( KeyManager.get_skey_by_pubkey(client_pkey), self.server.method, CTX) ctlen = struct.unpack( '>H', pskcipher.decrypt(self.rfile.read(2)))[0] ct = self.rfile.read(ctlen) data = cipher.decrypt(ct) buf = io.BytesIO(data) ts = buf.read(4) if abs(struct.unpack('>I', ts)[0] - time.time()) > 120: logging.error( 'bad timestamp, possible replay attrack. client ip: %s' % self.client_address[0]) # KeyManager.del_key(client_pkey) # _send(1, None) break host_len = ord(buf.read(1)) addr = buf.read(host_len) port = struct.unpack('>H', buf.read(2))[0] if self._request_is_loopback( (addr, port)) and port not in self.server.forward: logging.info( 'server %d access localhost:%d denied. from %s:%d, %s' % (self.server.server_address[1], port, self.client_address[0], self.client_address[1], user)) _send(2, cipher) continue try: logging.info('server %d request %s:%d from %s:%d, %s' % (self.server.server_address[1], addr, port, self.client_address[0], self.client_address[1], user)) remote = create_connection((addr, port), timeout=10, proxy=self.server.proxy) remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) _send(0, cipher) # self.remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) except (IOError, OSError) as e: # Connection refused logging.warning( 'server %s:%d %r on connecting %s:%d' % (self.server.server_address[0], self.server.server_address[1], e, addr, port)) _send(2, cipher) continue if self.forward_tcp(self.connection, remote, cipher, pskcipher, timeout=60): break self.connection.settimeout(60) logging.debug( 'hxsocks connect reusable, except next connection') elif cmd in (1, 3, 4, 17, 19, 20): # A shadowsocks request if not self.server.ss: logging.warning( 'shadowsocks not enabled for this server. port: %d' % self.server.server_address[1]) break ota = cmd & 16 if cmd & 15 == 1: _addr = pskcipher.decrypt(self.rfile.read(4)) addr = socket.inet_ntoa(_addr) elif cmd & 15 == 3: _addr = pskcipher.decrypt(self.rfile.read(1)) addr = pskcipher.decrypt(self.rfile.read(ord(_addr))) _addr += addr elif cmd & 15 == 4: _addr = socket.AF_INET6, pskcipher.decrypt( self.rfile.read(16)) addr = socket.inet_ntop(_addr) port = struct.unpack('>H', pskcipher.decrypt( self.rfile.read(2)))[0] # verify if ota: header = chr(cmd) + _addr + struct.pack('>H', port) self._ota_chunk_idx = 0 rmac = pskcipher.decrypt(self.rfile.read(10)) key = pskcipher.decipher_iv + pskcipher.key mac = hmac.new(key, header, hashlib.sha1).digest()[:10] if not compare_digest(rmac, mac): logging.error("OTA Failed!!") break if self._request_is_loopback( (addr, port)) and port not in self.server.forward: logging.info( 'server %d access localhost:%d denied. from %s:%d' % (self.server.server_address[1], port, self.client_address[0], self.client_address[1])) break try: remote = None logging.info( 'server %d SS request %s:%d from %s:%d %s' % (self.server.server_address[1], addr, port, self.client_address[0], self.client_address[1], 'with ota' if ota else '')) remote = create_connection((addr, port), timeout=10, proxy=self.server.proxy) if ota: return self.ssforward_tcp_ota(self.connection, remote, pskcipher, timeout=60) return self.ssforward_tcp(self.connection, remote, pskcipher, timeout=60) except (IOError, OSError) as e: # Connection refused logging.warn( 'server %s:%d %r on connecting %s:%d' % (self.server.server_address[0], self.server.server_address[1], e, addr, port)) return else: logging.warning('unknown cmd %d, bad encryption key?' % cmd) break ins, _, _ = select.select([self.connection], [], [], 1) while ins: data = self.connection.recv(self.bufsize) if not data: break ins, _, _ = select.select([self.connection], [], [], 1) except Exception as e: logging.error(repr(e)) logging.error(traceback.format_exc())
def handle(self): try: self.encryptor = encrypt.Encryptor(KEY, METHOD) sock = self.connection d = sock.recv(262) reply = init_send = None if d.startswith('CONNECT '): d = recv_all(sock, d, '\r\n\r\n') addr, port, addr_to_send = self.get_host_port( d, '443', from_first_line=True) reply = 'HTTP/1.1 200 OK\r\n\r\n' elif d.startswith('GET ') or d.startswith('HEAD '): d = recv_all(sock, d, '\r\n\r\n') addr, port, addr_to_send = self.get_host_port(d, '80') d = self.clean_path(d) if port[0] == PORT and (addr.startswith('192.168') or addr.startswith('127.0')): mimetype = 'application/x-ns-proxy-autoconfig' with open('proxy.pac', 'rb') as fp: data = fp.read() self.wfile.write( 'HTTP/1.1 200\r\nContent-Type: %s\r\nContent-Length: %s\r\n\r\n' % (mimetype, len(data))) self.wfile.write(data) sock.close() logging.info('get proxy pac') return d = d.replace('Proxy-Connection:', 'Connection:') init_send = d elif d.startswith('POST '): d = recv_all(sock, d, '\r\n\r\n') i = d.find('\r\n\r\n') remain = len(d) - (i + 4) header = self.parse_header(d) if 'Content-Length' not in header: logging.error(d) return size = int(header['Content-Length']) - remain if size > 0: d += recv_size(sock, size) addr, port, addr_to_send = self.get_host_port(d, '80') d = self.clean_path(d) d = d.replace('Proxy-Connection:', 'Connection:') init_send = d else: sock.send("\x05\x00") data = self.rfile.read(4) or '\x00' * 4 mode = ord(data[1]) if mode != 1: logging.warn('mode != 1') logging.warn(d) return addrtype = ord(data[3]) addr_to_send = data[3] if addrtype == 1: addr_ip = self.rfile.read(4) addr = socket.inet_ntoa(addr_ip) addr_to_send += addr_ip elif addrtype == 3: addr_len = self.rfile.read(1) addr = self.rfile.read(ord(addr_len)) addr_to_send += addr_len + addr elif addrtype == 4: addr_ip = self.rfile.read(16) addr = socket.inet_ntop(socket.AF_INET6, addr_ip) addr_to_send += addr_ip else: logging.warn('addr_type not support') # not support return addr_port = self.rfile.read(2) addr_to_send += addr_port port = struct.unpack('>H', addr_port) reply = "\x05\x00\x00\x01" reply += socket.inet_aton('0.0.0.0') + struct.pack(">H", 2222) try: if reply: self.wfile.write(reply) # reply immediately remote = socket.create_connection((SERVER, REMOTE_PORT)) self.send_encrypt(remote, addr_to_send) logging.info('connecting %s:%d' % (addr, port[0])) except socket.error, e: logging.warn(e) return self.handle_tcp(sock, remote, (addr, port[0]), init_send)