Python 如何检测SSTP流量?

Python 如何检测SSTP流量?,python,communication,vpn,network-protocols,tunneling,Python,Communication,Vpn,Network Protocols,Tunneling,我正在写一个程序来检测VPN流量。 据我所知,隧道协议的检测与防火墙规则一样简单,使用专用端口: PPTP:端口1723/TCP OpenVPN:端口1194 L2TP:端口1701/UDP 我的问题是SSTP,因为它使用的是广泛使用的端口443 所以我有两个问题: 我是否太天真了,认为我只能通过它们的端口来检测这些VPN隧道协议 是否有人知道如何检测SSTP并将其流量与使用TLS/SSL(甚至使用DPI)的任何其他类型/应用程序区别开来 我附加了一段Python代码,用于检测上述端口中的通信

我正在写一个程序来检测VPN流量。 据我所知,隧道协议的检测与防火墙规则一样简单,使用专用端口:

PPTP:端口1723/TCP

OpenVPN:端口1194

L2TP:端口1701/UDP

我的问题是SSTP,因为它使用的是广泛使用的端口443

所以我有两个问题:

  • 我是否太天真了,认为我只能通过它们的端口来检测这些VPN隧道协议
  • 是否有人知道如何检测SSTP并将其流量与使用TLS/SSL(甚至使用DPI)的任何其他类型/应用程序区别开来
  • 我附加了一段Python代码,用于检测上述端口中的通信

    import dpkt
    import socket
    
    # -------------------------- Globals
    
    # VPN PORTS
    import common
    import dal
    
    protocols_strs = {"pp2e_gre": "1723/TCP PP2P_GRE_PORT",
                      "openvpn": "1194 OPENVPN_PORT",
                      "ike": "500/UDP IKE_PORT",
                      "l2tp_ipsec": "1701/UDP L2TP_IPSEC_PORT"
                      }
    
    port_protocols = {1723: 'pp2e_gre',
                      1194: 'openvpn',
                      500: 'ike',
                      1701: 'l2tp_ipsec'
                      }
    
    # Dict of sets holding the protocols sessions
    protocol_sessions = {"pp2e_gre": [],
                         "openvpn": [],
                         "ike": [],
                         "l2tp_ipsec": []}
    
    
    # -------------------------- Functions
    def is_bidirectional(five_tuple, protocol):
        """
        Given a tuple and protocol check if the connection is bidirectional in the protocol
        :param five_tuple:
        :return: True of the connection is bidirectional False otherwise
        """
        src_ip = five_tuple['src_ip']
        dest_ip = five_tuple['dest_ip']
    
        # Filter the sessions the five tuple's ips spoke in
        ike_sessions = filter(lambda session: (session['src_ip'] == src_ip and session['dest_ip'] == dest_ip)
                                              or
                                              (session['dest_ip'] == src_ip and session['src_ip'] == dest_ip),
                              protocol_sessions[protocol])
        # Return true if 2 session (1 for each direction) were found
        return len(ike_sessions) == 2
    
    
    def print_alert(timestamp, protocol, five_tuple):
        """
        Print alert description to std
        :param timestamp:
        :param protocol:
        :param five_tuple:
        :return:
        """
        print timestamp, ":\t detected port %s communication (%s:%s ---> %s:%s)" % \
                         (protocol, five_tuple['src_ip'], five_tuple['src_port'], five_tuple['dest_ip'],
                          five_tuple['dest_port'])
    
    
    def pp2e_gre_openvpn_ike_handler(five_tuple):
        # Get protocol
        protocol = five_tuple['protocol']
    
        # Clear old sessions in db
        dal.remove_old_sessions(five_tuple['timestamp'], 'vpn_sessions')
    
        # Clear old sessions in cache
        protocol_sessions[protocol] = common.clear_old_sessions(five_tuple, protocol_sessions[protocol])
    
        # If session already exists - return
        if common.check_if_session_exists(five_tuple, protocol_sessions[protocol]):
            session_to_update = common.get_session(five_tuple, protocol_sessions[protocol])
            session_to_update['timestamp'] = five_tuple['timestamp']
            return
    
        # Update DB
        dal.upsert_vpn_session(five_tuple)
    
        # Add to cache
        protocol_sessions[protocol].append(five_tuple)
    
        # Print alert
        print_alert(five_tuple['timestamp'], protocols_strs[protocol], five_tuple)
    
    
    def l2tp_ipsec_handler(five_tuple):
        if five_tuple in protocol_sessions['l2tp_ipsec']:
            return
    
        # If bi-directional IKE protocol performed earlier - alert
        if not is_bidirectional(five_tuple, 'ike'):
            return
    
        protocol_sessions['l2tp_ipsec'].append(five_tuple)
        print_alert(five_tuple['timestamp'], protocols_strs['l2tp_ipsec'], five_tuple)
    
    
    # -------------------------- VPN ports jump tables
    tcp_vpn_ports = {1723: pp2e_gre_openvpn_ike_handler,
                     1194: pp2e_gre_openvpn_ike_handler}
    
    udp_vpn_ports = {500: pp2e_gre_openvpn_ike_handler,
                     1701: l2tp_ipsec_handler,
                     1194: pp2e_gre_openvpn_ike_handler}
    
    
    # -------------------------- Functions
    def process_packet(timestamp, packet):
        """
        Given a packet process it for detecting a VPN communication
    
        :param packet:
        :param timestamp:
        :return:
        """
        # Parse the input
        eth_frame = dpkt.ethernet.Ethernet(packet)
    
        # Check if IP
        if eth_frame.type != dpkt.ethernet.ETH_TYPE_IP:
            return
    
        # If not IP return
        ip_frame = eth_frame.data
    
        # if TCP or UDP
        if ip_frame.p not in (dpkt.ip.IP_PROTO_TCP, dpkt.ip.IP_PROTO_UDP):
            return
    
        # Extract L3 frame
        frame = ip_frame.data
    
        # Extract ports
        frame_ports = (frame.sport, frame.dport)
    
        # get VPN ports in session
        detected_ports = set(tcp_vpn_ports).intersection(frame_ports)
    
        # If TCP VPN port was not detected return
        if not detected_ports:
            return
    
        # Get detected port
        port = detected_ports.pop()
    
        # Translate port to str
        protocol_str = port_protocols[port]
    
        # Choose handler by port
        handler = tcp_vpn_ports[port]
    
        # Extract 5-tuple parameters from frames
        five_tuple = {'src_ip': socket.inet_ntoa(ip_frame.src),
                      'dest_ip': socket.inet_ntoa(ip_frame.dst),
                      'src_port': frame.sport,
                      'dest_port': frame.dport,
                      'protocol': protocol_str,
                      'timestamp': timestamp}
    
        # Invoke the chosen handler
        handler(five_tuple)
    
  • “我是否太天真,认为我只能通过其端口检测这些VPN隧道协议?”
  • “OpenVPN的端口号是1194,但是任何介于1和65535之间的端口号都可以使用。如果不提供“端口”选项,将使用1194

    因此,如果您的代码根据字典条目查找1194流量,那么您将只捕获默认的开放VPN流

  • SSTP消息使用HTTPS协议的SSL通道加密。所以我不知道你会如何识别这个流量,因为它是加密的。()