[ Thursday, 7 January 2010, fenio ]
Remote access to a computer and internal network’s secured resources – all of it in a simple way that’s following well-known security’s best practices? Sounds impossible, but it’s not. How to achieve it explains Bartosz Feński aka fEnIo.
A computer network with a tight security should be separated from the outside world as much, as it’s possible. It’s often the case. Even if there is a over a dozen of devices(PCs), that play different parts assigned to them in terms of company’s infrastructure, usually there is one that separates them from others, a firewall and a router.
On the assumption that the company’s policy is not too strict we often have an free access to this kind of devices. It can be various internal services, databases, servers of whatever is necessary to run a current company. What if, after work, when we are home safe and sound, we still need to connect to one of those servers that are not accessible outside the internal network.
I’ll describe few ways to do it.
The simplest and, as far as I reckon, the most often case is when just behind firewall there is a 2nd server accessible by SSH, but only for LAN users. It’s similar to the situation, where router does NAT, and server’s addresses behind him are from private address’ classes. Therefore, If we want to log in, we need to log in to the firewall first.
Sounds familiar ? How many times have you actually tried to do the following:
laptop$ ssh router [password1] router$ ssh server [password2] server$
I’ve done it millions of times, and if someone does something often enough there is a chance that it would be so infuriating that eventually someone will try to automate it. SSH share the same story.
Let’s make an configuration file on a laptop ~/.ssh/config:
Host server ProxyCommand ssh router nc %h %p 2> /dev/null
For this configuration to work a program called netcat is necessary, but most of the distributions have it in high-priority packages so it’s often already installed, so… How does the server connection looks like ?
laptop$ ssh server [password1] [password2] server$
Let’s generate a key so we won’t be bothered about all the passwords.
laptop$ ssh-keygen laptop$ ssh-copy-id router laptop$ ssh-copy-id server
Login process is much more easier now:
laptop$ ssh server server$
The coolest thing about it all is the fact, that along with the possibility of logging in to a device that is not public-accessible, we also get the full set of SSH features. There is no problem in using scp, sshfs, forwarding Xs or to set a tunnel to other device through a server.
But what if…
laptop -> router1 -> router2 -> ... -> routerN -> server
There are no barriers to add several devices to ~/.ssh/config and automate the whole login process even if u need to log in to few middle devices before logging in to the right one. You just need to define the right proxy command.
SSH problem is solved, but what if the service we try to get to is, for example, a WWW server? We can use text browsers from the device we logged in, but it’s not really elegant or convenient.
We can use,mentioned earlier, port forwarding, that along with automatic login to different devices is a pretty flexible solution, but we need to remember to add certain SSH commands to every service or setting it all up in ~/.ssh/config)….
… but SSH function SOCKS saves the day:
laptop$ ssh -D 8080 router [password1] router$
If we generated a key, then we don’t need to give a password. We need to set up localhost as a SOCKS server and port 8080 in our browser. All connections will be tunneled to the router and visible for the WWW server as if they were initiated from this device.
Not every applications let’s you use SOCKS server though, but there is a cure. It’s called tsocks. It’s a simple program, that with the help of LD_PRELOAD variable, makes applications use the alternative versions of the connect(), sendto(), socket() functions. Thanks to that the applications can use middle servers almost without any dedicated configuration, unconsciously if we may use this term in reference to binary beings.
The configuration file should look as follows:
server = 127.0.0.1 server_type = 5 server_port = 8080
Now the applications, we’d like to “deceive” should be run:
laptop$ tsocks application_without_socks_support
As I’ve just presented, with SSH and a simple program we can quite easily organize our work environment and bypass limitations caused by a firewall. We can’t solve all our problems though. Let’s take our old FTP for example. It needs 2 ports to communicate, so it can’t be deceived in the way shown above. Moreover, if there is 40 services run on 30 devices behind firewall SSH configuration will be exceptionally complex and hard to maintain.
Perfect would be a solution, in which our laptop with a certain address’ class simply connects to through a channel to the targeted devices in a way, that the device knows the connection came from a secured and trusted network.
OpenVPN solves the problem. To the contrary to SSH-based solutions, that works on 7th layer (application), OpenVPN works on 3rd (network)or even 2nd (transport) layer so it’s entirely transparent for the software. Moreover, it comes with authentication and encryption, so we don’t loose anything comparing to SSH.
Although since version 4.3 OpenSSH makes 2/3 layer tunneling possible,
but its configuration stands next to impossible.
OpenVPN allows making advanced configurations and, for instance, setting up a secured connection between several corporate branches. I’ll limit the example and only show how to gain access in the case described at the beginning of this article. Laptop will be a client and a VPN server will be configured on a router.
I assume, that openvpn package is installed on the laptop and the router. Let’s generate a key (that will be used to encrypt and authenticate the transmission) on the router.
router$ openvpn --genkey --secret /etc/openvpn/static.key
And a configuration file /etc/openvpn/server.conf:
dev tun ifconfig 10.8.0.1 10.8.0.2 secret static.key
10.8.x class’ addresses will be used to set up a tunnel. You are free to choose your own addresses.
One thing left is to run the server:
router$ sudo /etc/init.d/openvpn start
We should get one more interface
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 inet addr:10.8.0.1 P-t-P:10.8.0.2 Mask:255.255.255.255 UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:100 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Moreover we need to unlock the 1194 port in firewall setup.
We copy generated static.key on the laptop and we create client configuration file /etc/openvpn/client.conf:
remote routers_address dev tun ifconfig 10.8.0.2 10.8.0.1 secret static.key route 192.168.0.0 255.255.255.0
Now we switch routers_address to its actual address. Route option will make a new record in routing table visible and from now all transfer is directed to the set up tunnel.
Last but not least thing we have to do is to run VPN on the laptop:
laptop$ sudo /etc/init.d/openvpn start
Let’s look at the routing table:
10.8.0.1 0.0.0.0 255.255.255.255 UH 0 0 0 tun0 192.168.0.0 10.8.0.1 255.255.255.0 UG 0 0 0 tun0
That’s the way to set up the simplest configuration. Of course, as everything, It has its flaws. For example, everyone who has the key can access our network – sometimes though the key may fall into the wrong hands. OpenVPN has its own, more sophisticated authentication methods – simply get the generated key password-protected, but its security is far beyond this article framework.
Translated from Polish: Kamil Zawadzki