|
Документ взят из кэша поисковой машины. Адрес
оригинального документа
: http://rtm-cs.sinp.msu.ru/manual/howto/VPN-HOWTO.html
Дата изменения: Thu May 4 20:01:38 2000 Дата индексирования: Mon Oct 1 20:47:05 2012 Кодировка: |
pppd
sshd
pppd
ssh
I work Real Networks, and we needed VPN service. This was my first real project, and I truly learned more about Linux with this than with any other task. I ended up using my experience with that project to write this document, to share with others what I learned, so that they can do ultra-nifty things with Linux too!
I want to first and foremost thank my wife Julie, without her, I wouldn't be where I am today. I also want to thank Arpad Magosanyi, the author of the first VPN mini-howto and pty-redir, the utility that makes all of this possible. Jerry, Rod, Glen, Mark V., Mark W., and David, You guys rock! Thanks for all your help.
This document is broken down into 5 sections.
This section
Basic VPN theory. What is a VPN, and how does it work. Read this if you are entirely new to VPN.
This section describes how a VPN server is set up.
This section describes how a VPN client is set up.
A step by step implementation of a sample VPN setup.
Other bits and pieces of info that you might find helpful.
Copyright (c) by Matthew Wilson. This document may be distributed only subject to the terms and conditions set forth in the LDP License at http://www.linuxdoc.org/COPYRIGHT.html, except that this document must not be distributed in modified form without the author's consent.
The author assumes no responsibility for anything done with this document, nor does he make any warranty, implied or explicit. If you break it, it's not my fault. Remember, what you do here could make very large holes in the security model of your network. You've been warned.
The original VPN mini-HOWTO was written by Arpad Magosanyi in 1997. He has since allowed me to take up the document and extend it into a full HOWTO. All of this would not be possible without his original document. Thanks again Arpad. :)
Version 1.0 of this HOWTO was completed on December 10, 1999.
VPN stands for Virtual Private Network. A VPN uses the Internet as it's transport mechanism, while maintaining the security of the data on the VPN.
Well, there are several answers to that question. It really depends on your network layout. The most common configuration is to have a single main internal network, with remote nodes using VPN to gain full access to the central net. The remote nodes are commonly remote offices or employees working from home. You can also link two smaller (or even larger!) networks to form an even larger single network.
Put simply, to make a VPN, you create a secure tunnel between the two networks and route IP through it. If I've lost you already, you should read The Linux Networking Overview HOWTO to learn about networking with Linux.
Please bear with me, my ASCII art could use some work.
\ \
-------- / / --------
Remote ______| Client |______\ Internet \_____| Server |______ Private
Network | Router | / / | Router | Network
-------- \ \ --------
/ /
Client Router
----------------------------------------------------
| /-> 10.0.0.0/255.0.0.0 \ |
Remote | |--> 172.16.0.0/255.240.0.0 |--> Tunnel >---\ |
Network >---|--|--> 192.168.0.0/255.255.0.0 / |--|----> Internet
192.168.12.0 | | | |
| \-----> 0.0.0.0/0.0.0.0 --> IP Masquerade >--/ |
----------------------------------------------------
Server Router
----------------------------------------------------
| /-> 10.0.0.0/255.0.0.0 \ |
| /--> Tunnel >--|--> 172.16.0.0/255.240.0.0 |--|----> Private
Internet >--|--| \--> 192.168.0.0/255.255.0.0 / | Network
| | | 172.16.0.0/12
| \-----> 0.0.0.0/0.0.0.0 -----> /dev/null | 192.168.0.0/16
----------------------------------------------------
The above diagram shows how the network might be set up. If you don't know what IP Masquerade is, you probably shouldn't be here. Go read the The Linux Networking Overview HOWTO and come back once you've figured it out.
The Client Router is a Linux box acting as the gateway/firewall for the remote network. As you can see, the remote network uses the local net 192.168.12.0. For the sake of a simple diagram, I let out the local routing information in the routers. The basic idea is to route traffic for all of the private networks (10.0.0.0, 172.16.0.0, and 192.168.0.0) through the tunnel. The setup shown here is one way. That is, while the remote network can see the private network, the private network cannot necessarily see the remote network. In order for that to happen, you must specify that the routes are bidirectional.
From the diagram you should also note that all of the traffic coming out of the client router appears to be from the client router, that is, it's all from one IP address. You could route real numbers from inside your network but that brings all sorts of security problems with it.
The system that I describe to implement VPN uses SSH and PPP. Basically I use ssh to create a tunnel connection, and then use pppd to run TCP/IP traffic though it. That's what makes up the tunnel.
The real trick to getting ssh and pppd to play well together is the utility written by Arpad Magosanyi that allows the redirection of standard in and standard out to a pseudo tty. This allows pppd to talk through ssh as if it were a serial line. On the server side, pppd is run as the users shell in the ssh session, completing the link. After that, all you need to do is the routing.
There are of course other ways of setting up a VPN, here are a couple of other systems.
PPTP is a Microsoft protocol for VPN. It is supported under Linux, but is known to have serious security issues. I do not describe how to use it here since it is covered by the Linux VPN Masquerade HOWTO.
IP Sec is a different set of protocols from SSH. I don't actually know all that much about it, so if someone wants to help me out with a description, I'd be most appreciative. Again, I do not describe how to use it here since it is covered by the Linux VPN Masquerade HOWTO.
CIPE is a kernel level network encryption system that may be better suited to enterprise setups. You can find out more about it at the CIPE homepage. I plan on looking into it more, so maybe I'll have info about it here someday.
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.
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.
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.
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.
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.
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
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.
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.
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.
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:
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.
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.)
Now we examine the client end. In practice, when used to allow access to a remote network, this box can easily serve as a Samba (Windows Networking) server, DHCP server, and even an internal web server. The important thing to remember is that this box should be as secure as possible, as it runs your whole remote network.
First things first, you must have ppp available in your kernel. If you are going to allow multiple machines to use the tunnel, then you need to have firewalling and forwarding available too. If the client is going to be a single machine, ppp is enough.
The link is created by running pppd through a pseudo terminal that is
created by pty-redir and connected to ssh. This is done with
something similar to the following sequence of commands:
# /usr/sbin/pty-redir /usr/bin/ssh -t -e none -o 'Batchmode yes' -c blowfish -i /root/.ssh/identity.vpn -l joe > /tmp/vpn-device # sleep 10 # /usr/sbin/pppd `cat /tmp/vpn-device` # sleep 15 # /sbin/route add -net 172.16.0.0 gw vpn-internal.mycompany.com netmask 255.240.0.0 # /sbin/route add -net 192.168.0.0 gw vpn-internal.mycompany.com netmask 255.255.0.0
Simply, what this does is run ssh, redirecting it's input and output to pppd. The options passed to ssh configure it to run without escape characters (-e), using the blowfish crypto algorithm (-c), using the identity file specified (-i), in terminal mode (-t), with the options 'Batchmode yes' (-o). The sleep commands are used to space out the executions of the commands so that each can complete their startup before the next is run.
Of course you don't want to have to type those commands in every time that you want to get the tunnel running. I've written a set of bash scripts that keep the tunnel up and running. You can download the package from here. Just download that an uncompress it into /usr/local/vpn. Inside you'll find three files:
You'll need to edit the vpnd script to set things like the client's
username and the server's names. You may also need to modify the starttunnel
section of the script to specify which networks you are using. Below is a copy of the script
for your reading enjoyment. You'll note that you could put the script in a
different directory, you just need to change the VPN_DIR variable.
#! /bin/bash
#
# vpnd: Monitor the tunnel, bring it up and down as necessary
#
USERNAME=vpn-username
IDENTITY=/root/.ssh/identity.vpn
VPN_DIR=/usr/local/vpn
LOCK_DIR=/var/run
VPN_EXTERNAL=vpn.mycompany.com
VPN_INTERNAL=vpn-internal.mycompany.com
PTY_REDIR=${VPN_DIR}/pty-redir
SSH=${VPN_DIR}/${VPN_EXTERNAL}
PPPD=/usr/sbin/pppd
ROUTE=/sbin/route
CRYPTO=blowfish
PPP_OPTIONS="noipdefault ipcp-accept-local ipcp-accept-remote local noauth nocrtscts lock nodefaultroute"
ORIG_SSH=/usr/bin/ssh
starttunnel () {
$PTY_REDIR $SSH -t -e none -o 'Batchmode yes' -c $CRYPTO -i $IDENTITY -l $USERNAME > /tmp/vpn-device
sleep 15
$PPPD `cat /tmp/vpn-device` $PPP_OPTIONS
sleep 15
# Add routes (modify these lines as necessary)
/sbin/route add -net 10.0.0.0 gw $VPN_INTERNAL netmask 255.0.0.0
/sbin/route add -net 172.16.0.0 gw $VPN_INTERNAL netmask 255.240.0.0
/sbin/route add -net 192.168.0.0 gw $VPN_INTERNAL netmask 255.255.0.0
}
stoptunnel () {
kill `ps ax | grep $SSH | grep -v grep | awk '{print $1}'`
}
resettunnel () {
echo "reseting tunnel."
date >> ${VPN_DIR}/restart.log
eval stoptunnel
sleep 5
eval starttunnel
}
checktunnel () {
ping -c 4 $VPN_EXTERNAL 2>/dev/null 1>/dev/null
if [ $? -eq 0 ]; then
ping -c 4 $VPN_INTERNAL 2>/dev/null 1>/dev/null
if [ $? -ne 0 ]; then
eval resettunnel
fi
fi
}
settraps () {
trap "eval stoptunnel; exit 0" INT TERM
trap "eval resettunnel" HUP
trap "eval checktunnel" USR1
}
runchecks () {
if [ -f ${LOCK_DIR}/tunnel.pid ]; then
OLD_PID=`cat ${LOCK_DIR}/vpnd.pid`
if [ -d /proc/${OLD_PID} ]; then
echo "vpnd is already running on process ${OLD_PID}."
exit 1
else
echo "removing stale pid file."
rm -rf ${LOCK_DIR}/vpnd.pid
echo $$ > ${LOCK_DIR}/vpnd.pid
echo "checking tunnel state."
eval checktunnel
fi
else
echo $$ > ${LOCK_DIR}/vpnd.pid
eval starttunnel
fi
}
case $1 in
check) if [ -d /proc/`cat ${LOCK_DIR}/vpnd.pid` ]; then
kill -USR1 `cat ${LOCK_DIR}/vpnd.pid`
exit 0
else
echo "vpnd is not running."
exit 1
fi ;;
reset) if [ -d /proc/`cat ${LOCK_DIR}/vpnd.pid` ]; then
kill -HUP `cat ${LOCK_DIR}/vpnd.pid`
exit 0
else
echo "vpnd is not running."
exit 1
fi ;;
--help | -h)
echo "Usage: vpnd [ check | reset ]"
echo "Options:"
echo " check Sends running vpnd a USR1 signal, telling it to check"
echo " the tunnel state, and restart if neccesary."
echo " reset Sends running vpnd a HUP signal, telling it to reset"
echo " it's tunnel connection." ;;
esac
ln -sf $ORIG_SSH $SSH
settraps
runchecks
while true; do
i=0
while [ $i -lt 600 ]; do
i=((i+1))
sleep 1
done
eval checktunnel
done
I actually run this setup on pentium 90's running the LRP distribution of Linux. LRP is a distribution of Linux that fits in, and boots off of a single floppy disk. You can learn more about it at http://www.linuxrouter.org/ You can download my LRP package for the VPN client from here. You will also need both the ppp and ssh packages from the LRP site.
In this section, I explain step by step how to set up your VPN system. I'll start with the server, and then move on to the client. For the purposes of an example, I will invent a situation that would require a couple of different kinds of VPN set up.
Let's imagine that we have a company, called mycompany.com. At our head office, we are using the 192.168.0.0 reserved network, breaking the class B into 256 class C networks to allow routing. We have just set up two small remote offices, and want to add them to our network. We also want to allow employees who work from home to be able to use their DSL and cable modem connections instead of making them use dialup. To start, we need to plan things out a little.
I decide that I want to give each remote office a class C network range to allow them to expand as necessary. So, I reserve the 192.168.10.0 and 192.168.11.0 nets. I also decide that for home users, I've got enough numbers that I don't need to masquerade them on the VPN server side. Each client gets it's own internal IP. So, I need to reserve another class C for that, say 192.168.40.0. The only thing that I must now do is to add these ranges to my router. Let's imagine that our company owns a small Cisco (192.168.254.254) that handles all of the traffic through our OC1. Just set routes on the Cisco such that traffic headed to these reserved nets goes to our VPN server (192.168.40.254). I put the VPN server into the home user's net for reasons that should become clear later. We'll name the external interface of the server vpn.mycompany.com, and the internal vpn-internal.mycompany.com.
As for external numbers, we don't need to know them explicitly. You should have your own numbers, supplied by your ISP.
we're going to need a few pieces of software. Get the following packages, and install them where specified.
To start, you'll probably need to rebuild your kernel for the server. You need to make sure that the following kernel options are turned on in addition to basic networking and everything else that you might need. If you've never built your own kernel before, read the Kernel HOWTO.
For 2.0 kernels:
For 2.2 kernels:
If you are building a server that has only one network card, I suggest that you think about buying another, and rewiring your network. The best way to keep your network private is to keep it on it's own wires. So if you do have two network cards, you'll need to know how to configure both of them. We'll use eth0 for the external interface, and eth1 for the internal interface.
We first should configure the external interface of the server. You should already know how to do this, and probably already have it done. If you don't, then do so now. If you don't know how, go back and read the Networking HOWTO
Now we bring up the internal interface. According to the numbers that we've chosen, the internal interface of the server is 192.168.40.254. so we have to configure that interface.
For 2.0 kernels, use the following:
# /sbin/ifconf