0

I have a bastion server which has access to another server which is otherwise unavailable to the outside world.

I am trying to make it so that I can make an https web call to hit an endpoint on the unavailable server from my localhost for testing purposes. To do this, I have been trying to follow this answer: https://superuser.com/a/1447340/441810

So I edited my /etc/hosts file and added:

127.0.0.1 <firewalled-box>

And then I created the tunnel:

ssh -L 443:<firewalled-box>:443 me@<bastion>

However, when I make the web call on my local machine...

curl -H 'Content-Type: application/json' -H 'Accept: application/json' https://<firewalled-box>/some/path/somewhere/fancy

I get:

curl: (7) Failed to connect to <firewalled-box> port 443: Connection refused
2
  • I do think you will have better luck using a non-standard port. also make sure the tunnel is on 127.0.0.1, not 127.0.1.1 or any of the other addresses in the loopback range. Try netstat -ntlup | grep <portnum> to verify the tunnel is connected and your local port is in a listening state on the address you expect it to be. There is also a question about your httpd and TLS and firewall configuration on the remote target. lots of places this could go wrong. confirm that the site loads via 127.0.0.1 on the target box to confirm its working. also do you have a proxy server in play? good luck. Commented Apr 9, 2020 at 2:40
  • Are you running ssh as a normal user? Because you cannot bind to port 443 unless you are root. Commented Apr 9, 2020 at 6:20

1 Answer 1

0

Diagnosis

Connection refused means curl was not able to connect to whatever it tried to connect to. In your case it tried to connect to your (local) SSH client, unless you did something wrong with /etc/hosts and curl actually tried to connect to the real (or fake-but-wrong) <firewalled-box>.

I assume curl tried to connect to your SSH client. It seems your ssh was not listening or the communication was blocked.

How do I know the problem is between curl and your ssh, not (or at least not yet) between the SSH server and <firewalled-box>?

It's about how port forwarding with SSH works. In case of local forwarding a connection to SSH client needs to be established before the SSH server tries to connect to the target machine. If the latter connection fails then the former will be terminated. But because the former connection has already been established in the first place, the connecting process (curl in your case) will print something like Connection reset by peer, certainly not Connection refused.

In your case Connection refused indicates the connection initiated by curl couldn't be established.


Solution

The problem may be because non-privileged users cannot listen on ports lower than 1024. If you run ssh -L … and the port cannot be used, some ssh implementations will refuse to connect to the SSH server at all, but some will only print a warning and connect anyway. The warning might pass unnoticed if <bastion> cleared the console or printed a long welcome message.

Use -o ExitOnForwardFailure=yes to be sure your ssh listens upon connection.

If low port number is the culprit then running ssh as root will help, although I don't recommend running ssh as root.

Maybe all you need is to use a higher number locally, like -L 1443:<firewalled-box>:443. Then curl should connect to https://<firewalled-box>:1443/….

Note formally <firewalled-box> in -L should be a name/address understood by the <bastion> machine, while <firewalled-box> in curl invocation should be understood by your local machine (thanks to the modified /etc/hosts).


Alternative

I suggest dynamic port forwarding, SOCKS.

  • Remove 127.0.0.1 <firewalled-box> from your /etc/hosts.
  • Invoke ssh -ND 7654 me@<bastion>.
  • Run curl with -x socks5://localhost:7654. If you use <firewalled-box> in the address passed to curl, it will have to resolve locally to an IP address valid remotely; so possibly you will need to modify /etc/hosts anyway.

More details about -D in this answer of mine.

2
  • The problem with the sock5 solution is that ultimately I am not going to use curl, but rather execute code locally which is making a call to the <firewalled-vox> host, so that's why I had that in /etc/hosts, to try to "alias" the host to localhost, so that I don't need to reference "localhost" anywhere when the web call is made.
    – patrick
    Commented Apr 9, 2020 at 4:46
  • Thanks @KamilMaciorowski for pointing out my error. I deleted my previous answer since this covers everything. Commented Apr 9, 2020 at 6:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .