Exemple #1
0
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
Exemple #2
0
 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)
Exemple #3
0
    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()