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
patrick
  • 101

1 Answers1

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.