0

I am running a web server that exposes a website locally on the client machine at dev.local.company.com:3888 and I want to access that website on a separate machine on the local network over ssh. Both computers are macOS and the dev.local.company.com domain is equivalent to localhost.

So I ran ssh -L 3888:dev.local.company.com:4000 connors-mbp to attempt to forward dev.local.company content at port 3888 to be viewable on the remote at port 4000. This works and logs into the remote. But when I attempt to start the web server, it displays an error saying port 3888 is already in use and says it is in use by SSH itself.

Why would SSH be "running" on that port if it is supposed to be forwarding it? Error is shown below.

? Something is already running on port 3888. Probably:
  ssh -L 3888:dev.local.company.com:3000 Connors-MBP-3 (pid 38536)
  in /Users/connor

Running in reverse order, server open first then attempt to run ssh -L, ssh shows an error saying that port is already in use by the server. Error from this alternative order shown below.

bind [127.0.0.1]:3888: Address already in use
channel_setup_fwd_listener_tcpip: cannot listen to port: 3888
Connorelsea
  • 147
  • 5
  • I think the underlying problem you have is confusing the different layers of the TCP/IP model. Simplifying a bit, routing (and iptables) runs at a lower level and helps the kernel forward packets - but SSH runs as an application and binds to a port and operates at a higher level - ie its acting as a proxy. – davidgo May 09 '23 at 04:30

1 Answers1

2

The message is correct; the port is in use. "Local" or -L tunnels establish the listener on the SSH client side, forwarding connections to an endpoint through the server; they will naturally conflict with any other listener on the SSH client system.

What you're asking for is the complete opposite – "to be viewable on the remote at port 4000" means the listener needs to be on the SSH server side, with the forward target being your client. This means that if you're SSH-ing from the "web server" machine you need to use the other tunnel type, -R or "remote" tunnels, and you need to swap its listen and target parameters as well:

ssh -R 4000:dev.local.company.com:3888 connors-mbp
-or-
ssh -R 4000:localhost:3888 connors-mbp

Here 4000 (implied localhost:4000) will be the listener on the "connors-mbp" machine, which will forward connections to "dev.local.company.com:3888" on the client machine.

Generally, the syntax is always <new_listen_port>:<connect_host>:<connect_port>. With -L the listen port is on the SSH client side, with -R it's on the SSH server side.


Keep in mind that the web server doesn't know which domain name you used in these options; all it knows is the domain name used in the final URL (i.e. the HTTP "Host:" header sent by your browser), so -R 4000:dev.local.company.com:3888 and -R 4000:localhost:3888 are completely equivalent in your case (as you mention you have an /etc/hosts mapping for the former). If the web server expects to be called with a specific "Host:" header, you'll need to add an identical mapping (also pointing to 127.0.0.1) on the other computer as well.

u1686_grawity
  • 426,297
  • 64
  • 894
  • 966
  • Thank you for this detailed answer, it has cleared up my understanding and sent me down the right path. Haven't fully figured it out yet though, the command was successful on the server machine but trying to access `localhost:4000` on the other machine returns connection reset error. Trying to dive deeper and investigate what is happening currently. Firewall is turned off on both machines in system settings so not sure it could be that. – Connorelsea May 09 '23 at 04:50
  • Is the web server running? Are you in fact ssh'ing _from_ the machine that has the webserver, or _to_ the machine? Either way `ssh -v` would probably reveal the cause, but often it just means the specified target host:port isn't accepting connections. – u1686_grawity May 09 '23 at 04:51
  • The web server is running and accessible on server computer. I ran the ssh -R on the server computer and then attempted the URL on the other computer. Is it possible that the issue could be needing to enable GatewayPorts on either machine? – Connorelsea May 09 '23 at 04:56
  • 1
    GatewayPorts would be needed if you wanted the listener to be accessible from a third system. If you're just accessing localhost:4000 on the same computer that's receiving the SSH connection, it doesn't sound like it should be needed. Restart the connection with `-v` added on the ssh client and see what it prints out whenever you attempt to visit the forwarded port. – u1686_grawity May 09 '23 at 05:00
  • Thanks for the -v tip, output of this attempt to run that on the server computer and then access the forwarded port on the other computer is at the following link. Trying to decipher it currently https://gist.github.com/Connorelsea/1a121915c59a676bf967f6915492cb33 – Connorelsea May 09 '23 at 05:03
  • 1
    That looks normal; is the connection being dropped by the web app server itself then? (Keep in mind SSH isn't an HTTP proxy and it can't inform web apps what domain is being forwarded – if you input "localhost" in your browser, the web app thinks it's being accessed as "localhost" and not as "dev.local.company.com".) – u1686_grawity May 09 '23 at 05:49
  • Thank you! That is definitely correct, I tried to run an alternative web server directly on localhost and was able to access that on the other machine via ssh port forwarding. Any advice on how it would be possible to access the original site while still using the custom domain on the other machine? On the server machine dev.local.company.com is mapped to 127.0.0.1 in /etc/hosts – Connorelsea May 09 '23 at 06:22
  • 1
    If the webapp relies on the domain being preserved (i.e. HTTP "Host:" header), just do the exact same /etc/hosts mapping on the other system, i.e. map the domain to connor-mbp's 127.0.0.1 where the sshd tunnel is listening. (If you were using -L tunnels, then -D proxy mode might have been an alternative, but it has no equivalent for -R tunnels.) – u1686_grawity May 09 '23 at 06:46
  • I had tried that on the other system and thought it wasn't working but it does work and turns out I was missing an issue where I needed to force it to use HTTPS for this specific server. So it's all working perfectly now and I am able to edit the web server code on the remote system and view the website as well. Even forced reloads after change is working on remote, very cool. Thank you a ton for your help it's much appreciated. – Connorelsea May 09 '23 at 07:01
  • "-D proxy mode might have been an alternative, but it has no equivalent for -R tunnels" -- How about `-R 1234`? – Kamil Maciorowski May 09 '23 at 08:20
  • @KamilMaciorowski: I forgot that had been added. – u1686_grawity May 09 '23 at 08:21