opencoff / go-tunnel

TLS/SSL Tunnel - A modern STunnel replacement written in golang
GNU General Public License v2.0
294 stars 42 forks source link

Simple HTTP -> TLS Configuration #2

Open walkingriver opened 4 years ago

walkingriver commented 4 years ago

I'm wondering whether I could use go-tunnel to provide an on-box proxy to an existing public web service, which is TLS 1.2 only? How would that configuration look? If it's a public service, such as Netflix or Google, I wouldn't need any special certs, right? Thanks!

Is there any additional documentation on the configuration file? What is the bind property used for? No matter what I set it to, it doesn't seem to accept it.

opencoff commented 4 years ago

If I understand you correctly, you have Box A that needs to access a public web service; and the public web service runs TLS 1.2. If so, then yes, you can do this with go-tunnel; here's a fragment of the config file:

listen:
    -   address: 127.0.0.1:9090
        allow: [127.0.0.1/8, 11.0.1.0/24, 11.0.2.0/24]
        deny: []

        timeout:
            connect: 10
            read: 10
            write: 30

        # limit to N reqs/sec globally
        ratelimit:
            global: 2000
            perhost: 30

        connect:
            address: your_public_web_service:port
            tls:
                ca: /path/to/cabundle.crt # server cert verification chain

With the above config - you should be able to connect to 127.0.0.1:9090 and gotun will transparently bridge the packets to a TLS backed connection to your public web service.

Lastly, "bind" is useful when your box has multiple outbound IP addresses and you want to use a specific outgoing IP address. For most users, this option is NOT needed at all.

walkingriver commented 4 years ago

Thanks for the quick reply. Is the CA required for a public website? Say I’m hitting the GitHub API with a bearer token. That wouldn’t require any certificate exchange, right?

walkingriver commented 4 years ago

Would including this as the tls -> ca work? https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt

walkingriver commented 4 years ago

I got it to work. Turns out, we have a corporate certificate bundle. Now I am seeing things like this in our logs.

<1>:2020/01/02 17:25:12.516997 gotun-127.0.0.1:8001: (server.go:421) Accepted new connection from 127.0.0.1:32920
<1>:2020/01/02 17:25:12.518692 gotun-127.0.0.1:8001: (server.go:216) LHS 127.0.0.1:32920-127.0.0.1:8001, RHS 10.xx.xx.xx:58572-10.xx.xx.xx:8443
<1>:2020/01/02 17:25:12.523564 gotun-127.0.0.1:8001: (server.go:239) tls client handshake with 10.xx.xx.xx:8443 complete; Version 0x303, Cipher 0xc02f
<1>:2020/01/02 17:25:12.536736 gotun-127.0.0.1:8001: (server.go:349) 10.xx.xx.xx:58572: nr 0, read err EOF
opencoff commented 4 years ago

That is normal. When one end of the socket closes connection, the end that is reading (i.e., server.go) gets "zero bytes" and in golang, EOF is also set.

Here is a full config file I just tested with; it acts as a HTTP proxy to git.kernel.org:

log: STDOUT
loglevel: DEBUG
listen:

        # Listen on non-TLS connection and bridge to a TLS endpoint
    -   address: :8081
        allow: [127.0.0.1/8, 192.168.0.0/24]
        deny: []

        # TLS connect to https://git.kernel.org
        connect:
            address: 147.75.56.137:443
            tls: # This is the CA bundle on debian systems
                ca: /etc/ssl/certs

And this is how I downloaded via this proxy:

wget -v --max-redirect=1 -O yy \ http://127.0.0.1:8081/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-5.5-rc4.tar.gz

You can see it downloads via the gotun instance. In the end, gotun prints # of bytes transfered via the proxy:

<1>:2020/01/02 19:45:39.167208 gotun-0.0.0.0:8081: (server.go:421) Accepted new connection from 127.0.0.1:33602
<1>:2020/01/02 19:45:39.185274 gotun-0.0.0.0:8081: (server.go:216) LHS 127.0.0.1:33602-127.0.0.1:8081, RHS 192.168.0.190:39338-147.75.56.137:443
<1>:2020/01/02 19:45:39.224188 gotun-0.0.0.0:8081: (server.go:239) tls client handshake with 147.75.56.137:443 complete; Version 0x303, Cipher 0xc02f
<1>:2020/01/02 19:46:36.317476 gotun-0.0.0.0:8081: (server.go:350) 192.168.0.190:39338: nr 0, read err read tcp4 192.168.0.190:39338->147.75.56.137:443: i/o timeout
<2>:2020/01/02 19:46:36.317548 gotun-0.0.0.0:8081: 127.0.0.1:33602: rd 214, wr 174819187; 147.75.56.137:443: rd 174819187, wr 214
walkingriver commented 4 years ago

I think I understand, thanks. I was getting confused because the last test we ran showed these same lines over and over again, and the client never seemed to get a reply. This was using a PHP SOAP library.

wget also seemed to retry multiple times before it was successful. It ended up taking 9.5s to retrieve a 32k WSDL with wget. I wasn't sure if that was the client, the server, or the tunnel.

opencoff commented 4 years ago

Pls check if your service does a redirect to a different server/URL. My first try with www.kernel.org confused me because of the HTTP 3xx redirect. After I put the exact new URL in the wget invocation, I was able to go directly to the destination server via gotunnel.

walkingriver commented 4 years ago

I don't see any redirects. Just multiple attempts to retry before it works.

opencoff commented 4 years ago

do you have any logs or other details to help narrow down the "retries"?

walkingriver commented 4 years ago

Just what I sent you a few days ago. It's those few lines repeated.

opencoff commented 4 years ago

Could you try the latest version (0.4.3) and see if it produces the retries?

walkingriver commented 4 years ago

I don't think I was able to do so, because I'm on RHEL 5. I had to build an older version with a special version of Go. It was actually quite painful just getting to this point. If you have a way to get the latest built and working on RHEL 5, I'd love to speak more.

walkingriver commented 4 years ago

If there is any possibility of continuing this conversation privately, I'd welcome it. My Twitter handle is also @walkingriver

opencoff commented 4 years ago

So, #1: if you are on any linux system and type make on the top-dir of this repo, it will by default build a statically linked executable. You can move this static binary to any linux platform - in theory it should work; assuming of course there is no issue with the syscalls used by the go runtime. I don't have access to any RHEL system. Looking at the golang discussion: https://github.com/golang/go/issues/4989 seems conclusive :-( Also this reddit thread: https://www.reddit.com/r/golang/comments/2u3bb7/running_go_on_centos5/

2. I don't use twitter or any social media; happy to chat privately - sw@herle.net