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
1
  • 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
    Commented May 9, 2023 at 4:30

1 Answer 1

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.

11
  • 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. Commented May 9, 2023 at 4: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. Commented May 9, 2023 at 4:51
  • 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. Commented May 9, 2023 at 5:00
  • 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".) Commented May 9, 2023 at 5:49
  • 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.) Commented May 9, 2023 at 6:46

You must log in to answer this question.

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