We are using a cloud server (Debian Squeeze) where public ports on a public IP route traffic to internal servers. We are looking for a way to use IPTables and ssh where based on some part of the ssh connection string (or something along these lines) iptables will reroute the ssh connection to the "right" internal server. This would allow us to use one common public port, and then re-route ssh connections to individual servers.

So, for example we hope to do something like the following:

  • user issues ssh connection (public key encryption) such as ssh -X -v -p xxx user@xxx.xxx.xxx.xxx but maybe adds something into the string for iptables to use
  • iptables uses some part of that string or some means to re-route the connection to an internal server using something like

    iptables -t nat -A PREROUTING ! -s xxx.xxx.xxx.0/24 -m tcp -p tcp --dport $EXTPORT -j DNAT --to-destination $HOST:$INTPORT

    ....where $HOST is the internal ip of a server, $EXTPORT is the common public facing port and $INTPORT is the internal server port.

It appears that the "string" aspect of iptables does not do what we want.

We can currently route based on the IP table syntax we're using, but rely on having a separate public port for each server and are hoping to use one common public port and then re-route to specific internal servers based on some part of the ssh connection string or some other means.

Any suggestions? Thanks!


That is not possible. The communication between you and the ssh server is fully encrypted, iptables has no way to look inside the packet and thus can only match based on the IP/port on the sending and receiving side.

I would set up different ports on the public-accessible machine and forward them via iptables to the machines in the background and then do something like this in your ssh client config (~/.ssh/config):

Host machineA
        HostName your-public-machine
        Port 12341

Host machineB
        HostName your-public-machine
        Port 12342

Host machineC
        HostName your-public-machine
        Port 12343

With this config you can just run ssh machineA, ssh machineB or ssh machineC and get to the correct machine.

  • Thanks Zhenech! May be misunderstanding on our part (apologies if so), but we hope to route all traffic through a single "public" cloud provider port. Will your suggestion support this? E.g., we have clientA and clientB. Each connects via ssh over the cloud provider's public port 22 to pubic facing server0. From there, public facing server0 would reroute clientA to serverA and clientB to serverB. We can do this now, but have to use two public cloud provider ports. Also, and we didn't mention, we can send keys to the clients, but won't have further access to their ssh configs. Thx! – senrabdet Nov 4 '12 at 13:01
  • 1
    Okay, so if you do not want to have different ports and cannot distribute a config, this changes a lot :) What you could do is you could have a special user on your public box and the customers always connect with their public key to that user. And this user has some hacky ~/.ssh/authorized_keys that executes a command depending on the key used (this is usually used to allow only rsync or git via SSH). See linux.die.net/man/8/sshd for the "AUTHORIZED_KEYS FILE FORMAT" and its "command" parameter. The command then would be "ssh customer-server" :) – zhenech Nov 4 '12 at 14:20
  • Thanks zhenech - just check post again, and saw your follow up response. Will check it out! – senrabdet Dec 2 '12 at 13:45
  • thanks again for the response. We're trying to implement your (great) suggestion, but have some "newbie" questions about what ssh keys get generated and stored where... First, we assume: -we create the special user "specialuser" on "Server0" (the "Host") -we are trying to ssh from "Client1" over port 22 that connects to "Server0" and then gets forwarded via port 222 to "Server1" - we generate the rsa key pair on Client1 Q1: We assume we are putting the "command=" in the authorized_keys file on Server0 - is that right? Q2: if the private key is on Client1, is the same public key put in the auth – senrabdet Dec 10 '12 at 14:02
  • Small point. The SSH connection is not fully encrypted when the connection is being established. The initial handshake where the client and server tell each other their supported SSH versions, ciphers, authentication methods etc are all unencrypted, and form the base for the DH key exchange. However SSH clients generally do not send anything until the server has identified itself, so a connection has to be established before any identifying information is available, at which point it is too late to route the connection elsewhere. – Leigh Dec 10 '12 at 14:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.