示例#1
0
 def handle(self):
     global HEARTBEAT_SOCKET_COUNT
     sock = self.connection
     HEARTBEAT_SOCKET_COUNT += 1
     sock.settimeout(10)
     try:
         data = sock.recv(4096)
     except TimeoutError:
         logging.warning(f"HeartBeat Timed out")
     dec_data = decrypt(data)
     obj = hsp.handshake()
     peer_ip, port = sock.getpeername()
     # 收到请求时如果是白名单中的ip, 则不需要再校验
     if peer_ip not in white_list:
         logging.info(
             f"received heartbeat from {peer_ip}, white_list:{white_list}, black_list:{black_list}"
         )
         # 收到请求若是黑名单中的, 则直接拒绝
         if peer_ip in black_list:
             logging.info(f"rejected black listed heartbeat {peer_ip}")
             raise Exception(f"rejected black listed heartbeat {peer_ip}")
         else:
             try:
                 if obj.decode_protocol(dec_data) != 'Done':
                     # 加入黑名单
                     black_list.append(peer_ip)
                     logging.info(
                         f"after {peer_ip}, white_list:{white_list}, black_list:{black_list}"
                     )
                 else:
                     # 加入白名单
                     white_list.append(peer_ip)
                     if peer_ip in black_list:
                         black_list.remove(peer_ip)
                     logging.info(
                         f"after {peer_ip}, white_list:{white_list}, black_list:{black_list}"
                     )
             except Exception as e:
                 logging.error(e)
                 exc_type, exc_obj, exc_tb = sys.exc_info()
                 fname = os.path.split(
                     exc_tb.tb_frame.f_code.co_filename)[1]
                 logging.warning(f"{exc_type}  {fname}  {exc_tb.tb_lineno}")
                 pass
     sock.close()
     HEARTBEAT_SOCKET_COUNT -= 1
示例#2
0
def pulse(ip, port):
    try:
        remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        remote.connect((ip, port))
        # logging.info(f"sending heartbeat to {ip}:{port}")
        send_all(
            remote,
            encrypt(
                hsp.handshake(addr='hello', port=str(port)).encode_protocol()))
    except ConnectionRefusedError:
        logging.warning(f"cannot talk to {ip}:{port}")
    except Exception as e:
        logging.warning(e)
        exc_type, exc_obj, exc_tb = sys.exc_info()
        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
        logging.warning(f"{exc_type}  {fname}  {exc_tb.tb_lineno}")

    global pulse_thread
    pulse_thread = threading.Timer(5, pulse, (ip, port))
    pulse_thread.start()
示例#3
0
import handshake_protocol_v1 as hsp
m = hsp.handshake('ip', '1.1.1.1', '8080')
n = hsp.handshake('url', 'www.baidu.com', '8080')
u = hsp.handshake()
print(m.encode_protocol())
print(n.encode_protocol())
print(u.encode_protocol())
k = u.decode_protocol(m.encode_protocol())
print(u.encode_protocol())

dd = hsp.bytedata(
    raw_data=
    b'd5edb61c315af758b4be428991d615b6f44156d01c17b9ab3ba26fd9452ba715db0d771da68cbca4f4c8ecfec9d1acf4f192d6042981dd9d9e0e8f6ba4b6452cfa612ac49d5b8dba93aeec38b4e63a1e5da8dd911a2ab6e015a924d6c6e6744ac6bfdceae3096c587dc560f241bf188ab0b4086a0161b341d045be5e138d26b331534e5ba4b3f77ecf6ac58a70ab465bb56034146748bd4157e7b3da9626d67d96e570ed46acd6507a5c77571f20961a5a35f582379fd86213f0acf590d08ce8e4c8e103f8419324b23052d6d8333995b0d7d08f75b8efc6f3497e17ba95959b5ca35bbd329a41e5aa57a997db06559a7b0636d7b31c9e5acc117cf6f7d70a6ffc68783df9d1e7cf10cb5ec494c82f094dacd65700dcb8efe0ed149577b8d324d70567ad45242b064b7ad628f9069d84bee82dd6db6b3c47107683598ed360f837aed83703aa547155d4974ba6d780a1ba40151378b656279319d530f736641f708bc9105eb165d61d72eb346da6dd995d1ecadcdcef14efad8f14af1c4eed1607592e95cbde33ab96cd7e974d3e86e94f444aebd747c369f379e1ad0b9ce8cae66cd2415d9e315d9135fa46357edb64ba5e49b51ca021ab7a473e29d349e9b98d7ed32f76097dd46b7d959348ab18ab3e0c884ae68e881b08830b3f48f878922daac26b7f782a83a6bd1bfdea34377e28163fc9ca1df33c6833df4406b30cb7ae0c05d07ee3f346b09725eb9bbedf2ac05d84515aeb304a4474701b2c7e7ca0c1276bcefe0f8f8f4d8e0cfef0cde3adb3ff3c6e6cb6f0fcebc3039b171f5dcf5379f1fbc7579f0caa7ec19bc095342b9d93ce53a85fbe0d6a02f81e9421e65ddce8376cdadfc97b30adaeb82e653b08e2f0470ce410e5856bdd148931176bfb370e74a2b9dfac5b15f1c3fbe323e9ec1bf13e3f8674ff5f8f1f4f1e3a3fbe7ff9fb1b9d9e3f2973a7efcd8f1e3278e1fbfad70fcf8daf1e3ebc78fe78e1fef8d8fefa58abd2afe4eec460353a9d151e162ea9899607d8ea48988ec01bbe074efb7974df0d59318d06590dcaa95f6aafb1448532f9e9c5b16497adb5940cb268ae95f3c628da6acdd164ae3df54217dec1773276e1d4dcf3d42208fa64c9e262a757a6ccea2a5acb3e294d39566b947fa548d8ae04558115852dc00c2a3b3bc3936718286b1d1abd5945040e11aace715f74a6875ac061cb409918ada0b0fb1b4480458b26b3dd2291ebd84b84c2b0501c13dd281ec351646ac4281cdfb66556a1a98e8962a4eb959717e7affa183d8c86836408934bff209a1e49c9faa3e148eea4d1272d84009b1827a1246714ca01bb39aecd8ed7860122eb778b826f3860012044eb50562e96fe856d967c24dce4acbc538fa25c011fcc4a464034b57a76d525235a70b7bc05a96dfa05e0aa57d32aa9759d0e0a85b77d2fa3746907f8f827dc34d07310ab1aa5510beb03cde2739e061d22f765b69dd2436a916addbacd49c45df0a5434f06ad64aa5468d7a1a17aea27e702d0d77b7f9e3bb8f3ec07c86e9385c5db75d69d66db7211dcbf740d7ea7552ed8e5386392ab5e57b0a3d8d8c8cceb1d2090953dba9379702d2a19e44f94d81e78d9dfaedb382a19d2d8f509a26a28268a99b1ed703ec71a9f03849e41820f5799ac7320431ca9ac24c3fa3b0f288faede80937b643a79120cd7e7d030e4fcfc05872da848e47105236bc090af88e91f14966e6c804fe9bc47f53f86f1affcde0bf3df86f2ffedb87ff6cfc57c27f65fc57c17f30b947aa2327304bf82a0c02057b52d63896052f3df44ddb720be373eefec9893977f7eed135cd87fc860cb0bbc1b3d96aad89d2fcb54d56781de0de6ae567c00d160c4d79661d1b1fb3f2d3277413d49db5bb20c81c732b3e304a8999744ca7d81e488d41a5a3da98b546c2323b92c3380aabce8e788e063c530c313b39330d4826a6f0cfe4ccf8384185f5d8baf0868c79509541e8d323dcd7883fc7f9a3206364d82cc066470b53c3445ea8354b76cd1bd014ac628ba605ec8da3797f3ccabd4eb759bfdbc15e0251da68c1ab4bd321080c3f16b6cd9d76272b75c889c0bf2d4878c7b135c945bb5269d2adac7283afc82174176fcfe0bdc784697a1ce893fa55730cbd23b3953eb36d074b9cb293cefd8236c749cc609898a63ed38f6acbfac7ef1d5860cc9a1dc77fa43af0784eaa959d6663d680cda93964258c3100631e2922e0526d8655265ec152303380923e2c6ea6738cca9f00259862ea17d4003b677449fd6994c9b67a9dc574086e5d8eda84e18d7f3dd358bf924f6a88066fd6c325a160dbb16b87bdc2fe68394bb1c8eb5e74fb69948bc19c8a2901d435f8515c5935426a08428dad87c02e3bbdef60e07c76d1d0926ad238129bd37735942108a90649bf573a916edca6d350ad89a8d59cc642773184a406829beedccff31e1c02a8788bee25068808202450ba7c272b3d59f3d6782280ba05d7ec139c0ee7cad03a54cf2010e08c656e2a467feb965383b65a8b525ddecbbf3ee49844eeb4b184f799b3593a3906ad547156b6858b1aa3e14195ac6e1276b38c288dc18e5aa05674ed4eb6d3aab9d04f0c0066a338a6a60ae65f8c30045e0f6b23a16ec2e3a1e2447d86ea4525ac0ab339563926e804e2eba8527496b2f490108b0e348d8812f86cd5255f7487b835f428cb14beb7aaa60e0c5a269f385c378a37918220c72e0ef997002e7d8b91ab6fa10a6e58027d1efbc64cdf6daf6e275aa62ca4d778ecd464c2d498159a28fb86e814fd5bb7e0662d2f62147940a223acab84b8cd7b1cc7f03165878eaa515e7d5d1fe525998043037790fc9b185e437904380816036dbb775a303862ed9c6283aafbaa874a8f59f566a557c32'
)
print(dd.encode_protocol())
uu = hsp.bytedata()
uu.decode_protocol(dd.encode_protocol())
print(uu.decode_protocol(dd.encode_protocol()))
print(uu.encode_protocol())

print(uu.raw_data)

print('test finished')
示例#4
0
    def handle(self):  # override method
        global REMOTE_SOCKET_COUNT, LOCAL_SOCKET_COUNT
        try:
            sock = self.connection
            sock.settimeout(15)
            data = sock.recv(4096)
            LOCAL_SOCKET_COUNT += 1
            dec_data = decrypt(data)
            remote = None
            addr = None

            peer_ip, peer_port = sock.getpeername()
            if peer_ip in black_list or peer_ip not in white_list:
                # 若已经在黑名单上, 或者不在白名单里, 则直接拒绝代理
                logging.warning(
                    f"[Socks5Server]rejected a request from {peer_ip}")
                raise Exception('illegal packet recvd!')
            try:
                obj = hsp.handshake()
                if obj.decode_protocol(dec_data) != 'Done':
                    raise Exception('illegal packet recvd!')
                port = int(obj.port)
                addr = obj.addr

            except Exception as e:
                self.refuse_serve()
                exc_type, exc_obj, exc_tb = sys.exc_info()
                fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
                logging.warning(f"{exc_type}  {fname}  {exc_tb.tb_lineno}")
                raise Exception("malformed handshake!")

            # got all required information
            try:
                remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
                REMOTE_SOCKET_COUNT += 1
                remote.settimeout(20)
                remote.connect(
                    (addr, port))  # connect to dst, may fail if blocked by gfw

                # if connect successfully, should sent a random message to unblock the client.
                send_all(
                    sock,
                    encrypt(
                        hsp.handshake(addr=addr,
                                      port=str(port)).encode_protocol()))
                # do exchange
                self.handle_tcp(sock, remote, str(addr))
            except ConnectionRefusedError:
                logging.debug('connection refused: ' + str(addr))
            except socket.timeout:
                logging.debug('TimeOut while connecting to: ' + str(addr))
            except Exception as e:
                self.refuse_serve()
                logging.warning(str(addr))
                logging.warning(e)
                exc_type, exc_obj, exc_tb = sys.exc_info()
                fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
                logging.warning(f"{exc_type}  {fname}  {exc_tb.tb_lineno}")
                # send empty message to browser
        except Exception as e:
            logging.warning(e)
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            logging.warning(f"{exc_type}  {fname}  {exc_tb.tb_lineno}")
        finally:
            if sock is not None:
                sock.close()
                LOCAL_SOCKET_COUNT -= 1
            if remote is not None:
                remote.close()
                REMOTE_SOCKET_COUNT -= 1
            if addr is not None:
                logging.info(f'released resource! {addr}')
示例#5
0
    def handle(self):
        try:
            remote = None
            addr = ""
            sock = self.connection  # local socket [127.1:port]
            sock.settimeout(15)
            # follow SOCKS5 protocol
            sock.recv(262)  # Sock5 Verification packet
            sock.send(
                b"\x05\x00"
            )  # Sock5 Response: '0x05' Version 5; '0x00' NO AUTHENTICATION REQUIRED
            data = sock.recv(65536).strip()

            if data == b'':
                return

            mode = data[1]  # CMD == 0x01 (connect)
            data_to_send = {'type': 'handshake', 'version': 'v1'}
            if mode != 1:
                logging.warning('mode != 1')
                sock.close()
                return

            addrtype = data[3]  # indicate destination address type
            ptr = 4  # next to read index

            if addrtype == 1:  # IPv4
                ip_range = data[ptr:4 + ptr]
                addr = socket.inet_ntoa(data[ptr:4 + ptr])  # get dst addr
                str_addr = addr
                ptr += 4
            elif addrtype == 3:  # FQDN (Fully Qualified Domain Name)
                addr_len = int(data[ptr])  # Domain name's Length
                ptr += 1
                addr = data[ptr:ptr + addr_len]
                str_addr = addr.decode('utf-8')
                ptr += addr_len
            else:
                # not support
                logging.warning('addr_type not support')
                sock.close()
                return
            addr_port = data[ptr:2 + ptr]
            # Parse the big endian port number. Note: The result is a tuple even if it contains exactly one item.
            port = struct.unpack('>H', addr_port)
            data_to_send['dst_port'] = port[0]
            try:
                if '-6' in sys.argv[1:]:  # IPv6 support
                    remote = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
                else:
                    remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY,
                                  1)  # turn off Nagling
                remote.settimeout(20)

                # 随机挑选一个REMOTE_PORT 进行连接
                dst_port = random.randint(
                    0, WORKING_THREAD - 1) + 10 + REMOTE_PORT
                logging.info(f"--------------random port is: {dst_port}")
                remote.connect((SERVER, dst_port))

                # connected to the server, should complete authentication and after the peer has established connection
                # to host.
                # then should let browser send other data

                m = hsp.handshake(addr=str_addr, port=str(port[0]))
                msg = m.encode_protocol()
                send_encrypt(remote, msg)  # encrypted handshake
                # 这里会阻塞
                confirm_msg = remote.recv(4096)

                if b'0x15the_login_invalid_or_the_url_unreachable' == confirm_msg:
                    logging.error(
                        'Error: 1. The url is unreachable for the proxy 2. Or encrypt method mismatch.'
                    )
                    sock.close()
                    return

                # tell the browser we are ready to proxy for you.
                reply = b"\x05\x00\x00\x01"  # VER REP RSV ATYP
                # socks5 protocol needs this. its a must
                reply += socket.inet_aton('192.168.34.34') + struct.pack(
                    ">H", 1030)
                self.wfile.write(reply)  # response packet
                logging.info('requested: %s:%d' % (str_addr, port[0]))

            except ConnectionRefusedError:
                logging.warning("cannnot talk to server")

            except socket.error as es:
                logging.warning(es)
                exc_type, exc_obj, exc_tb = sys.exc_info()
                fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
                logging.warning(f"{exc_type}  {fname}  {exc_tb.tb_lineno}")

                reply = b"\x05\x04\x00\x01"  # host unreachable
                self.wfile.write(reply)  # response packet
                sock.close()
                return

            self.handle_tcp(sock, remote, str_addr)

        except Exception as es:
            logging.warning(es)
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            logging.warning(f"{exc_type}  {fname}  {exc_tb.tb_lineno}")
        finally:
            if sock is not None:
                sock.close()
            if remote is not None:
                remote.close()
            logging.info(f'connection closed.{addr}')
示例#6
0
    def handle(self):
        try:
            sock = self.connection        # local socket [127.1:port]

            # follow SOCKS5 protocol

            sock.recv(262)                # Sock5 Verification packet
            sock.send(b"\x05\x00")         # Sock5 Response: '0x05' Version 5; '0x00' NO AUTHENTICATION REQUIRED

            data = sock.recv(4096).strip()

            if data == b'':
                return

            mode = data[1]           # CMD == 0x01 (connect)
            data_to_send = {}
            data_to_send['type'] = 'handshake'
            data_to_send['version'] = 'v1'
            if mode != 1:
                logging.warn('mode != 1')
                sock.close()
                return


            addrtype = data[3]       # indicate destination address type
            ptr = 4   # next to read index


            if addrtype == 1:             # IPv4
                ip_range = data[ptr:4+ptr]
                addr = socket.inet_ntoa(data[ptr:4+ptr])  # get dst addr

                ptr += 4
                data_to_send['dst_addr'] = {'type':'ip', 'addr': addr}

            elif addrtype == 3:           # FQDN (Fully Qualified Domain Name)

                addr_len = int(data[ptr])          # Domain name's Length
                ptr += 1

                try:
                    addr = data[ptr:ptr+addr_len]

                except:
                    raise Exception('addr_len too long')

                ptr += addr_len

                addr_len = min(addr_len, 255)    # in case the url length is too long

                byte_len_ = bytes([addr_len])   # 0~255

                addr = addr.decode('utf-8') # covert url to string

                data_to_send['dst_addr'] = {'type':'url', 'addr':addr}

            else:
                logging.warn('addr_type not support')
                sock.close()
                # not support
                return
            addr_port = data[ptr: 2+ptr]
            # addr_to_send += addr_port                   # addr_to_send = ATYP + [Length] + dst addr/domain name + port
            port = struct.unpack('>H', addr_port)       # prase the big endian port number. Note: The result is a tuple even if it contains exactly one item.

            data_to_send['dst_port'] = port[0]
            try:

                # reply immediately
                if '-6' in sys.argv[1:]:                # IPv6 support
                    remote = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
                else:
                    remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                remote.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)       # turn off Nagling
                remote.connect((SERVER, REMOTE_PORT))

                # connected to the server, should complete authentication and after the peer has established connection to host.
                # then should let browser send other data

                m = hsp.handshake(addr=addr, port=str(port[0]))
                msg = m.encode_protocol()
                self.send_encrypt(remote, msg)  # encrypted handshake

                confirm_msg = remote.recv(4096)

                if b'0x15the_login_invalid_or_the_url_unreachable' == confirm_msg:
                    logging.error('Error: 1. The url is unreachable for the proxy 2. Or encrypt method mismatch.')
                    sock.close()
                    return


                # tell the browser we are ready to proxy for you.

                reply = b"\x05\x00\x00\x01"  # VER REP RSV ATYP
                # socks5 protocol needs this. its a must
                reply += socket.inet_aton('192.168.34.34') + struct.pack(">H", 1030)
                self.wfile.write(reply)  # response packet




                logging.info('requested: %s:%d' % (addr, port[0]))

            except socket.error as e:
                reply = b"\x05\x04\x00\x01" # host unreachable
                self.wfile.write(reply)  # response packet
                logging.warn(e)
                sock.close()
                return


            self.handle_tcp(sock, remote)



        except Exception as e:
            logging.warn(data)
            logging.warn(e)