Next Previous Contents

3. Server

This section tells you how to set up the server side of things, I figured that this should go first since without a server, your client is kind of useless.

3.1 Security - keeping people out

Security is very important for a VPN. That's why you're building one in the first place, isn't it? You need to keep a few things in mind while setting up your server.

Trim your daemons

Since this server is going to be on both sides of your firewall, and set up to forward traffic into your network, it's a good idea to secure the box as well as you possibly can. You can read up more on Linux security in the Linux Security HOWTO For my purposes, I've killed everything but sshd and a Roxen Web server. I use the web server to download a couple of files (my scripts, etc) for setting up new machines to access the VPN. I don't use an FTP server since it's harder to configure one to be secure than it is to just make a few files available with a web server. Plus, I only need to be able to download files. If you really want to run different servers on your gateway, you might want to think about restricting access to them to only those machines on your private network.

Don't allow passwords

Yes, it sounds kind of silly, but it got your attention, didn't it? No, you don't use passwords, you disable them completely. All authentication on this machine should be done via ssh's public key authentication system. This way, only those with keys can get in, and it's pretty much impossible to remember a binary key that's 530 characters long.

So how do you do that? It requires editing the /etc/passwd file. The second field contains either the password hash, or alternatively 'x' telling the authentication system to look in the /etc/shadow file. What you do is change that field to read '*' instead. This tells the authentication system that there is no password, and that none should be allowed.

Here's how a typical /etc/passwd file looks:

...
nobody:x:65534:100:nobody:/dev/null:
mwilson:x:1000:100:Matthew Wilson,,,:/home/mwilson:/bin/bash
joe:*:504:101:Joe Mode (home),,,:/home/vpn-users:/usr/sbin/pppd
bill:*:504:101:Bill Smith (home),,,:/home/vpn-users:/usr/sbin/pppd
frank:*:504:101:Frank Jones (home),,,:/home/vpn-users:/usr/sbin/pppd
...
Note that I've done more than just editing the second field. I'll say more about the other fields later on.

3.2 User Access - letting people in

User access is done via ssh's authentication scheme. As I've stated above, this is how users get access to the system, while maintaining a high level of security. If you're not familiar with ssh, check out http://www.ssh.org/ Note that I am using ssh version 1, not version 2. There is a big difference, notably that version 1 is free, and 2 isn't.

Configuring sshd

You'll need to configure sshd. The following options should be present. The idea is to disable password authentication and rhosts authentication. The following options should be present in your /etc/sshd_config file.

PermitRootLogin yes
IgnoreRhosts yes
StrictModes yes
QuietMode no
CheckMail no
IdleTimeout 3d
X11Forwarding no
PrintMotd no
KeepAlive yes
RhostsAuthentication no
RhostsRSAAuthentication no
RSAAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
UseLogin no

3.3 Restricting Users

Now that you're keeping the bad people out, and only letting the good people in, you may need to make sure that the good people behave themselves. This is most easily done by not letting them do anything except run pppd. This may or may not be necessary. I restrict users because the system that I maintain is dedicated to VPN, users have no business doing anything else on it.

sudo or not sudo

There is this neat little program called sudo that allows the admin on a Unix system to grant certain users the ability to run certain programs as root. This is necessary in this case since pppd must be run as root. You'll need to use this method if you want to allow users shell access. Read up on how to setup and use sudo in the sudo man page. Using sudo is best on multi-use systems that typically host a small number of trusted users.

If you decide to not allow users to have shell access, then the best way to keep them from gaining it is to make their shell be pppd. This is done in the /etc/passwd file. You can see above that that is what I did for the last three users. The last field of the /etc/passwd file is the user's shell. You needn't do anything special to pppd in order to make it work. It gets executed as root when the user connects. This is certainly the simplest setup to be had, as well as the most secure. It's the ideal for large scale and corporate systems. I describe exactly what all needs to be done later in this document. You can jump ahead if you like.

3.4 Networking

Now that your users have access to the system, we need to make sure that they have access to the network. We do that by using the Linux kernel's firewalling rules and routing tables. Using the route and ipfwadm commands, we can set up the kernel to handle network traffic in the appropriate ways. For more info on ipfwadm, ipchains and route see the Linux Networking HOWTO.

The Kernel

In order for any of this to work, you must have your kernel configured correctly. If you don't know how to build your own kernel, then you should read the Kernel HOWTO. You'll need to make sure that the following kernel options are turned on in addition to basic networking. I use a 2.0.38 kernel in my system.

For 2.0 kernels:

For 2.2 kernels:

Filter Rules

First, we write firewall filter rules that allow our users to access our internal nets, while restricting them from accessing the outside internet. If this sounds wierd, but think about it this way: they already have access to the internet, so why let them use the tunnel to access the net? It wastes both our bandwidth and processor.

The filter rules that we use depend upon which internal nets we use. But basically they say: "Allow traffic coming from our VPNs that is destined for our internal nets to go there." So how do we do that? As always, it depends. If you are running a 2.0 kernel, you use the tool called ipfwadm, if on the other hand you are using a 2.2 kernel, you use the utility called ipchains.

To set the rules with ipfwadm, run it with options similar to the following:

# /sbin/ipfwadm -F -f
# /sbin/ipfwadm -F -p deny
# /sbin/ipfwadm -F -a accept -S 192.168.13.0/24 -D 172.16.0.0/12

To set the rules with ipchains, run it with options similar to the following:

# /sbin/ipchains -F forward
# /sbin/ipchains -P forward DENY
# /sbin/ipchains -A forward -j ACCEPT -s 192.168.13.0/24 -d 172.16.0.0/12

For those using 2.2 kernels, please read this.

Routing

So, now our users are allowed to access our nets, now we need to tell the kernel where to send the packets. On my system, I have two ethernet cards, one is on the external network, while the other is on the internal network. This helps keep things secure, as outbound traffic is masqueraded by our gateway, and any incoming traffic is filtered and routed by our Cisco. For most setups, the routing should be simple.

What we do is route all traffic destined for the private networks out the internal interface, and all other traffic out the external interface. The specific routing commands depend on which internal nets you are using. Below is an example of what they might look like. These lines are of course in addition to your basic routes for your local nets. I also doubt that you are using all 3 groups of internal numbers.

Assuming that 172.16.254.254 is our internal gateway:

# /sbin/route add -net 10.0.0.0 netmask 255.0.0.0 gw 172.16.254.254 dev eth1
# /sbin/route add -net 172.16.0.0 netmask 255.240.0.0 gw 172.16.254.254 dev eth1
# /sbin/route add -net 192.168.0.0 netmask 255.255.0.0 gw 172.16.254.254 dev eth1

One additional note on routing. If you are using two way routing for say, a remote office, then you will need to do one more thing. You'll need to set up routes on the server that point back to the client. The easiest way to accomplish this is to run a cron job every minute that quietly sets back routes. It's not a big deal if the client isn't connected, route will just spit out an error (that you've conveniently sent to /dev/null.)


Next Previous Contents