sonertari / SSLproxy

Transparent SSL/TLS proxy for decrypting and diverting network traffic to other programs, such as UTM services, for deep SSL inspection
BSD 2-Clause "Simplified" License
385 stars 100 forks source link

Question about transparent SSL/TLS proxying without decryption #35

Open djosip opened 2 years ago

djosip commented 2 years ago

Hello!

First, thank you for the effort and time invested in SSLproxy project.

I went through the available documentation and did some testing but I am unable to conclude if it's possible to achieve transparent SSL/TLS proxying with SSLproxy without content decryption (and without forging of SSL certificates). I have spent some time playing with the options such as -o Divert=no and -o Passthrough=yes as I assumed that if the diverting is turned off and passing through is turned on, the traffic would be "simply" transparently forwarded to the target server running https service.

I have setup something like this using SSLproxy 0.9 on the Centos Linux 7.9 x86_64 with kernel 3.10.0-1160.42.2.el7.x86_64:

,----------,     ,----------,     ,----------,
|          |     |          |     |          |
|  Client  | --> |  Proxy   | --> |  Server  |
|          |     |          |     |          |
'----------'     '----------'     '----------'
 172.16.1.1       192.168.1.1       8.8.8.8

This is the command I used (as root) on the Proxy server: sslproxy -D4 -c /etc/sslproxy/certs/ca.crt -k /etc/sslproxy/certs/ca.key -C /etc/pki/tls/cert.pem -o Divert=no -o Passthrough=yes -o VerifyPeer=no -P https 192.168.1.1 443

For testing purposes on the Client server I used curl and the /etc/hosts file had a line 192.168.1.1 dns.google The curl command looked like: curl -v https://dns.google:443 The Proxy server is able to properly resolve domain names and to connect to https services on the Internet. Note that for the purpose of explaining the issue I used different IP addresses and URL but it doesn't really matter. I didn't use any specific iptables rules as I wanted the SSLproxy to listen on 192.168.1.1:443

Upon execution of the curl command on the Client server, the above setup would result with SSLproxy momentarily opening all remaining ~1024 file descriptors and the client would get the error stating that the connection was reset.

What am I missing? My goal was to pass the https traffic from Client to the Server via SSLproxy and use its filtering feature without decrypting the actual content (I assume that SNI makes this possible).

Kind regards!

sonertari commented 2 years ago

Please see the filtering rules in SSLproxy 0.9.0 (and structured filtering rules on the develop branch to be released soon with v0.9.1). Note that the Passthrough mode is for fail-open configuration for SSL/TLS errors, that's all (if there is no SSL/TLS error, it does not pass the connection through).

So, first, I suggest you use a config file, instead of command line. And in the config file add a rule like the following:

Pass from 172.16.1.1 to *

which should engage the Passthrough mode for all connections originating from 172.16.1.1 (fail-open or not).

I'll see if I need to clarify the documentation for the Passthrough mode.

djosip commented 2 years ago

Initially I used config file but I thought it would be easier to test it if I provide command line arguments. I tested it with different Pass filters including Pass * and Pass from ip 172.16.1.1 to *

No matter what I try, I get almost thousand lines like this:

SNI peek: [dns.google] [complete], fd=1008
Connecting to [192.168.1.1]:443

followed by a single line:

Out of file descriptors

and after that, almost thousand lines like this:

Closing on ssl error without filter match: 192.168.1.1:50002, 192.168.1.1:443, -, -, dns.google, -
Client-side BEV_EVENT_ERROR
Error from bufferevent: 104:Connection reset by peer 0:0:-:0:-:0:-
Closing on ssl error without filter match: 172.16.1.1:44742, 192.168.1.1:443, -, -, dns.google, -

Config file looks like this:

PidFile /var/run/sslproxy.pid
Daemon no
Debug yes
DebugLevel 4
ConnectLog /var/log/sslproxy/connect.log
LogStats yes
StatsPeriod 1
ConnIdleTimeout 120
ExpiredConnCheckPeriod 10
UserDBPath users.db

ProxySpec {
        Proto https
        Addr 192.168.1.1
        Port 443
        Divert no
        Passthrough yes
        VerifyPeer no
        CACert /etc/pki/tls/certs/localhostca.crt
        CAKey /etc/pki/tls/private/localhost.key
        CAChain /etc/pki/tls/cert.pem
        #Pass from ip 172.16.1.1 to sni dns.google port 443
        Pass from ip 172.16.1.1 to *
}

And this is the command line I am using: sslproxy -f /etc/sslproxy/sslproxy.conf -D4 -c /etc/sslproxy/certs/ca.crt -k /etc/sslproxy/certs/ca.key -C /etc/pki/tls/cert.pem

I decided to post the question here because I wasn't sure whether I am doing something wrong or SSLproxy doesn't support passthrough without certificate forging.

On the client side I get this:

# curl -k -v https://dns.google:443
* Expire in 0 ms for 6 (transfer 0x55a03f1a5fb0)
* Expire in 1 ms for 1 (transfer 0x55a03f1a5fb0)
* Expire in 1 ms for 1 (transfer 0x55a03f1a5fb0)
* Expire in 2 ms for 1 (transfer 0x55a03f1a5fb0)
*   Trying 192.168.1.1...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x55a03f1a5fb0)
* Connected to dns.google (192.168.1.1) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to dns.google:443
* Closing connection 0
* curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to dns.google:443
sonertari commented 2 years ago

I don't see any problem with your sslproxy configuration (at least as far as I can see). But if you get the Out of file descriptors error, it reminds me of a possible network configuration issue. I saw such errors if there is a loop, and sslproxy was receiving the traffic passing through it indirectly redirected to itself. Can you post how you redirect traffic to sslproxy?

Also, can you test with a target address/port proxyspec like https 192.168.1.1 443 8.8.8.8 443, just to see if it works? I wonder if target spec can detect a loop (8.8.8.8:443 is the server in your first post).

And also, perhaps you can first test with plain HTTP, instead of HTTPS, to rule out ssl cert issues.

(I have tried Passthrough yes and Divert no options based on your report, and I don't use them often, but they seem to not cause any issues in my test setup.)