def _handle_server(self): server = self._server_socket data, r_addr = server.recvfrom(BUF_SIZE) key = None iv = None if not data: logging.debug('UDP handle_server: data is empty') if self._stat_callback: self._stat_callback(self._listen_port, len(data)) if self._is_local: if self._is_tunnel: # add ss header to data tunnel_remote = self.tunnel_remote tunnel_remote_port = self.tunnel_remote_port data = common.add_header(tunnel_remote, tunnel_remote_port, data) else: frag = common.ord(data[2]) if frag != 0: logging.warn('UDP drop a message since frag is not 0') return else: data = data[3:] else: # decrypt data try: data, key, iv = cryptor.decrypt_all(self._password, self._method, data, self._crypto_path) except Exception: logging.debug('UDP handle_server: decrypt data failed') return if not data: logging.debug('UDP handle_server: data is empty after decrypt') return header_result = parse_header(data) if header_result is None: return addrtype, dest_addr, dest_port, header_length = header_result logging.info("[%d] udp data to %s:%d from %s:%d" % (self._config['server_port'], dest_addr, dest_port, r_addr[0], r_addr[1])) if self._is_local: server_addr, server_port = self._get_a_server() else: server_addr, server_port = dest_addr, dest_port # spec https://shadowsocks.org/en/spec/one-time-auth.html self._ota_enable_session = addrtype & ADDRTYPE_AUTH if self._ota_enable and not self._ota_enable_session: logging.warn('client one time auth is required') return if self._ota_enable_session: if len(data) < header_length + ONETIMEAUTH_BYTES: logging.warn('UDP one time auth header is too short') return _hash = data[-ONETIMEAUTH_BYTES:] data = data[:-ONETIMEAUTH_BYTES] _key = iv + key if onetimeauth_verify(_hash, data, _key) is False: logging.warn('UDP one time auth fail') return addrs = self._dns_cache.get(server_addr, None) if addrs is None: addrs = socket.getaddrinfo(server_addr, server_port, 0, socket.SOCK_DGRAM, socket.SOL_UDP) if not addrs: # drop return else: self._dns_cache[server_addr] = addrs af, socktype, proto, canonname, sa = addrs[0] key = client_key(r_addr, af) client = self._cache.get(key, None) if not client: # TODO async getaddrinfo if self._forbidden_iplist: if common.to_str(sa[0]) in self._forbidden_iplist: logging.debug('IP %s is in forbidden list, drop' % common.to_str(sa[0])) # drop return client = socket.socket(af, socktype, proto) client.setblocking(False) self._cache[key] = client self._client_fd_to_server_addr[client.fileno()] = r_addr self._sockets.add(client.fileno()) self._eventloop.add(client, eventloop.POLL_IN, self) if self._is_local: key, iv, m = cryptor.gen_key_iv(self._password, self._method) # spec https://shadowsocks.org/en/spec/one-time-auth.html if self._ota_enable_session: data = self._ota_chunk_data_gen(key, iv, data) try: data = cryptor.encrypt_all_m(key, iv, m, self._method, data, self._crypto_path) except Exception: logging.debug("UDP handle_server: encrypt data failed") return if not data: return else: data = data[header_length:] if not data: return try: client.sendto(data, (server_addr, server_port)) except IOError as e: err = eventloop.errno_from_exception(e) if err in (errno.EINPROGRESS, errno.EAGAIN): pass else: shell.print_exception(e)
def _handle_server(self): server = self._server_socket data, r_addr = server.recvfrom(BUF_SIZE) key = None iv = None if not data: logging.debug('UDP handle_server: data is empty') if self._stat_callback: self._stat_callback(self._listen_port, len(data)) if self._is_local: if self._is_tunnel: # add ss header to data tunnel_remote = self.tunnel_remote tunnel_remote_port = self.tunnel_remote_port data = common.add_header(tunnel_remote, tunnel_remote_port, data) else: frag = common.ord(data[2]) if frag != 0: logging.warn('UDP drop a message since frag is not 0') return else: data = data[3:] else: # decrypt data try: data, key, iv = cryptor.decrypt_all(self._password, self._method, data, self._crypto_path) except Exception: logging.debug('UDP handle_server: decrypt data failed') return if not data: logging.debug('UDP handle_server: data is empty after decrypt') return header_result = parse_header(data) if header_result is None: return addrtype, dest_addr, dest_port, header_length = header_result logging.info("udp data to %s:%d from %s:%d" % (dest_addr, dest_port, r_addr[0], r_addr[1])) if self._is_local: server_addr, server_port = self._get_a_server() else: server_addr, server_port = dest_addr, dest_port # spec https://shadowsocks.org/en/spec/one-time-auth.html self._ota_enable_session = addrtype & ADDRTYPE_AUTH if self._ota_enable and not self._ota_enable_session: logging.warn('client one time auth is required') return if self._ota_enable_session: if len(data) < header_length + ONETIMEAUTH_BYTES: logging.warn('UDP one time auth header is too short') return _hash = data[-ONETIMEAUTH_BYTES:] data = data[: -ONETIMEAUTH_BYTES] _key = iv + key if onetimeauth_verify(_hash, data, _key) is False: logging.warn('UDP one time auth fail') return addrs = self._dns_cache.get(server_addr, None) if addrs is None: addrs = socket.getaddrinfo(server_addr, server_port, 0, socket.SOCK_DGRAM, socket.SOL_UDP) if not addrs: # drop return else: self._dns_cache[server_addr] = addrs af, socktype, proto, canonname, sa = addrs[0] key = client_key(r_addr, af) client = self._cache.get(key, None) if not client: # TODO async getaddrinfo if self._forbidden_iplist: if common.to_str(sa[0]) in self._forbidden_iplist: logging.debug('IP %s is in forbidden list, drop' % common.to_str(sa[0])) # drop return client = socket.socket(af, socktype, proto) client.setblocking(False) self._cache[key] = client self._client_fd_to_server_addr[client.fileno()] = r_addr self._sockets.add(client.fileno()) self._eventloop.add(client, eventloop.POLL_IN, self) if self._is_local: key, iv, m = cryptor.gen_key_iv(self._password, self._method) # spec https://shadowsocks.org/en/spec/one-time-auth.html if self._ota_enable_session: data = self._ota_chunk_data_gen(key, iv, data) try: data = cryptor.encrypt_all_m(key, iv, m, self._method, data, self._crypto_path) except Exception: logging.debug("UDP handle_server: encrypt data failed") return if not data: return else: data = data[header_length:] if not data: return try: client.sendto(data, (server_addr, server_port)) except IOError as e: err = eventloop.errno_from_exception(e) if err in (errno.EINPROGRESS, errno.EAGAIN): pass else: shell.print_exception(e)
def _handle_server(self): server = self._server_socket data, r_addr = server.recvfrom(BUF_SIZE) key = None iv = None if not data: logging.debug('UDP handle_server: data is empty') if self._stat_callback: self._stat_callback(self._listen_port, len(data)) # 若本地端从监听1080端口收到本机应用进程(例如chrome)的数据,进行切除header if self._is_local: if self._is_tunnel: # add ss header to data tunnel_remote = self.tunnel_remote tunnel_remote_port = self.tunnel_remote_port data = common.add_header(tunnel_remote, tunnel_remote_port, data) else: frag = common.ord(data[2]) if frag != 0: logging.warn('UDP drop a message since frag is not 0') return else: data = data[3:] # 如果是服务端收到本地端发出的udp数据,先进行解密 else: # decrypt data try: data, key, iv = cryptor.decrypt_all(self._password, self._method, data, self._crypto_path) except Exception: logging.debug('UDP handle_server: decrypt data failed') return if not data: logging.debug('UDP handle_server: data is empty after decrypt') return # 处理header header_result = parse_header(data) if header_result is None: return addrtype, dest_addr, dest_port, header_length = header_result logging.info("udp data to %s:%d from %s:%d" % (dest_addr, dest_port, r_addr[0], r_addr[1])) if self._is_local: # 如果是local收到,则server_addr server_port都是远程的 server_addr, server_port = self._get_a_server() else: # 如果远程收到,则将server_addr这些改成dest_addr dest_port,方便操作 # dest就是最终目标,例如 www.youtube.com:443 server_addr, server_port = dest_addr, dest_port # spec https://shadowsocks.org/en/spec/one-time-auth.html self._ota_enable_session = addrtype & ADDRTYPE_AUTH if self._ota_enable and not self._ota_enable_session: logging.warn('client one time auth is required') return if self._ota_enable_session: if len(data) < header_length + ONETIMEAUTH_BYTES: logging.warn('UDP one time auth header is too short') return _hash = data[-ONETIMEAUTH_BYTES:] data = data[: -ONETIMEAUTH_BYTES] _key = iv + key if onetimeauth_verify(_hash, data, _key) is False: logging.warn('UDP one time auth fail') return addrs = self._dns_cache.get(server_addr, None) if addrs is None: addrs = socket.getaddrinfo(server_addr, server_port, 0, socket.SOCK_DGRAM, socket.SOL_UDP) if not addrs: # drop return else: self._dns_cache[server_addr] = addrs af, socktype, proto, canonname, sa = addrs[0] key = client_key(r_addr, af) client = self._cache.get(key, None) if not client: # TODO async getaddrinfo if self._forbidden_iplist: if common.to_str(sa[0]) in self._forbidden_iplist: logging.debug('IP %s is in forbidden list, drop' % common.to_str(sa[0])) # drop return client = socket.socket(af, socktype, proto) client.setblocking(False) self._cache[key] = client self._client_fd_to_server_addr[client.fileno()] = r_addr self._sockets.add(client.fileno()) # 添加进Eventloop,标志设置为可读 self._eventloop.add(client, eventloop.POLL_IN, self) # 如果是local,要向远程发,要过墙,所以要加密 if self._is_local: key, iv, m = cryptor.gen_key_iv(self._password, self._method) # spec https://shadowsocks.org/en/spec/one-time-auth.html if self._ota_enable_session: data = self._ota_chunk_data_gen(key, iv, data) try: data = cryptor.encrypt_all_m(key, iv, m, self._method, data, self._crypto_path) except Exception: logging.debug("UDP handle_server: encrypt data failed") return if not data: return # 如果是远程,要向dest发请求,所以把除数据的部分除去,即除去header。 else: # data已经在上面进行数据解密了。不需要像local一样加密发送。 # data已经被切除头的3个字节了 data = data[header_length:] if not data: return try: # 发送,完美无瑕。。。。 # 这个sendto同时有udp的和tcp的两种,sendto函数主要用于UDP,但这里两种都用了 # 调用sendto时候会自动加上那个首3个字节,貌似是x00 x00 x00 client.sendto(data, (server_addr, server_port)) except IOError as e: err = eventloop.errno_from_exception(e) if err in (errno.EINPROGRESS, errno.EAGAIN): pass else: shell.print_exception(e)
def _handle_server(self): server = self._server_socket data, r_addr = server.recvfrom(BUF_SIZE) client_address = r_addr[0] key = None iv = None if not data: logging.debug('U[%d] UDP handle_server: data is empty' % self._config['server_port']) if self._stat_callback: self._stat_callback(self._listen_port, len(data)) if self._is_local: if self._is_tunnel: # add ss header to data tunnel_remote = self.tunnel_remote tunnel_remote_port = self.tunnel_remote_port data = common.add_header(tunnel_remote, tunnel_remote_port, data) else: frag = common.ord(data[2]) if frag != 0: logging.warning('UDP drop a message since frag is not 0') return else: data = data[3:] else: # decrypt data try: data, key, iv = cryptor.decrypt_all(self._password, self._method, data) except Exception: logging.debug('U[%d] UDP handle_server: decrypt data failed' % self._config[ 'server_port']) return if not data: logging.debug( 'U[%d] UDP handle_server: data is empty after decrypt' % self._config[ 'server_port'] ) return header_result = parse_header(data) if header_result is None: return addrtype, dest_addr, dest_port, header_length = header_result if self._config['firewall_ports'] and self._config['server_port'] not in self._config['firewall_trusted']: # Firewall enabled if self._config['firewall_mode'] == 'blacklist' and dest_port in self._config['firewall_ports']: firewall_blocked = True elif self._config['firewall_mode'] == 'whitelist' and dest_port not in self._config['firewall_ports']: firewall_blocked = True else: firewall_blocked = False else: firewall_blocked = False if firewall_blocked: logging.warning('U[%d] UDP PORT BANNED: RP[%d] A[%s-->%s]' % ( self._config['server_port'], dest_port, client_address, common.to_str(dest_addr) )) return else: logging.info('U[%d] UDP CONN: RP[%d] A[%s-->%s]' % ( self._config['server_port'], dest_port, client_address, common.to_str(dest_addr) )) if self._is_local: server_addr, server_port = self._get_a_server() else: server_addr, server_port = dest_addr, dest_port addrs = self._dns_cache.get(server_addr, None) if addrs is None: addrs = socket.getaddrinfo(server_addr, server_port, 0, socket.SOCK_DGRAM, socket.SOL_UDP) if not addrs: # drop return else: self._dns_cache[server_addr] = addrs af, socktype, proto, canonname, sa = addrs[0] key = client_key(r_addr, af) client = self._cache.get(key, None) if not client: # TODO async getaddrinfo if self._forbidden_iplist: if common.to_str(sa[0]) in self._forbidden_iplist: logging.debug('U[%d] IP %s is in forbidden list, drop' % (self._config['server_port'], common.to_str(sa[0]))) # drop return client = socket.socket(af, socktype, proto) client.setblocking(False) self._cache[key] = client self._client_fd_to_server_addr[client.fileno()] = r_addr self._sockets.add(client.fileno()) self._eventloop.add(client, eventloop.POLL_IN, self) if self._is_local: key, iv, m = cryptor.gen_key_iv(self._password, self._method) try: data = cryptor.encrypt_all_m(key, iv, m, self._method, data, self._crypto_path) except Exception: logging.debug("UDP handle_server: encrypt data failed") return if not data: return else: data = data[header_length:] if not data: return try: client.sendto(data, (server_addr, server_port)) except (socket.error, OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if sys.platform == "win32": if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK, errno.WSAEWOULDBLOCK): pass else: shell.print_exception(e) elif error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): pass else: shell.print_exception(e)
def _handle_server(self): server = self._server_socket data, r_addr = server.recvfrom(BUF_SIZE) client_address = r_addr[0] key = None iv = None if not data: logging.debug('U[%d] UDP handle_server: data is empty' % self._config['server_port']) if self._stat_callback: self._stat_callback(self._listen_port, len(data)) if self._is_local: frag = common.ord(data[2]) if frag != 0: logging.warn('U[%d] UDP drop a message since frag is not 0' % self._config['server_port']) return else: data = data[3:] else: # decrypt data try: data, key, iv = cryptor.decrypt_all(self._password, self._method, data) except Exception: logging.debug('U[%d] UDP handle_server: decrypt data failed' % self._config['server_port']) return if not data: logging.debug( 'U[%d] UDP handle_server: data is empty after decrypt' % self._config['server_port']) return header_result = parse_header(data) if header_result is None: return addrtype, dest_addr, dest_port, header_length = header_result if self._config['firewall_ports'] and self._config[ 'server_port'] not in self._config['firewall_trusted']: # Firewall enabled if self._config[ 'firewall_mode'] == 'blacklist' and dest_port in self._config[ 'firewall_ports']: firewall_blocked = True elif self._config[ 'firewall_mode'] == 'whitelist' and dest_port not in self._config[ 'firewall_ports']: firewall_blocked = True else: firewall_blocked = False else: firewall_blocked = False if firewall_blocked: logging.warning('U[%d] UDP PORT BANNED: RP[%d] A[%s-->%s]' % (self._config['server_port'], dest_port, client_address, common.to_str(dest_addr))) return else: logging.info('U[%d] UDP CONN: RP[%d] A[%s-->%s]' % (self._config['server_port'], dest_port, client_address, common.to_str(dest_addr))) if self._is_local: server_addr, server_port = self._get_a_server() else: server_addr, server_port = dest_addr, dest_port # spec https://shadowsocks.org/en/spec/one-time-auth.html if self._one_time_auth_enable or (addrtype & ADDRTYPE_AUTH == ADDRTYPE_AUTH): if not self._one_time_auth_enable and self._config['verbose']: logging.info( 'U[%d] UDP one time auth automatically enabled' % self._config['server_port']) self._one_time_auth_enable = True if len(data) < header_length + ONETIMEAUTH_BYTES: logging.warn( 'U[%d] UDP one time auth header is too short' % self._config['server_port']) return _hash = data[-ONETIMEAUTH_BYTES:] data = data[:-ONETIMEAUTH_BYTES] _key = iv + key if onetimeauth_verify(_hash, data, _key) is False: logging.warn('U[%d] UDP one time auth fail' % self._config['server_port']) return addrs = self._dns_cache.get(server_addr, None) if addrs is None: addrs = socket.getaddrinfo(server_addr, server_port, 0, socket.SOCK_DGRAM, socket.SOL_UDP) if not addrs: # drop return else: self._dns_cache[server_addr] = addrs af, socktype, proto, canonname, sa = addrs[0] key = client_key(r_addr, af) client = self._cache.get(key, None) if not client: # TODO async getaddrinfo if self._forbidden_iplist: if common.to_str(sa[0]) in self._forbidden_iplist: logging.debug( 'U[%d] IP %s is in forbidden list, drop' % (self._config['server_port'], common.to_str(sa[0]))) # drop return client = socket.socket(af, socktype, proto) client.setblocking(False) self._cache[key] = client self._client_fd_to_server_addr[client.fileno()] = r_addr self._sockets.add(client.fileno()) self._eventloop.add(client, eventloop.POLL_IN, self) if self._is_local: key, iv, m = cryptor.gen_key_iv(self._password, self._method) # spec https://shadowsocks.org/en/spec/one-time-auth.html if self._one_time_auth_enable: data = self._ota_chunk_data_gen(key, iv, data) try: data = cryptor.encrypt_all_m(key, iv, m, self._method, data) except Exception: logging.debug("UDP handle_server: encrypt data failed") return if not data: return else: data = data[header_length:] if not data: return try: client.sendto(data, (server_addr, server_port)) except (socket.error, OSError, IOError) as e: error_no = eventloop.errno_from_exception(e) if sys.platform == "win32": if error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK, errno.WSAEWOULDBLOCK): pass else: shell.print_exception(e) elif error_no in (errno.EAGAIN, errno.EINPROGRESS, errno.EWOULDBLOCK): pass else: shell.print_exception(e)