Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tracphil/77c21df5c7cfaf93cc5f593651125424 to your computer and use it in GitHub Desktop.
Save tracphil/77c21df5c7cfaf93cc5f593651125424 to your computer and use it in GitHub Desktop.

SSH Tunneling A Multiple Node Span With MacOsX

I needed to get some work done on a jenkins server that unfortunately was behind a firewall, and was inaccessible even with my VPN turned on.

Fortunately I had SSH access to a machine inside the firewall that also had SSH access to the jenkins server. So I knew that there was a way to use SSH tunnelling to get to the jenkins server.

Tunnel between the localhost and the first node.

First I created an SSH tunnel between my local machine and the machine inside the firewall.

SSH -L 8884:localhost:8883 nodeA

So as you can see I am forwarding packets from nodeA's 8883 port to my local's 8884 port.

(Note that I've set up a ~/.ssh/config file with the details on how to access nodeA so that I do not have to be overly verbose.)

I can verify that my tunnel is working with curl:

curl https://localhost:8884
> curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to localhost:8884

Thus, the connection is working but there is no output on the local 8884 port yet because whatever is connected to nodeA's 8883 port does not know how to respond to an HTTP client. (Nothing is connected to that port, so the result is making sense).

Tunnel between the first and second node.

Now I need to create a connection between my jenkins server on nodeB to my access machine (nodeA) in order to close the loop.

To do this I need to open up another terminal window and ssh into nodeA. From nodeA I create a connection to nodeB.

SSH -L 8883:locahost:443 nodeB

This is doing exactly what we did on our local. However testing with curl from within NodeA we will see that there is a response.

curl https://localhost:8883
curl -I -L https://localhost:8883/jenkins/login -k
HTTP/1.1 200 OK

Great so we are getting somewhere. Whatever is connected to localhost:8883 on nodeA knows how to respond to an HTTP client.

If we test from our localhost we should see a response too.

curl https://localhost:8884
curl -I -L https://localhost:8883/jenkins/login -k
HTTP/1.1 200 OK

Sweet. So now we can interact with our jenkins server via localhost:8883

(Optional) Redirect the localhost packets.

In my usecase there was a caveat. Although I could get to the jenkins server this way there was a road block. We had set up Google Auth for logging in and this required access to https://nodeB because of a hard coded redirect from the Google Auth Service. My options where to turn of security on the jenkins server or figure out how to access nodeB on port 443 locally.

Forwarding my local 443 to my local 8884 port should do the trick; However, I don't have SSH access enabled for my local computer.

sudo ssh -L 443:localhost:8884 localhost
ssh: connect to host localhost port 22: Connection refused

So that's not an option.

But then I learned it's possible to redirect packets on MacOsX: https://salferrarello.com/mac-pfctl-port-forwarding

echo "rdr pass inet proto tcp from any to any port 443 -> 127.0.0.1 port 8443" | sudo pfctl -ef -

And that did the trick

curl https://localhost/jenkins/login -I -k -L
HTTP/1.1 200 OK

I finished up by adding the following line to my /etc/hosts file:

127.0.0.1 nodeB

Now Accessing the jenkins server on nodeB from my local works as expected:

curl https://nodeB/jenkins/login -I -k -L
HTTP/1.1 200 OK

Undo local packet forwarding.

Later I may want to undo all these changes.

sudo pfctl -F all -f /etc/pf.conf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment