def http2shadosocks(data): """ genearte http response and shadowsocks premble """ words = data.split() if len(words) < 3: raise HttpRequestError(400, "Bad request version") method, path, version = words[:3] https = True if method.upper() == "CONNECT" else False if version[:5] != 'HTTP/': raise HttpRequestError(400, "Bad request version (%r)" % version) # socks5 request format cmd = 0x01 # connect try: if https: host, port = path.split(":") else: result = urlparse.urlsplit(path) host = result.hostname if not host: logging.debug(data) raise HttpRequestError(400, "Bad request") port = result.port or 80 uri = result.path or "/" if result.query: data += (result.query + "\r\n") except IndexError: raise HttpRequestError(400, "Bad request") atyp = utils.is_ip(host) if not atyp: atyp = struct.pack("!B", 0x03) addr = struct.pack("!B", len(host)) + \ utils.to_str(host) elif atyp == socket.AF_INET: addr = utils.inet_pton(atyp, host) atyp = struct.pack("!B", 0x01) else: addr = utils.inet_pton(atyp, host) atyp = struct.pack("!B", 0x04) premble = atyp + addr + struct.pack("!H", int(port)) if not https: premble += data.replace(path, uri, 1) addr = (utils.to_str(host), port) http_response = "%s 200 Connection Established\r\n"\ "Proxy-Agent: myss\r\n"\ "\r\n" % version if https else "" return http_response, premble, addr
def on_recv_syn(self): if self._status == self.STAGE_CLOSED: logging.warning("read on closed socket!") self.destroy() return data = None try: data = self._sock.recv(self.BUF_SIZE) except (OSError, IOError) as e: if utils.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return cmd = utils.ord(data[1]) if cmd == socks5.CMD_UDPFWD: logging.debug('UDP associate') if self._sock.family == socket.AF_INET6: header = b'\x05\x00\x00\x04' else: header = b'\x05\x00\x00\x01' addr, port = self._sock.getsockname()[:2] addr_to_send = socket.inet_pton(self._sock.family, addr) port_to_send = struct.pack('>H', port) data = header + addr_to_send + port_to_send self._write_buf.append(data) # send back ack self._wbuf_size += len(data) return elif cmd == socks5.CMD_CONNECT: data = data[3:] else: logging.error('unknown command %d', cmd) self.destroy() return self._append_to_rbuf(data) utils.merge_prefix(self._read_buf, self.BUF_SIZE) if not self._read_buf: return data = self._read_buf[0] header_result = socks5.parse_header(data) if not header_result: return addrtype, remote_addr, remote_port, header_length = header_result logging.info("connecting %s:%d from %s:%d" % (\ (remote_addr, remote_port, ) + self._addr)) data = self._pop_from_rbuf(self.BUF_SIZE) self._status = self.STAGE_SOCKS5_SYN ack, l = socks5.gen_ack() self._write_buf.append(ack) # send back ack self._wbuf_size += l if self._exclusive_host(remote_addr): # self._append_to_rbuf(data, codec=True) self._peer_addr = self._sshost() # connect ssserver else: self._direct_conn = True self._peer_addr = (utils.to_str(remote_addr), remote_port) #直连 self._dns_resolver.resolve(self._peer_addr[0], self._on_dns_resolved)
def on_recv_syn(self): if self._status == self.STAGE_CLOSED: logging.warning("read on closed socket!") self.destroy() return data = None try: data = self._sock.recv(self.BUF_SIZE) except (OSError, IOError) as e: if utils.errno_from_exception(e) in \ (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): return if not data: self.destroy() return self._append_to_rbuf(data, codec=True) utils.merge_prefix(self._read_buf, self.BUF_SIZE) if not self._read_buf: return data = self._read_buf[0] header_result = socks5.parse_header(data) if not header_result: return addrtype, remote_addr, remote_port, header_length = header_result self._pop_from_rbuf(header_length) self._status = self.STAGE_SOCKS5_SYN logging.info("connecting %s:%d from %s:%d" % (\ (remote_addr, remote_port, ) + self._addr)) self._peer_addr = (utils.to_str(remote_addr), remote_port) try: self._dns_resolver.resolve(remote_addr, self._on_dns_resolved) except Exception as e: logging.error(e) self.destroy()