====== Connecting to a server's web interface with SSH ====== Sometimes, we have to remotely administer servers. And sometimes, those servers run a daemon that has to be configured using a web interface - e.g. //CUPS// or //ejabberd//. In order to connect to such a web interface, you need a browser, an IP address and a port. In essence, the web interface has to be publicly accessible for that - which is not something you'd usually want. (Firewall configuration, access control, security risks, possibly needing port forwarding, and so on.) Now there are many ways to remotely administer servers using a GUI. All of which have one thing in common: they suck. Either they're free software and they suck (VNC, X forwarding, ...) or they're proprietary and they suck even more (RDP, NX, TeamViewer, ...) //And then there's the whole issue of how it's outright ridiculous to install a GUI on a server in the first place.// ==== Using SSH to connect to web interfaces ==== Fortunately, one can easily bind a server's local port to a client's local port using nothing but SSH. This means you only need to use port 22, and you can use SSH pubkey authentication and encryption for everything you do. All it takes is this command: ssh [username]@[hostname] -T -L [random-local-port]:localhost:[desired-server-port] For example, what if you wanted to access the CUPS admin page as user ''olimex'' on your OLinuXino, with hostname ''lithium'' and IP ''192.168.0.2'', without having to allow TCP traffic on port 631? The username would be ''olimex''\\ The hostname would be ''lithium.local'' (or ''192.168.0.2'')\\ The random local port can be anything, so let's use ''63789''\\ The server port would be ''631'' That would mean: ''**ssh olimex@lithium.local -T -L 63789:localhost:631**'' Enter the password (if you don't have pubkey access), press Enter, open ''localhost:63789'' on the client, and enjoy. Killing a tunnel is also easy: just hit //Ctrl + D// and close the terminal. ==== Using SSH to connect to web interfaces on other servers in your server's LAN ==== So what if you want to connect to the web interface of a daemon running on //another// server in the same LAN as the server you have SSH access to, while the server in question is //not// remotely accessible? Even that is possible! Say, for example, your server is in a LAN and has ''192.168.0.50'' as its internal IP address. ''192.168.0.50:22'' will be forwarded to a random port of the external IP address (let's say ''90.70.60.50:4444''). You have a local user account called ''cindy''. Another server in the LAN has ''192.168.0.60'' as its internal IP address, has ''chatserver'' as its hostname, and let's say it runs the ''ejabberd'' web interface on the default port ''5280''. You can once again use the familiar command: ssh [username]@[external-ip] -p [external-port] -T -L [random-local-port]:[desired-server-in-the-lan]:[desired-server-port] The username would be ''cindy''\\ The external IP would be ''90.70.60.50''\\ The external port would be ''4444''\\ The random local port can be anything, so let's use ''5599''\\ The other server in the LAN would be ''chatserver.local'' (or ''192.168.0.60'')\\ The other server's port would be ''5280'' That would mean: ''**ssh cindy@90.70.60.50 -p 4444 -T -L 5599:192.168.0.60:5280**'' ==== Using SSH as a SOCKS host ==== Sometimes, you can't get by with mapping only a single port. (Think about SSL redirects, for instance.) In that case, you can use SSH to set up a SOCKS host and tell your browser to connect through that as a proxy. Let's say that you want to access multiple things in the LAN of a remote machine you have access to. You can set up a tunnel by using this command: ssh -N -D [random-local-port] [username]@[external-ip] -p [external-port] Let's use the same variables as before: The username would be ''cindy'' The external IP would be ''90.70.60.50'' The external port would be ''4444'' The random local port can be anything, so let's use ''5599'' That would mean: ''**ssh -N -D 5599 cindy@90.70.60.50 -p 4444**'' You can then tell your browser to use the SOCKS host on ''localhost:5599''. With Firefox, you go to //Preferences --> Advanced --> Network --> Settings --> Manual proxy configuration//. With Chromium, the system proxy settings are inherited. So you'll have to set up Network Manager and apply the proxy system-wide. Don't forget to undo the settings once you're done! ==== The local admin is mean! They refuse to forward a port! ==== Sometimes, the local admin is mean and refuses to forward a port. In that case, you won't be able to connect to any SSH server behind NAT. But fear not! SSH can still help you if the local admin cannot. However, you're going to need some infrastructure on your side. At least a publicly accessible server running SSH and preferably nothing else. Sure, if you have a static IP or something like DynDNS you could use your own computer at home, but we really don't recommend it. In the best case scenario, you rent a very basic VPS somewhere, and do a minimal GNU/Linux server install on it. Install ''openssh-server'' and perhaps a firewall that blocks all traffic except port ''22''. Create a user account on that VPS with as little rights as possible. (Just its own home directory, and keep it out of the sudoers file.) In this example, let's say that you have a VPS somewhere with the IP address ''88.55.22.90'', and that you bought a domain name for it: ''datraverse.eu''. You made a user account called ''adminsaremean''. Anyone can connect to this server if they'd guess the password (so choose a strong one). But there's nothing interesting on the server, and the user account can't do anything interesting either. However, it can be very valuable as a //reverse SSH proxy server//. So how does one use a reverse SSH proxy server? Well, from the client side (the machine that wasn't allowed to have its port forwarded), you connect to the publicly accessible proxy server on a random port. Let's say the client's user account is called ''hippopotamus''. Then, you connect to the server from your computer. From that shell, you connect to localhost with the random port you chose. First things first: connecting to your proxy from the client you want remote access to. You'll need to do this: ssh -N -R [random-port]:localhost:22 [username]@[proxy-server] The random port can be anything, so let's use ''1234''\\ The username will be ''adminsaremean''\\ The proxy server will be ''datraverse.eu'' That would mean: hippopotamus@client-somewhere-far-away:~$ ssh -N -R 1234:localhost:22 adminsaremean@datraverse.eu Running this command will show nothing interesting. That's exactly what we want. Of course, you can also script this for easy initiation. Or add it to /etc/rc.local. (But beware that you'll probably want pubkey authentication for that.) Now, on to the server. The remote client, with user account ''hippopotamus'', will be connected to port ''1234'', and you want to open a secure shell from your server to that client. This can be done with the following command (from the proxy server): ssh [username]@localhost -p [random-port] The username will be ''hippopotamus''\\ The random port will be ''1234'' That would mean: adminsaremean@proxy-server:~$ ssh hippopotamus@localhost -p 1234 Now you'll be logged in to the remote client, even though it's behind NAT and maybe even a firewall, no matter how mean the local admin is. ==== So how do I connect to a web interface now? This is really hard! ==== Connecting to a web interface this way, is really hard. You'll need to create two tunnels: one from the client to the server, and one from your computer to the server. So, we're still connected from the client to port ''1234'' on the server. And we want, for instance, access to the CUPS admin page on the client. In order to do so, you'll first need a tunnel from port ''631'' on the client to a random port on the proxy server. Let's use ''5678'' in this example: adminsaremean@proxy-server:~$ ssh hippopotamus@localhost -p 1234 -T -L 5678:localhost:631 If you're hardcore, you can now use ''lynx'' or ''w3m'' to connect to ''localhost:5678'' on your proxy server. But that's not ideal, of course. So from your computer, you connect to the proxy server and bind port ''5678'' (which is forwarded to ''631'' on the client) to another random local port. Let's use ''6070'' in this example: cindy@thinkpad-with-coreboot:~$ ssh adminsaremean@theunconventional.xxx -T -L 6070:localhost:5678 This would mean that port ''6070'' on your computer is forwarded to port ''5678'' on the proxy server, which in turn is forwarded to port ''631'' on ''localhost:1234'' on the proxy server, which is actually port ''22'' on the remote client, meaning that the ''localhost:631'' on the proxy server actually wasn't the local host! Think about this right before you go to bed! ==== FAQ === === I have the remote client set up to only accept the public key on my laptop. Will this still work securely? === Because you're using reverse SSH to connect to the server, this connection will be outgoing rather than incoming from the remote client's end. However, it will treat any connection **to** the random port on the proxy server as an **incoming SSH connection**. So you will have to create a public key on the server with a very strong passphrase, and add it to ''~/.ssh/authorized_keys'' on the remote client. === I don't want my proxy server to allow password authentication. Will that work? === Sure. But you'll need to create SSH keys for every remote client you ever want to manage and every computer you ever want to use to remotely manage those clients, and add those pubkeys to ''~/.ssh/authorized_keys'' on your proxy server. === But if I use pubkey authentication, any clever user on the client side could log in to any other client, which may not even be theirs! === First off, there is no such thing as a clever user. ;)\\ Jokes aside: they'd still need your pubkey password, and you should of course //never// cache that on the proxy server. But if this really bothers you, you can also create a separate user account on the proxy server with each their own SSH keys and //authorized_keys// files. They won't have access to eachother's home directories, but you will have a lot of work storing all those passwords and adding all those keys.