dlundquist / sniproxy

Proxies incoming HTTP and TLS connections based on the hostname contained in the initial request of the TCP session.
BSD 2-Clause "Simplified" License
2.55k stars 396 forks source link

Need to drop SNI in backend for specified domains #268

Open Nefurtity opened 6 years ago

Nefurtity commented 6 years ago

The firewall will look for SNI field to block some websites, because SNI is plain texts in Client Hello, the server name can be detected easily, and the SSL connection would be blocked.

Need to specify a list of domains in config file, when the Client Hello message coming, look for SNI field, if SNI is bellowing one of the specified domains, drop the SNI e.g. hostname at the backend, the Client Hello message without SNI go through the firewall, finally SSL connection established.

Client Hello                                                Client Hello
...                                                         ...
Length: 84                                                  Length: 84
Server Name Indication: www.blocked.com   -> sniproxy  ->   Supported_groups (len=8)
Supported_groups (len=8)                                    ...
...

However this trick only takes effect for some websites which supports non-SNI SSL, but I believe it is very useful to access a lot of websites behind an SNI sensitivity firewall.

dlundquist commented 6 years ago

While this sounds possible, I think a VPN would be a better solution. I would imagine a firewall could just as easily filter based on the server certificate, or the subject in that certificate. Stripping out the SNI header doesn't seem to buy any meaningful privacy, and encourages increased IP address consumption. Another consideration is increases the complexity of SNIproxy but requiring the TLS protocol module to modify the buffer state. Presently there is no direct dependency between these two modules.

Your welcome to SNIproxy as a base for this application. I would start by introducing a remove_extension(struct Buffer *client_hello, uint16 tls_extention_id) function the TLS module.

jornane commented 6 years ago

Removing the SNI header would probably also yield a different certificate. I also know of servers that will outright reject clients without SNI. I do agree that a VPN is probably a better solution. I don't share the concern about IP address consumption, since there are plenty of IPv6 addresses out there.

Nefurtity commented 6 years ago

I have tried to remove the server name extension field, and increases the padding extension to keep the total TLS record length as the same. But finally, I got Handshake Failure (40)

    605 2.966434       192.168.10.100        192.168.10.53         TLSv1.2  583    Client Hello

Frame 605: 583 bytes on wire (4664 bits), 583 bytes captured (4664 bits)
Ethernet II, Src: Apple_c5:7f:4f (c4:b3:01:c5:7f:4f), Dst: AsustekC_57:6d:d1 (00:26:18:57:6d:d1)
Internet Protocol Version 4, Src: 192.168.10.100, Dst: 192.168.10.53
Transmission Control Protocol, Src Port: 63433, Dst Port: 443, Seq: 1, Ack: 1, Len: 517
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Client Hello
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 512
        Handshake Protocol: Client Hello
            Handshake Type: Client Hello (1)
            Length: 508
            Version: TLS 1.2 (0x0303)
            Random: 17a18c56d3818904c1e374c50f289a68119cf815fb681181...
            Session ID Length: 0
            Cipher Suites Length: 134
            Cipher Suites (67 suites)
            Compression Methods Length: 1
            Compression Methods (1 method)
            Extensions Length: 333
            Extension: server_name (len=18)
            Extension: ec_point_formats (len=4)
            Extension: supported_groups (len=58)
            Extension: signature_algorithms (len=38)
            Extension: next_protocol_negotiation (len=0)
            Extension: application_layer_protocol_negotiation (len=14)
            Extension: padding (len=173)

    625 3.205915       192.168.10.53         163.177.151.110       TLSv1.2  571    Client Hello

Frame 625: 571 bytes on wire (4568 bits), 571 bytes captured (4568 bits)
Ethernet II, Src: AsustekC_57:6d:d1 (00:26:18:57:6d:d1), Dst: NecPlatf_3e:fc:6c (a4:12:42:3e:fc:6c)
Internet Protocol Version 4, Src: 192.168.10.53, Dst: 163.177.151.110
Transmission Control Protocol, Src Port: 41218, Dst Port: 443, Seq: 1, Ack: 1, Len: 517
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Client Hello
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 512
        Handshake Protocol: Client Hello
            Handshake Type: Client Hello (1)
            Length: 508
            Version: TLS 1.2 (0x0303)
            Random: 17a18c56d3818904c1e374c50f289a68119cf815fb681181...
            Session ID Length: 0
            Cipher Suites Length: 134
            Cipher Suites (67 suites)
            Compression Methods Length: 1
            Compression Methods (1 method)
            Extensions Length: 333
            Extension: ec_point_formats (len=4)
            Extension: supported_groups (len=58)
            Extension: signature_algorithms (len=38)
            Extension: next_protocol_negotiation (len=0)
            Extension: application_layer_protocol_negotiation (len=14)
            Extension: padding (len=195)

    627 3.237869       163.177.151.110       192.168.10.53         TLSv1.2  155    Server Hello

Frame 627: 155 bytes on wire (1240 bits), 155 bytes captured (1240 bits)
Ethernet II, Src: NecPlatf_3e:fc:6c (a4:12:42:3e:fc:6c), Dst: AsustekC_57:6d:d1 (00:26:18:57:6d:d1)
Internet Protocol Version 4, Src: 163.177.151.110, Dst: 192.168.10.53
Transmission Control Protocol, Src Port: 443, Dst Port: 41218, Seq: 1, Ack: 518, Len: 101
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Server Hello
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 96
        Handshake Protocol: Server Hello
            Handshake Type: Server Hello (2)
            Length: 92
            Version: TLS 1.2 (0x0303)
            Random: 5a3aa1dcfdfa6dccae60b660fa7240db52644586fd5117df...
            Session ID Length: 32
            Session ID: 7a4f0c12bf370047b994e598439974bdb8a7e271312e084f...
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
            Compression Method: null (0)
            Extensions Length: 20
            Extension: renegotiation_info (len=1)
            Extension: application_layer_protocol_negotiation (len=11)

    629 3.237922       192.168.10.53         192.168.10.100        TLSv1.2  167    Server Hello

Frame 629: 167 bytes on wire (1336 bits), 167 bytes captured (1336 bits)
Ethernet II, Src: AsustekC_57:6d:d1 (00:26:18:57:6d:d1), Dst: Apple_c5:7f:4f (c4:b3:01:c5:7f:4f)
Internet Protocol Version 4, Src: 192.168.10.53, Dst: 192.168.10.100
Transmission Control Protocol, Src Port: 443, Dst Port: 63433, Seq: 1, Ack: 518, Len: 101
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Server Hello
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 96
        Handshake Protocol: Server Hello
            Handshake Type: Server Hello (2)
            Length: 92
            Version: TLS 1.2 (0x0303)
            Random: 5a3aa1dcfdfa6dccae60b660fa7240db52644586fd5117df...
            Session ID Length: 32
            Session ID: 7a4f0c12bf370047b994e598439974bdb8a7e271312e084f...
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
            Compression Method: null (0)
            Extensions Length: 20
            Extension: renegotiation_info (len=1)
            Extension: application_layer_protocol_negotiation (len=11)

    630 3.238239       163.177.151.110       192.168.10.53         TLSv1.2  3638   Certificate

Frame 630: 3638 bytes on wire (29104 bits), 3638 bytes captured (29104 bits)
Ethernet II, Src: NecPlatf_3e:fc:6c (a4:12:42:3e:fc:6c), Dst: AsustekC_57:6d:d1 (00:26:18:57:6d:d1)
Internet Protocol Version 4, Src: 163.177.151.110, Dst: 192.168.10.53
Transmission Control Protocol, Src Port: 443, Dst Port: 41218, Seq: 102, Ack: 518, Len: 3584
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Certificate
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 3579
        Handshake Protocol: Certificate
            Handshake Type: Certificate (11)
            Length: 3575
            Certificates Length: 3572
            Certificates (3572 bytes)

    632 3.238289       192.168.10.53         192.168.10.100        TCP      1514   443 → 63433 [ACK] Seq=102 Ack=518 Win=30080 Len=1448 TSval=28626668 TSecr=491852132 [TCP segment of a reassembled PDU]

Frame 632: 1514 bytes on wire (12112 bits), 1514 bytes captured (12112 bits)
Ethernet II, Src: AsustekC_57:6d:d1 (00:26:18:57:6d:d1), Dst: Apple_c5:7f:4f (c4:b3:01:c5:7f:4f)
Internet Protocol Version 4, Src: 192.168.10.53, Dst: 192.168.10.100
Transmission Control Protocol, Src Port: 443, Dst Port: 63433, Seq: 102, Ack: 518, Len: 1448

    634 3.239616       163.177.151.110       192.168.10.53         TLSv1.2  392    Server Key Exchange

Frame 634: 392 bytes on wire (3136 bits), 392 bytes captured (3136 bits)
Ethernet II, Src: NecPlatf_3e:fc:6c (a4:12:42:3e:fc:6c), Dst: AsustekC_57:6d:d1 (00:26:18:57:6d:d1)
Internet Protocol Version 4, Src: 163.177.151.110, Dst: 192.168.10.53
Transmission Control Protocol, Src Port: 443, Dst Port: 41218, Seq: 3686, Ack: 518, Len: 338
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Server Key Exchange
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 333
        Handshake Protocol: Server Key Exchange
            Handshake Type: Server Key Exchange (12)
            Length: 329
            EC Diffie-Hellman Server Params

    636 3.239632       163.177.151.110       192.168.10.53         TLSv1.2  63     Server Hello Done

Frame 636: 63 bytes on wire (504 bits), 63 bytes captured (504 bits)
Ethernet II, Src: NecPlatf_3e:fc:6c (a4:12:42:3e:fc:6c), Dst: AsustekC_57:6d:d1 (00:26:18:57:6d:d1)
Internet Protocol Version 4, Src: 163.177.151.110, Dst: 192.168.10.53
Transmission Control Protocol, Src Port: 443, Dst Port: 41218, Seq: 4024, Ack: 518, Len: 9
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Server Hello Done
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 4
        Handshake Protocol: Server Hello Done
            Handshake Type: Server Hello Done (14)
            Length: 0

    638 3.249889       192.168.10.53         192.168.10.100        TLSv1.2  1101   Certificate, Server Key Exchange, Server Hello Done

Frame 638: 1101 bytes on wire (8808 bits), 1101 bytes captured (8808 bits)
Ethernet II, Src: AsustekC_57:6d:d1 (00:26:18:57:6d:d1), Dst: Apple_c5:7f:4f (c4:b3:01:c5:7f:4f)
Internet Protocol Version 4, Src: 192.168.10.53, Dst: 192.168.10.100
Transmission Control Protocol, Src Port: 443, Dst Port: 63433, Seq: 2998, Ack: 518, Len: 1035
[3 Reassembled TCP Segments (3584 bytes): #632(1448), #633(1448), #638(688)]
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Certificate
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 3579
        Handshake Protocol: Certificate
            Handshake Type: Certificate (11)
            Length: 3575
            Certificates Length: 3572
            Certificates (3572 bytes)
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Server Key Exchange
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 333
        Handshake Protocol: Server Key Exchange
            Handshake Type: Server Key Exchange (12)
            Length: 329
            EC Diffie-Hellman Server Params
    TLSv1.2 Record Layer: Handshake Protocol: Server Hello Done
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 4
        Handshake Protocol: Server Hello Done
            Handshake Type: Server Hello Done (14)
            Length: 0

    639 3.249924       163.177.151.110       192.168.10.53         TLSv1.2  63     [TCP Spurious Retransmission] , Server Hello Done

Frame 639: 63 bytes on wire (504 bits), 63 bytes captured (504 bits)
Ethernet II, Src: NecPlatf_3e:fc:6c (a4:12:42:3e:fc:6c), Dst: AsustekC_57:6d:d1 (00:26:18:57:6d:d1)
Internet Protocol Version 4, Src: 163.177.151.110, Dst: 192.168.10.53
Transmission Control Protocol, Src Port: 443, Dst Port: 41218, Seq: 4024, Ack: 518, Len: 9
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Server Hello Done
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 4
        Handshake Protocol: Server Hello Done
            Handshake Type: Server Hello Done (14)
            Length: 0

    645 3.330981       192.168.10.100        192.168.10.53         TLSv1.2  192    Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message

Frame 645: 192 bytes on wire (1536 bits), 192 bytes captured (1536 bits)
Ethernet II, Src: Apple_c5:7f:4f (c4:b3:01:c5:7f:4f), Dst: AsustekC_57:6d:d1 (00:26:18:57:6d:d1)
Internet Protocol Version 4, Src: 192.168.10.100, Dst: 192.168.10.53
Transmission Control Protocol, Src Port: 63433, Dst Port: 443, Seq: 518, Ack: 4033, Len: 126
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Client Key Exchange
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 70
        Handshake Protocol: Client Key Exchange
            Handshake Type: Client Key Exchange (16)
            Length: 66
            EC Diffie-Hellman Client Params
    TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
        Content Type: Change Cipher Spec (20)
        Version: TLS 1.2 (0x0303)
        Length: 1
        Change Cipher Spec Message
    TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 40
        Handshake Protocol: Encrypted Handshake Message

    647 3.331042       192.168.10.53         163.177.151.110       TLSv1.2  180    Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message

Frame 647: 180 bytes on wire (1440 bits), 180 bytes captured (1440 bits)
Ethernet II, Src: AsustekC_57:6d:d1 (00:26:18:57:6d:d1), Dst: NecPlatf_3e:fc:6c (a4:12:42:3e:fc:6c)
Internet Protocol Version 4, Src: 192.168.10.53, Dst: 163.177.151.110
Transmission Control Protocol, Src Port: 41218, Dst Port: 443, Seq: 518, Ack: 4033, Len: 126
Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Client Key Exchange
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 70
        Handshake Protocol: Client Key Exchange
            Handshake Type: Client Key Exchange (16)
            Length: 66
            EC Diffie-Hellman Client Params
    TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
        Content Type: Change Cipher Spec (20)
        Version: TLS 1.2 (0x0303)
        Length: 1
        Change Cipher Spec Message
    TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 40
        Handshake Protocol: Encrypted Handshake Message

    649 3.363816       163.177.151.110       192.168.10.53         TLSv1.2  61     Alert (Level: Fatal, Description: Handshake Failure)

Frame 649: 61 bytes on wire (488 bits), 61 bytes captured (488 bits)
Ethernet II, Src: NecPlatf_3e:fc:6c (a4:12:42:3e:fc:6c), Dst: AsustekC_57:6d:d1 (00:26:18:57:6d:d1)
Internet Protocol Version 4, Src: 163.177.151.110, Dst: 192.168.10.53
Transmission Control Protocol, Src Port: 443, Dst Port: 41218, Seq: 4033, Ack: 644, Len: 7
Secure Sockets Layer
    TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
        Content Type: Alert (21)
        Version: TLS 1.2 (0x0303)
        Length: 2
        Alert Message
            Level: Fatal (2)
            Description: Handshake Failure (40)

    651 3.363861       192.168.10.53         192.168.10.100        TLSv1.2  73     Alert (Level: Fatal, Description: Handshake Failure)

Frame 651: 73 bytes on wire (584 bits), 73 bytes captured (584 bits)
Ethernet II, Src: AsustekC_57:6d:d1 (00:26:18:57:6d:d1), Dst: Apple_c5:7f:4f (c4:b3:01:c5:7f:4f)
Internet Protocol Version 4, Src: 192.168.10.53, Dst: 192.168.10.100
Transmission Control Protocol, Src Port: 443, Dst Port: 63433, Seq: 4033, Ack: 644, Len: 7
Secure Sockets Layer
    TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
        Content Type: Alert (21)
        Version: TLS 1.2 (0x0303)
        Length: 2
        Alert Message
            Level: Fatal (2)
            Description: Handshake Failure (40)

@dlundquist Do you have any idea?

Nefurtity commented 6 years ago

After many times retry, remove the server name extension will lead a Handshake Failure (40), or Decrypt Error(51) by different servers. I found that change the hostname to another one which has the same length works.

Client Hello                                                Client Hello
...                                                         ...
Length: 84                                                  Length: 84
Server Name Indication: www.blocked.com   -> sniproxy  ->   Server Name Indication: www.another.com
Supported_groups (len=8)                                    Supported_groups (len=8)
...                                                                                       ...
dlundquist commented 6 years ago

@Nefurtity I didn't analyze your TLS handshakes in detail, but my first through is to check that you updated the TLS record length, handshake length and extension length when you remove the SNI extension. Since you can modify the content of the SNI header without breaking the TLS negotiation, I would suspect that the content of the TLS handshake isn't protected by a message digest later in the handshake. I seem to recall some application proxy that modified the cipher suites to ensure complacence requirements, which would also support this.

I would start by writing a tests for the TLS handshake mutation function similar to the ones in tests/tls.c with a very simple handshake and ensuring the resulting handshake matches one you've modified by hand exactly.

const unsigned char good_data_2[] = {
    // TLS record
    0x16, // Content Type: Handshake
    0x03, 0x01, // Version: TLS 1.0
    0x00, 0x48, // Length
        // Handshake
        0x01, // Handshake Type: Client Hello
        0x00, 0x00, 0x42, // Length
        0x03, 0x03, // Version: TLS 1.2
        // Random
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0x00, // Session ID Length
        0x00, 0x04, // Cipher Suites Length
            0x00, 0x01, // NULL-MD5
            0x00, 0xff, // RENEGOTIATION INFO SCSV
        0x01, // Compression Methods
            0x00, // NULL
        0x00, 0x17, // Extensions Length
            // Extension
            0x00, 0x00, // Extension Type: Server Name
            0x00, 0x0e, // Length
            0x00, 0x0c, // Server Name Indication Length
                0x00, // Server Name Type: host_name
                0x00, 0x09, // Length
                // "localhost"
                0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
            // Extension
            0x00, 0x0f, // Extension Type: Heart Beat
            0x00, 0x01, // Length
            0x01 // Mode: Peer allows to send requests
};

Should be modified into:

const unsigned char good_data_2_mangled[] = {
    // TLS record
    0x16, // Content Type: Handshake
    0x03, 0x01, // Version: TLS 1.0
    0x00, 0x36, // Length
        // Handshake
        0x01, // Handshake Type: Client Hello
        0x00, 0x00, 0x30, // Length
        0x03, 0x03, // Version: TLS 1.2
        // Random
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
        0x00, // Session ID Length
        0x00, 0x04, // Cipher Suites Length
            0x00, 0x01, // NULL-MD5
            0x00, 0xff, // RENEGOTIATION INFO SCSV
        0x01, // Compression Methods
            0x00, // NULL
        0x00, 0x05, // Extensions Length
            // Extension
            0x00, 0x0f, // Extension Type: Heart Beat
            0x00, 0x01, // Length
            0x01 // Mode: Peer allows to send requests
};

As for testing handshakes I would look at feeding your requests to OpenSSL s_server with the debug flag for initial testing.

ysc3839 commented 4 years ago

I tried change the first byte of server name (example.com -> axample.com) and finally got a decrypt error from server. Is it possible to doing this? I guess the client and server would check their handshake packets after finished handshake.