LDP/LDP/howto/docbook/VPN-HOWTO.xml

2575 lines
78 KiB
XML

<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book>
<bookinfo>
<title>VPN HOWTO</title>
<author>
<firstname>Matthew D.</firstname> <surname>Wilson</surname>
<affiliation>
<address><email>matthew@shinythings.com</email></address>
</affiliation>
</author>
<pubdate>Dec 1999</pubdate>
<revhistory id="revhistory">
<revision>
<revnumber>2.0</revnumber>
<date>2002-05-30</date>
<authorinitials>tab</authorinitials>
<revremark>Updated to Docbook 4.1 and applied GFDL per Matthew Wilson</revremark>
</revision>
<revision>
<revnumber>1.0</revnumber>
<date>1999-12-01</date>
<authorinitials>mdw</authorinitials>
<revremark>Initial release</revremark>
</revision>
</revhistory>
<abstract>
<para>This HOWTO describes how to set up a Virtual Private Network with Linux.</para>
</abstract>
</bookinfo>
<toc></toc>
<chapter id="introduction">
<title>Introduction</title>
<sect1>
<title>Why I wrote this HOWTO</title>
<para>
I work at 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!
</para>
</sect1>
<sect1>
<title>Acknowledgements and Thanks</title>
<para>
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.
</para>
</sect1>
<sect1>
<title>Format of this document</title>
<para>
This document is broken down into 5 chapters.
</para>
<para>
<variablelist>
<varlistentry>
<term>Section 1: Introduction</term>
<listitem>
<para>This section</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Section 2: Theory</term>
<listitem>
<para>Basic VPN theory. What is a VPN, and how does it work. Read this if you are entirely new to VPN.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Section 3: Server</term>
<listitem>
<para>This section describes how a VPN server is set up.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Section 4: Client</term>
<listitem>
<para>This section describes how a VPN client is set up.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Section 5: Implementation</term>
<listitem>
<para>A step by step implementation of a sample VPN setup.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Section 6: Addenda</term>
<listitem>
<para>Other bits and pieces of info that you might find helpful.</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect1>
<sect1>
<title>Legal Information</title>
<sect2>
<title>Copyright</title>
<para>Copyright (c) 2002 Matthew D. Wilson.</para>
<para>Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
</para>
</sect2>
<sect2>
<title>Disclaimer</title>
<para>
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.
</para>
</sect2>
<sect2 id="gfdl">
<title>GNU Free Documentation License</title>
<!-- - GNU Project - Free Software Foundation (FSF) -->
<!-- LINK REV="made" HREF="mailto:webmasters@gnu.org" -->
<para>Version 1.1, March 2000</para>
<blockquote>
<para>Copyright (C) 2000 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.</para>
</blockquote>
</sect2>
<sect2 id="gfdl-0">
<title>PREAMBLE</title>
<para>The purpose of this License is to make a manual, textbook,
or other written document "free" in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it,
with or without modifying it, either commercially or
noncommercially. Secondarily, this License preserves for the
author and publisher a way to get credit for their work, while not
being considered responsible for modifications made by
others.</para>
<para>This License is a kind of "copyleft", which means that
derivative works of the document must themselves be free in the
same sense. It complements the GNU General Public License, which
is a copyleft license designed for free software.</para>
<para>We have designed this License in order to use it for manuals
for free software, because free software needs free documentation:
a free program should come with manuals providing the same
freedoms that the software does. But this License is not limited
to software manuals; it can be used for any textual work,
regardless of subject matter or whether it is published as a
printed book. We recommend this License principally for works
whose purpose is instruction or reference.</para>
</sect2>
<sect2 id="gfdl-1">
<title>APPLICABILITY AND DEFINITIONS</title>
<para>This License applies to any manual or other work that
contains a notice placed by the copyright holder saying it can be
distributed under the terms of this License. The "Document",
below, refers to any such manual or work. Any member of the
public is a licensee, and is addressed as "you".</para>
<para>A "Modified Version" of the Document means any work
containing the Document or a portion of it, either copied
verbatim, or with modifications and/or translated into another
language.</para>
<para>A "Secondary Section" is a named appendix or a front-matter
section of the Document that deals exclusively with the
relationship of the publishers or authors of the Document to the
Document's overall subject (or to related matters) and contains
nothing that could fall directly within that overall subject.
(For example, if the Document is in part a textbook of
mathematics, a Secondary Section may not explain any mathematics.)
The relationship could be a matter of historical connection with
the subject or with related matters, or of legal, commercial,
philosophical, ethical or political position regarding
them.</para>
<para>The "Invariant Sections" are certain Secondary Sections
whose titles are designated, as being those of Invariant Sections,
in the notice that says that the Document is released under this
License.</para>
<para>The "Cover Texts" are certain short passages of text that
are listed, as Front-Cover Texts or Back-Cover Texts, in the
notice that says that the Document is released under this
License.</para>
<para>A "Transparent" copy of the Document means a
machine-readable copy, represented in a format whose specification
is available to the general public, whose contents can be viewed
and edited directly and straightforwardly with generic text
editors or (for images composed of pixels) generic paint programs
or (for drawings) some widely available drawing editor, and that
is suitable for input to text formatters or for automatic
translation to a variety of formats suitable for input to text
formatters. A copy made in an otherwise Transparent file format
whose markup has been designed to thwart or discourage subsequent
modification by readers is not Transparent. A copy that is not
"Transparent" is called "Opaque".</para>
<para>Examples of suitable formats for Transparent copies include
plain ASCII without markup, Texinfo input format, LaTeX input
format, SGML or XML using a publicly available DTD, and
standard-conforming simple HTML designed for human modification.
Opaque formats include PostScript, PDF, proprietary formats that
can be read and edited only by proprietary word processors, SGML
or XML for which the DTD and/or processing tools are not generally
available, and the machine-generated HTML produced by some word
processors for output purposes only.</para>
<para>The "Title Page" means, for a printed book, the title page
itself, plus such following pages as are needed to hold, legibly,
the material this License requires to appear in the title page.
For works in formats which do not have any title page as such,
"Title Page" means the text near the most prominent appearance of
the work's title, preceding the beginning of the body of the
text.</para>
</sect2>
<sect2 id="gfdl-2">
<title>VERBATIM COPYING</title>
<para>You may copy and distribute the Document in any medium,
either commercially or noncommercially, provided that this
License, the copyright notices, and the license notice saying this
License applies to the Document are reproduced in all copies, and
that you add no other conditions whatsoever to those of this
License. You may not use technical measures to obstruct or
control the reading or further copying of the copies you make or
distribute. However, you may accept compensation in exchange for
copies. If you distribute a large enough number of copies you
must also follow the conditions in section 3.</para>
<para>You may also lend copies, under the same conditions stated
above, and you may publicly display copies.</para>
</sect2>
<sect2 id="gfdl-3">
<title>COPYING IN QUANTITY</title>
<para>If you publish printed copies of the Document numbering more
than 100, and the Document's license notice requires Cover Texts,
you must enclose the copies in covers that carry, clearly and
legibly, all these Cover Texts: Front-Cover Texts on the front
cover, and Back-Cover Texts on the back cover. Both covers must
also clearly and legibly identify you as the publisher of these
copies. The front cover must present the full title with all
words of the title equally prominent and visible. You may add
other material on the covers in addition. Copying with changes
limited to the covers, as long as they preserve the title of the
Document and satisfy these conditions, can be treated as verbatim
copying in other respects.</para>
<para>If the required texts for either cover are too voluminous to
fit legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto
adjacent pages.</para>
<para>If you publish or distribute Opaque copies of the Document
numbering more than 100, you must either include a
machine-readable Transparent copy along with each Opaque copy, or
state in or with each Opaque copy a publicly-accessible
computer-network location containing a complete Transparent copy
of the Document, free of added material, which the general
network-using public has access to download anonymously at no
charge using public-standard network protocols. If you use the
latter option, you must take reasonably prudent steps, when you
begin distribution of Opaque copies in quantity, to ensure that
this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you
distribute an Opaque copy (directly or through your agents or
retailers) of that edition to the public.</para>
<para>It is requested, but not required, that you contact the
authors of the Document well before redistributing any large
number of copies, to give them a chance to provide you with an
updated version of the Document.</para>
</sect2>
<sect2 id="gfdl-4">
<title>MODIFICATIONS</title>
<para>You may copy and distribute a Modified Version of the
Document under the conditions of sections 2 and 3 above, provided
that you release the Modified Version under precisely this
License, with the Modified Version filling the role of the
Document, thus licensing distribution and modification of the
Modified Version to whoever possesses a copy of it. In addition,
you must do these things in the Modified Version:</para>
<orderedlist numeration="upperalpha">
<listitem><para>Use in the Title Page
(and on the covers, if any) a title distinct from that of the
Document, and from those of previous versions (which should, if
there were any, be listed in the History section of the
Document). You may use the same title as a previous version if
the original publisher of that version gives permission.</para>
</listitem>
<listitem><para>List on the Title Page,
as authors, one or more persons or entities responsible for
authorship of the modifications in the Modified Version,
together with at least five of the principal authors of the
Document (all of its principal authors, if it has less than
five).</para>
</listitem>
<listitem><para>State on the Title page
the name of the publisher of the Modified Version, as the
publisher.</para>
</listitem>
<listitem><para>Preserve all the
copyright notices of the Document.</para>
</listitem>
<listitem><para>Add an appropriate
copyright notice for your modifications adjacent to the other
copyright notices.</para>
</listitem>
<listitem><para>Include, immediately
after the copyright notices, a license notice giving the public
permission to use the Modified Version under the terms of this
License, in the form shown in the Addendum below.</para>
</listitem>
<listitem><para>Preserve in that license
notice the full lists of Invariant Sections and required Cover
Texts given in the Document's license notice.</para>
</listitem>
<listitem><para>Include an unaltered
copy of this License.</para>
</listitem>
<listitem><para>Preserve the section
entitled "History", and its title, and add to it an item stating
at least the title, year, new authors, and publisher of the
Modified Version as given on the Title Page. If there is no
section entitled "History" in the Document, create one stating
the title, year, authors, and publisher of the Document as given
on its Title Page, then add an item describing the Modified
Version as stated in the previous sentence.</para>
</listitem>
<listitem><para>Preserve the network
location, if any, given in the Document for public access to a
Transparent copy of the Document, and likewise the network
locations given in the Document for previous versions it was
based on. These may be placed in the "History" section. You
may omit a network location for a work that was published at
least four years before the Document itself, or if the original
publisher of the version it refers to gives permission.</para>
</listitem>
<listitem><para>In any section entitled
"Acknowledgements" or "Dedications", preserve the section's
title, and preserve in the section all the substance and tone of
each of the contributor acknowledgements and/or dedications
given therein.</para>
</listitem>
<listitem><para>Preserve all the
Invariant Sections of the Document, unaltered in their text and
in their titles. Section numbers or the equivalent are not
considered part of the section titles.</para>
</listitem>
<listitem><para>Delete any section
entitled "Endorsements". Such a section may not be included in
the Modified Version.</para>
</listitem>
<listitem><para>Do not retitle any
existing section as "Endorsements" or to conflict in title with
any Invariant Section.</para>
</listitem>
</orderedlist>
<para>If the Modified Version includes new front-matter sections
or appendices that qualify as Secondary Sections and contain no
material copied from the Document, you may at your option
designate some or all of these sections as invariant. To do this,
add their titles to the list of Invariant Sections in the Modified
Version's license notice. These titles must be distinct from any
other section titles.</para>
<para>You may add a section entitled "Endorsements", provided it
contains nothing but endorsements of your Modified Version by
various parties--for example, statements of peer review or that
the text has been approved by an organization as the authoritative
definition of a standard.</para>
<para>You may add a passage of up to five words as a Front-Cover
Text, and a passage of up to 25 words as a Back-Cover Text, to the
end of the list of Cover Texts in the Modified Version. Only one
passage of Front-Cover Text and one of Back-Cover Text may be
added by (or through arrangements made by) any one entity. If the
Document already includes a cover text for the same cover,
previously added by you or by arrangement made by the same entity
you are acting on behalf of, you may not add another; but you may
replace the old one, on explicit permission from the previous
publisher that added the old one.</para>
<para>The author(s) and publisher(s) of the Document do not by
this License give permission to use their names for publicity for
or to assert or imply endorsement of any Modified Version.</para>
</sect2>
<sect2 id="gfdl-5">
<title>COMBINING DOCUMENTS</title>
<para>You may combine the Document with other documents released
under this License, under the terms defined in section 4 above for
modified versions, provided that you include in the combination
all of the Invariant Sections of all of the original documents,
unmodified, and list them all as Invariant Sections of your
combined work in its license notice.</para>
<para>The combined work need only contain one copy of this
License, and multiple identical Invariant Sections may be replaced
with a single copy. If there are multiple Invariant Sections with
the same name but different contents, make the title of each such
section unique by adding at the end of it, in parentheses, the
name of the original author or publisher of that section if known,
or else a unique number. Make the same adjustment to the section
titles in the list of Invariant Sections in the license notice of
the combined work.</para>
<para>In the combination, you must combine any sections entitled
"History" in the various original documents, forming one section
entitled "History"; likewise combine any sections entitled
"Acknowledgements", and any sections entitled "Dedications". You
must delete all sections entitled "Endorsements."</para>
</sect2>
<sect2 id="gfdl-6">
<title>COLLECTIONS OF DOCUMENTS</title>
<para>You may make a collection consisting of the Document and
other documents released under this License, and replace the
individual copies of this License in the various documents with a
single copy that is included in the collection, provided that you
follow the rules of this License for verbatim copying of each of
the documents in all other respects.</para>
<para>You may extract a single document from such a collection,
and distribute it individually under this License, provided you
insert a copy of this License into the extracted document, and
follow this License in all other respects regarding verbatim
copying of that document.</para>
</sect2>
<sect2 id="gfdl-7">
<title>AGGREGATION WITH INDEPENDENT WORKS</title>
<para>A compilation of the Document or its derivatives with other
separate and independent documents or works, in or on a volume of
a storage or distribution medium, does not as a whole count as a
Modified Version of the Document, provided no compilation
copyright is claimed for the compilation. Such a compilation is
called an "aggregate", and this License does not apply to the
other self-contained works thus compiled with the Document, on
account of their being thus compiled, if they are not themselves
derivative works of the Document.</para>
<para>If the Cover Text requirement of section 3 is applicable to
these copies of the Document, then if the Document is less than
one quarter of the entire aggregate, the Document's Cover Texts
may be placed on covers that surround only the Document within the
aggregate. Otherwise they must appear on covers around the whole
aggregate.</para>
</sect2>
<sect2 id="gfdl-8">
<title>TRANSLATION</title>
<para>Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section
4. Replacing Invariant Sections with translations requires
special permission from their copyright holders, but you may
include translations of some or all Invariant Sections in addition
to the original versions of these Invariant Sections. You may
include a translation of this License provided that you also
include the original English version of this License. In case of
a disagreement between the translation and the original English
version of this License, the original English version will
prevail.</para>
</sect2>
<sect2 id="gfdl-9">
<title>TERMINATION</title>
<para>You may not copy, modify, sublicense, or distribute the
Document except as expressly provided for under this License. Any
other attempt to copy, modify, sublicense or distribute the
Document is void, and will automatically terminate your rights
under this License. However, parties who have received copies, or
rights, from you under this License will not have their licenses
terminated so long as such parties remain in full
compliance.</para>
</sect2>
<sect2 id="gfdl-10">
<title>FUTURE REVISIONS OF THIS LICENSE</title>
<para>The Free Software Foundation may publish new, revised
versions of the GNU Free Documentation License from time to time.
Such new versions will be similar in spirit to the present
version, but may differ in detail to address new problems or
concerns. See <ulink url="http://www.gnu.org/copyleft/">http://www.gnu.org/copyleft/</ulink>.</para>
<para>Each version of the License is given a distinguishing
version number. If the Document specifies that a particular
numbered version of this License "or any later version" applies to
it, you have the option of following the terms and conditions
either of that specified version or of any later version that has
been published (not as a draft) by the Free Software Foundation.
If the Document does not specify a version number of this License,
you may choose any version ever published (not as a draft) by the
Free Software Foundation.</para>
</sect2>
<sect2 id="gfdl-11">
<title>How to use this License for your documents</title>
<para>To use this License in a document you have written, include
a copy of the License in the document and put the following
copyright and license notices just after the title page:</para>
<blockquote><para>
Copyright (c) YEAR YOUR NAME.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1
or any later version published by the Free Software Foundation;
with the Invariant Sections being LIST THEIR TITLES, with the
Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
</para></blockquote>
<para>If you have no Invariant Sections, write "with no Invariant
Sections" instead of saying which ones are invariant. If you have
no Front-Cover Texts, write "no Front-Cover Texts" instead of
"Front-Cover Texts being LIST"; likewise for Back-Cover
Texts.</para>
<para>If your document contains nontrivial examples of program
code, we recommend releasing these examples in parallel under your
choice of free software license, such as the GNU General Public
License, to permit their use in free software.</para>
</sect2>
</sect1>
<sect1>
<title>Document History</title>
<para>
The original <citetitle pubwork="article">VPN mini-HOWTO</citetitle> was written by
Arpad Magosanyi, <email>mag@bunuel.tii.matav.hu</email>, 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. :)
</para>
<para>
Version 1.0 of this HOWTO was completed on December 10, 1999.
</para>
</sect1>
<sect1>
<title>Related Documents</title>
<para>
<itemizedlist>
<listitem>
<para>
<ulink url="/HOWTO/Networking-Overview-HOWTO.html">Networking Overview HOWTO</ulink>
</para>
</listitem>
<listitem>
<para>
<ulink url="/HOWTO/NET3-4-HOWTO.html">Networking HOWTO</ulink>
</para>
</listitem>
<listitem>
<para>
<ulink url="/HOWTO/VPN-Masquerade-HOWTO.html">VPN-Masquerade HOWTO</ulink>
</para>
</listitem>
</itemizedlist>
</para>
</sect1>
</chapter>
<chapter id="theory">
<title>Theory</title>
<sect1>
<title>What is a VPN?</title>
<para>
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.
</para>
</sect1>
<sect1>
<title>But really, what IS a VPN?</title>
<para>
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 small (or
large) networks to form an even larger single network.
</para>
</sect1>
<sect1>
<title>So how does it work?</title>
<para>
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 <ulink url="http://www.tldp.org/HOWTO/Networking-Overview-HOWTO.html">
The Linux Networking Overview HOWTO</ulink> to learn more about networking
with Linux.</para>
<para>
Here are some diagrams to illustrate this concept:
</para>
<screen>
\ \
-------- / / --------
Remote ______| Client |______\ Internet \_____| Server |______ Private
Network | Router | / / | Router | Network
-------- \ \ --------
/ /
Client Router
----------------------------------------------------
| /-&#62; 10.0.0.0/255.0.0.0 \ |
Remote | |--&#62; 172.16.0.0/255.240.0.0 |--&#62; Tunnel &#62;---\ |
Network &#62;---|--|--&#62; 192.168.0.0/255.255.0.0 / |--|----&#62; Internet
192.168.12.0 | | | |
| \-----&#62; 0.0.0.0/0.0.0.0 --&#62; IP Masquerade &#62;--/ |
----------------------------------------------------
Server Router
----------------------------------------------------
| /-&#62; 10.0.0.0/255.0.0.0 \ |
| /--&#62; Tunnel &#62;--|--&#62; 172.16.0.0/255.240.0.0 |--|----&#62; Private
Internet &#62;--|--| \--&#62; 192.168.0.0/255.255.0.0 / | Network
| | | 172.16.0.0/12
| \-----&#62; 0.0.0.0/0.0.0.0 -----&#62; /dev/null | 192.168.0.0/16
----------------------------------------------------
</screen>
<para>
The above diagram shows how the network might be set up. If you don't
know what IP Masquerading is, you should probably read the
<ulink url="/HOWTO/Networking-Overview-HOWTO.html">The Linux Networking
Overview HOWTO</ulink> and come back once you understand how it works.
</para>
<para>
The Client Router is a Linux box acting as the gateway/firewall for the
remote network. The remote network uses the local IP address
192.168.12.0. For the sake of a simple diagram, I left out the local
routing information on 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.
</para>
<para>
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, all from
one IP address. You could route real numbers from inside your
network but that brings all sorts of security problems with it.
</para>
</sect1>
<sect1>
<title>SSH and PPP
</title>
<para>
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.
</para>
<para>
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.
</para>
</sect1>
<sect1>
<title>Alternative VPN Systems</title>
<para>
There are of course other ways of setting up a VPN. Here are a couple of
other systems:
</para>
<sect2>
<title>PPTP</title>
<para>
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 <ulink url="http://www.tldp.org/HOWTO/VPN-Masquerade-HOWTO.html">Linux VPN Masquerade HOWTO</ulink>.</para>
</sect2>
<sect2>
<title>IP Sec</title>
<para>
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 <ulink url="http://www.tldp.org/HOWTO/VPN-Masquerade-HOWTO.html">Linux VPN Masquerade HOWTO</ulink>.</para>
</sect2>
<sect2>
<title>CIPE</title>
<para>
CIPE is a kernel level network encryption system that may be better
suited to enterprise setups. You can find out more about it at <ulink url="http://sites.inka.de/sites/bigred/devel/cipe.html">the CIPE homepage</ulink>.</para>
</sect2>
</sect1>
</chapter>
<chapter>
<title>Server</title>
<para>
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.
</para>
<sect1>
<title>Security - keeping people out</title>
<para>
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.
</para>
<sect2>
<title>Trim your daemons</title>
<para>
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 <ulink url="/HOWTO/Security-HOWTO.html">Linux Security HOWTO</ulink>.
In this case I 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.
</para>
</sect2>
<sect2>
<title>Don't allow passwords</title>
<para>
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.
</para>
<para>
So how do you do that? It requires editing the <filename>/etc/passwd</filename> file. The
second field contains either the password hash, or alternatively 'x'
telling the authentication system to look in the <filename>/etc/shadow</filename> file. What
you do is change that field to read <quote>*</quote> instead. This tells the
authentication system that there is no password, and that none should be
allowed.
</para>
<para><anchor id="passwd" xreflabel="/etc/passwd file"/>Here's how a typical /etc/passwd file looks:</para>
<screen>
...
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
...
</screen>
<para>
Note that I've done more than just editing the second field. I'll
explain the other fields later on.
</para>
</sect2>
</sect1>
<sect1>
<title>User Access - letting people in</title>
<para>
User access is done via ssh's authentication scheme. As 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
<ulink url="http://www.ssh.org/">http://www.ssh.org/</ulink>. 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.
</para>
<sect2>
<title>Configuring <command>sshd</command></title>
<para>
You'll need to configure <command>sshd</command>.
The idea is to disable password authentication and rhosts
authentication. The following options should be present in your
<filename>/etc/sshd&lowbar;config</filename> file.
</para>
<screen>
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
</screen>
</sect2>
</sect1>
<sect1>
<title>Restricting Users</title>
<para>
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, so users have no business doing anything else on it.
</para>
<sect2>
<title>sudo or not sudo </title>
<para>
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.
</para>
<para>
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 pppd. This is
done in the /etc/passwd file. You can see <xref linkend="passwd"/>
that I did this 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, and ideal for large scale and corporate
systems. I describe exactly what all needs to be done later in this
document. You can <xref linkend="user-accounts"/> if you
like.
</para>
</sect2>
</sect1>
<sect1>
<title>Networking</title>
<para>
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 <command>route</command> and
<command>ipfwadm</command> commands, we can set up the kernel to handle network
traffic in the appropriate ways. For more info on <command>ipfwadm</command>,
<command>ipchains</command> and <command>route</command> see the
<ulink url="http://www.tldp.org/HOWTO/Linux-Networking-HOWTO.html">Linux Networking HOWTO</ulink>.</para>
<sect2>
<title>The Kernel</title>
<para>
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 <ulink url="http://www.tldp.org/HOWTO/Kernel-HOWTO.html">
Kernel HOWTO</ulink>. 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.
</para>
<para>
For 2.0 kernels:
<itemizedlist>
<listitem>
<para>
CONFIG&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;FORWARD
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;ROUTER
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;MASQUERADE (optional)
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;MASQUERADE&lowbar;ICMP (optional)
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;PPP
</para>
</listitem>
</itemizedlist>
</para>
<para>
For 2.2 kernels:
<itemizedlist>
<listitem>
<para>
CONFIG&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;ADVANCED&lowbar;ROUTER
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;ROUTER
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;MASQUERADE (optional)
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;MASQUERADE&lowbar;ICMP (optional)
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;PPP
</para>
</listitem>
</itemizedlist>
</para>
</sect2>
<sect2>
<title>Filter Rules</title>
<para>
First, we write firewall filter rules that allow our users to access our
internal nets, while restricting them from accessing the outside
internet. This sounds strange, but since the users
already have access to the internet, why let them use the tunnel to
access the net? It wastes both bandwidth and processor resources.
</para>
<para>
The filter rules that we use depend upon which internal nets we use,
but translate to: "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 <command>ipfwadm</command>, but if you are using a
2.2 kernel, you use the utility called <command>ipchains</command>.
</para>
<para>
To set the rules with <command>ipfwadm</command>, run it with options similar to
the following:
</para>
<screen>
&num; /sbin/ipfwadm -F -f
&num; /sbin/ipfwadm -F -p deny
&num; /sbin/ipfwadm -F -a accept -S 192.168.13.0/24 -D 172.16.0.0/12
</screen>
<para>
To set the rules with <command>ipchains</command>, run it with options similar to
the following:
</para>
<screen>
&num; /sbin/ipchains -F forward
&num; /sbin/ipchains -P forward DENY
&num; /sbin/ipchains -A forward -j ACCEPT -s 192.168.13.0/24 -d 172.16.0.0/12
</screen>
<para>
For those using 2.2 kernels, please read <xref linkend="ipv4forwarding"/>.
</para>
</sect2>
<sect2>
<title>Routing</title>
<para>
Now that users are allowed to access our nets, 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 the gateway, and any incoming traffic is filtered and
routed by the Cisco Router. For most setups, the routing should be simple.
</para>
<para>
Next, 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:
</para>
<screen>
Assuming that 172.16.254.254 is the internal gateway:
&num; /sbin/route add -net 10.0.0.0 netmask 255.0.0.0 gw 172.16.254.254 dev eth1
&num; /sbin/route add -net 172.16.0.0 netmask 255.240.0.0 gw 172.16.254.254 dev eth1
&num; /sbin/route add -net 192.168.0.0 netmask 255.255.0.0 gw 172.16.254.254 dev eth1
</screen>
<para>
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
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. If the client is not
connected, <command>route</command> will just spit out an error (that you've
conveniently sent to <filename>/dev/null</filename>.)
</para>
</sect2>
</sect1>
</chapter>
<chapter id="client">
<title>Client</title>
<para>
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.
</para>
<sect1>
<title>The Kernel</title>
<para>
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.
</para>
</sect1>
<sect1>
<title>Bring up the link</title>
<para>
The link is created by running <command>pppd</command> through a pseudo terminal that is
created by <command>pty-redir</command> and connected to <command>ssh</command>. This is done with
something similar to the following sequence of commands:
</para>
<screen>
&num; /usr/sbin/pty-redir /usr/bin/ssh -t -e none -o 'Batchmode yes' -c blowfish -i /root/.ssh/identity.vpn -l joe &#62; /tmp/vpn-device
&num; sleep 10
&num; /usr/sbin/pppd `cat /tmp/vpn-device`
&num; sleep 15
&num; /sbin/route add -net 172.16.0.0 gw vpn-internal.mycompany.com netmask 255.240.0.0
&num; /sbin/route add -net 192.168.0.0 gw vpn-internal.mycompany.com netmask 255.255.0.0
</screen>
<para>
What this does is run ssh, redirecting the 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.
</para>
</sect1>
<sect1>
<title>Scripting
</title>
<para>
If 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 <ulink url="http://www.shinythings.com/vpnd/vpnd.tar.gz">here</ulink>. Just download and uncompress it into /usr/local/vpn.
Inside you'll find three files:
</para>
<para>
<itemizedlist>
<listitem>
<para>
vpnd: The script that controls the tunnel connection.
</para>
</listitem>
<listitem>
<para>
check-vpnd: a script to be run by cron to check that vpnd is still up.
</para>
</listitem>
<listitem>
<para>
pty-redir: a small executable needed to initialize the tunnel.
</para>
</listitem>
</itemizedlist>
</para>
<para>
You'll need to edit the
<anchor id="vpn-script" xreflabel="vpnd script"/><command>vpnd</command>
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&lowbar;DIR variable.
</para>
<screen>
#! /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 &#62; /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 &#62;&#62; ${VPN_DIR}/restart.log
eval stoptunnel
sleep 5
eval starttunnel
}
checktunnel () {
ping -c 4 $VPN_EXTERNAL 2&#62;/dev/null 1&#62;/dev/null
if [ $? -eq 0 ]; then
ping -c 4 $VPN_INTERNAL 2&#62;/dev/null 1&#62;/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 $$ &#62; ${LOCK_DIR}/vpnd.pid
echo "checking tunnel state."
eval checktunnel
fi
else
echo $$ &#62; ${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
</screen>
</sect1>
<sect1>
<title>LRP - Linux Router Project</title>
<para>
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 <ulink url="http://www.linuxrouter.org/">http://www.linuxrouter.org/</ulink>
You can download my LRP package for the VPN client from <ulink url="http://www.shinythings.com/vpnd/vpnd.lrp">here</ulink>. You will
also need both the ppp and ssh packages from the LRP site.
</para>
</sect1>
</chapter>
<chapter id="implemenetation">
<title>Implementation</title>
<para>
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.
</para>
<sect1>
<title>Planning</title>
<para>
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.
</para>
<para>
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.
</para>
<para>
As for external numbers, we don't need to know them explicitly. You
should have your own numbers, supplied by your ISP.
</para>
</sect1>
<sect1>
<title>Gather the tools
</title>
<para>
We will need a few pieces of software. Get the following
packages, and install them where specified.
</para>
<sect2>
<title>For the Server:
</title>
<para>
<itemizedlist>
<listitem>
<para>
pppd (version 2.3 or greater)
</para>
</listitem>
<listitem>
<para>
ssh (version 1.2.26 or better)
</para>
</listitem>
</itemizedlist>
</para>
</sect2>
<sect2>
<title>For the Client:
</title>
<para>
<itemizedlist>
<listitem>
<para>
pppd (same version as server)
</para>
</listitem>
<listitem>
<para>
ssh
</para>
</listitem>
<listitem>
<para>
<ulink url="ftp://ftp.vein.hu/ssa/contrib/mag/pty-redir-0.1.tar.gz">pty-redir</ulink>
</para>
</listitem>
</itemizedlist>
</para>
</sect2>
</sect1>
<sect1>
<title>Server: Build the kernel
</title>
<para>
To start, you 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 <ulink url="/HOWTO/Kernel-HOWTO.html">Kernel HOWTO</ulink>.</para>
<para>
For 2.0 kernels:
<itemizedlist>
<listitem>
<para>
CONFIG&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;FORWARD
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;ROUTER
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;PPP
</para>
</listitem>
</itemizedlist>
</para>
<para>
For 2.2 kernels:
<itemizedlist>
<listitem>
<para>
CONFIG&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;ADVANCED&lowbar;ROUTER
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;ROUTER
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;PPP
</para>
</listitem>
</itemizedlist>
</para>
</sect1>
<sect1>
<title>Server: Configure Networking</title>
<para>
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.
</para>
<sect2>
<title>Configuring the interfaces</title>
<para>
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 <ulink url="/HOWTO/NET3-4-HOWTO.html">Networking HOWTO</ulink>
</para>
<para>
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.
</para>
<para>
For 2.0 kernels, use the following:
</para>
<screen>
&num; /sbin/ifconfig eth1 192.168.40.254 netmask 255.255.255.0 broadcast 192.168.40.255
&num; /sbin/route add -net 192.168.40.0 netmask 255.255.255.0 dev eth1
</screen>
<para>
For 2.2 kernels, use the following:
</para>
<screen>
&num; /sbin/ifconfig eth1 192.168.40.254 netmask 255.255.255.0 broadcast 192.168.40.255
</screen>
<para>
That gets our basic interfaces up. You can now talk to machines on
both local networks that are attached to the server.
</para>
</sect2>
<sect2>
<title>Setting routes</title>
<para>
We can now talk to machines on our local nets, but we can't get to the rest
of our internal network. That requires a few more lines of code. In order
to reach the other machines on other subnets, we need have a route that tells
traffic to go to the Cisco router. Here's that line:
</para>
<screen>
&num; /sbin/route add -net 192.168.0.0 gw 192.168.254.254 netmask 255.255.0.0 dev eth1
</screen>
<para>
That line tells the kernel that any traffic destined for the 192.168.0.0 network
should go out eth1, and that it should be handed off to the Cisco. Traffic for
our local net still gets where it is supposed to because the routing tables
are ordered by the size of the netmask. If we were to have other internal nets
in our network, we would have a line like the above for each net.
</para>
</sect2>
<sect2>
<title>Making filter rules</title>
<para>
Now that we can reach every machine that we could need to, we need to write
the firewall filtering rules that allow or deny access through the VPN server.
</para>
<para>
To set the rules with <command>ipfwadm</command>, run it like so:
</para>
<screen>
&num; /sbin/ipfwadm -F -f
&num; /sbin/ipfwadm -F -p deny
&num; /sbin/ipfwadm -F -a accept -S 192.168.40.0/24 -D 192.168.0.0/16
&num; /sbin/ipfwadm -F -a accept -b -S 192.168.10.0/24 -D 192.168.0.0/16
&num; /sbin/ipfwadm -F -a accept -b -S 192.168.11.0/24 -D 192.168.0.0/16
</screen>
<para>
To set the rules with <command>ipchains</command>, run it like so:
</para>
<screen>
&num; /sbin/ipchains -F forward
&num; /sbin/ipchains -P forward DENY
&num; /sbin/ipchains -A forward -j ACCEPT -s 192.168.40.0/24 -d 192.168.0.0/16
&num; /sbin/ipchains -A forward -j ACCEPT -b -s 192.168.10.0/24 -d 192.168.0.0/16
&num; /sbin/ipchains -A forward -j ACCEPT -b -s 192.168.11.0/24 -d 192.168.0.0/16
</screen>
<para>
This tells the kernel to deny all traffic except for the traffic that is coming
from the 192.168.40.0/24 network and destined for the 192.168.0.0/16 network. It
also tells the kernel that traffic going between the 192.168.10.0/24 and
192.168.0.0/16 nets is allowed, and the same for the 192.168.11.0 net. These
last two are bidirectional rules, this is important for getting the routing
to work going both ways.
</para>
</sect2>
<sect2>
<title>Routing</title>
<para>
For home users, everything will work fine to here. However
for the remote offices, we need to do some routing. First of all, we
need to tell the main router, or Cisco, that the remote offices are
behind the VPN server. So specify routes on the Cisco that tell
it to send traffic destined for the remote offices to the VPN server.
Now that is taken care of, we must tell the VPN server what to do
with the traffic destined for the remote offices. To do this, we run the
<command>route</command> command on the server. The only problem is that in order
for the <command>route</command> command to work, the link must be up, and if
it goes down, the route will be lost. The solution is to add the routes
when the clients connects, or more simply, to run the route command frequently
as it's not a problem to run it more than is necessary. So, create a script
and add it to your crontab to be run every few minutes, in the script, put the
following:
</para>
<screen>
/sbin/route add -net 192.168.11.0 gw 192.168.10.253 netmask 255.255.255.0
/sbin/route add -net 192.168.10.0 gw 192.168.11.253 netmask 255.255.255.0
</screen>
</sect2>
</sect1>
<sect1>
<title>Server: Configure <command>pppd</command>
</title>
<para>
Now we will configure pppd on the server to handle VPN connections. If
you are already using this server to handle dialup users or even dialing
out yourself, then you should note that these changes may affect those
services. I go over how to avoid conflicts at the end of this section.
</para>
<sect2>
<title><filename>/etc/ppp/</filename>
</title>
<para>
This directory may contain a number of files. You probably already
have a file called <filename>options</filename>. This file holds all of the global
options for <command>pppd</command>. These options cannot be overridden by <command>pppd</command> on the
command line.
</para>
</sect2>
<sect2>
<title><filename>/etc/ppp/options</filename>
</title>
<para>
Your <filename>options</filename> file should contain at least the following:
</para>
<screen>
ipcp-accept-local
ipcp-accept-remote
proxyarp
noauth
</screen>
<para>
The first two lines tell <command>pppd</command> to accept what the other end specifies
for IP addresses. This is necessary when hooking up remote offices, but can
be disabled if you are only connecting home users. It's okay to leave it on, as
it does not prevent the server from assigning addresses, it only says it that
it's okay to accept what the client asks for.
</para>
<para>
The third line is very important. From the <command>pppd</command> man page:
</para>
<screen>
proxyarp
Add an entry to this system's ARP [Address Resolu-
tion Protocol] table with the IP address of the
peer and the Ethernet address of this system. This
will have the effect of making the peer appear to
other systems to be on the local ethernet.
</screen>
<para>
This is important because if it is not done, local traffic will not be able
to get back through the tunnel.
</para>
<para>
The last line is just as important. This tells <command>pppd</command> to allow
connections without username and password. This is safe since authentication
is already handled by <command>sshd</command>.
</para>
</sect2>
<sect2>
<title>Avoiding conflicts</title>
<para>
If you are handling other services with <command>pppd</command>, you should
consider that the configurations for these other services may not be the
same as what the VPN system needs. <command>pppd</command> is designed such that
the options in the main options file <filename>/etc/ppp/options</filename> cannot be
overridden by options specified at runtime. This is done for security
reasons. In order to avoid conflict, determine which options cause the
conflict, and move them from the main file into a separate options file
that is loaded when the appropriate application of <filename>pppd</filename> is run.
</para>
</sect2>
</sect1>
<sect1>
<title>Server: Configure <command>sshd</command>
</title>
<para>
The following is what my <filename>/etc/sshd&lowbar;config</filename> file looks like. Yours
should look the same or similar:
</para>
<screen>
# This is the ssh server system wide configuration file.
Port 22
ListenAddress 0.0.0.0
HostKey /etc/ssh_host_key
RandomSeed /etc/ssh_random_seed
ServerKeyBits 768
LoginGraceTime 600
KeyRegenerationInterval 3600
PermitRootLogin yes
IgnoreRhosts yes
StrictModes yes
QuietMode no
FascistLogging yes
CheckMail no
IdleTimeout 3d
X11Forwarding no
PrintMotd no
KeepAlive yes
SyslogFacility DAEMON
RhostsAuthentication no
RhostsRSAAuthentication no
RSAAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
UseLogin no
</screen>
<para>
The important points to note are that password authentication is disabled
as are all of the <quote>R</quote> services. I have also turned off mail checking
and the message of the day as they can confuse <command>pppd</command> on the client side.
I still allow root login, but as this can only be done with a key, it is adequately
safe.
</para>
</sect1>
<sect1 id="user-accounts">
<title>Server: Set up user accounts</title>
<para>
Now we'll set up the user accounts.
</para>
</sect1>
<sect1>
<title>Add <userinput>vpn-users</userinput> group</title>
<para>
just run:
</para>
<screen>
&num; /usr/sbin/groupadd vpn-users
</screen>
<para>
Now cat the <filename>/etc/group</filename> file and look at the last line. It should be
the entry for the vpn-users group. Note the third field. This is the group ID (GID).
Write it down, as we'll need it in a minute. For this example, the GID is 101.
</para>
</sect1>
<sect1>
<title>create the <filename>vpn-users</filename> home directory</title>
<para>
We're going to use a single home directory for all of the users. So just
run:
</para>
<screen>
&num; mkdir /home/vpn-users
</screen>
</sect1>
<sect1>
<title>The <filename>.ssh</filename> directory</title>
<para>
Now create the <filename>.ssh</filename> directory in the <filename>vpn-users</filename> home
directory.
</para>
<screen>
&num; mkdir /home/vpn-users/.ssh
</screen>
</sect1>
<sect1>
<title>Adding users</title>
<para>
Now comes the fun part. We're going to edit the <filename>/etc/passwd</filename> file
by hand. Normally you let the system handle this file, but for an unusual
setup like this, it is easier to do it yourself. To start, open the
<filename>/etc/passwd</filename> file and see what's in there. Here's an example of what
you might find:
</para>
<screen>
...
nobody:x:65534:100:nobody:/dev/null:
mwilson:x:1000:100:Matthew Wilson,,,:/home/mwilson:/bin/bash
joe:*:1020:101:Joe Mode (home),,,:/home/vpn-users:/usr/sbin/pppd
bill:*:1020:101:Bill Smith (home),,,:/home/vpn-users:/usr/sbin/pppd
frank:*:1020:101:Frank Jones (home),,,:/home/vpn-users:/usr/sbin/pppd
...
</screen>
<para>
You'll find the first user on most any system. The second one is me.
After that are a few made up vpn-users. The first field is the username,
and the second is the password field. The third is user ID (UID) and the
fourth is the group ID (GID). After that comes some info on who the
people are in the fifth field. The sixth field is the user's home
directory, and the last is their shell. As you can see, each field is
separated by a colon. Look at the last three lines. The only difference
between them is the username in the first field, and the user info in
the fifth field. What we want to do is create lines like this for each
user. Don't just use one user for all of the connections, you'll never
be able to tell them apart if you do. So copy the last line of this
file and edit it so that it looks something like the above. Make sure
that the second field has an asterisk (*). The second field should be
unique to all the other IDs in the file. I used 1020. You should use a
number above 1000, since those below are typically reserved for system
use. The fourth field should be the group ID for vpn-users. I told you
to write it down, now is the time that you need it. So put the group ID
in there. Lastly, change the home directory to
<filename>/home/vpn-users</filename>, and the shell to <filename>/usr/sbin/pppd</filename>.
Now copy that line to make more users. Just edit the first
the fifth fields and you're set.
</para>
</sect1>
<sect1>
<title>Server: Administration</title>
<para>
One of the advantages to using this system for user accounts is that you
can take advantage of the UNIX user administration commands. Since each client
is logged in as a user, you can use standard methods to get user statistics.
The following are a few commands that I like to use to see what all is going on.
</para>
<para>
<variablelist>
<varlistentry>
<term>who</term>
<listitem>
<para>
Prints the users currently logged in, as well as when they logged in,
from where (name or IP), and on which port.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>w</term>
<listitem>
<para>
This command prints a more extensive listing of who is currently logged
in. It also tells you uptime and load averages for the system. It also lists
the user's current process (which should be -pppd for VPN clients) as well
as idle time, and current CPU usage for all processes as well as the current
process. Read the <literal remap="tt">w</literal> man page for more info.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>last &lsqb;username&rsqb;</term>
<listitem>
<para>
This lists the login history for the specified user, or for all users if
a username is not provided. It's most useful for finding out how well
the tunnels are running as it prints the length of time that the user
was logged in, or states that the user is still logged in. I should warn
you that on a system that has been up a long time, this list can grow
extremely long. Pipe is through <literal remap="tt">grep</literal> or <literal remap="tt">head</literal> to find
out exactly what you want to know.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
You can also control which users are allowed to connect by modifying the
<filename>/home/vpn-users/.ssh/authorized&lowbar;keys</filename> file. If you remove the user's
public key line from this file, they won't be able to log in.
</para>
</sect1>
<sect1>
<title>Client: Build the kernel</title>
<para>
Now we move onto the client. First we must rebuild the kernel so that it can support
all of the functions that we need. The minimum requirement is to have ppp in the
kernel. You will need forwarding, a firewall, and a gateway only
if you are going to allow other machines access to the tunnel. For this example, I
will setup one of the remote office machines in my example layout. Add the following
options to your kernel. Again, if you've never built a kernel before, read the
<ulink url="/HOWTO/Kernel-HOWTO.html">Kernel HOWTO</ulink>.</para>
<para>
For 2.0 kernels:
<itemizedlist>
<listitem>
<para>
CONFIG&lowbar;PPP
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;FORWARD
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;ROUTER
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;MASQUERADE
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;MASQUERADE&lowbar;ICMP
</para>
</listitem>
</itemizedlist>
</para>
<para>
For 2.2 kernels:
<itemizedlist>
<listitem>
<para>
CONFIG&lowbar;PPP
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;ADVANCED&lowbar;ROUTER
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;FIREWALL
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;ROUTER
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;MASQUERADE
</para>
</listitem>
<listitem>
<para>
CONFIG&lowbar;IP&lowbar;MASQUERADE&lowbar;ICMP
</para>
</listitem>
</itemizedlist>
</para>
</sect1>
<sect1>
<title>Client: Configure Networking</title>
<para>
Now we should setup the networking on our client box. Let's assume that
we've configured the external network and that it works. Now we will configure
the internal interface of the client to service our intranet.
</para>
<sect2>
<title>Interface</title>
<para>
We need to first bring up the internal network interface. To do this,
add the following to your <filename>/etc/rc.d/rc.inet1</filename> (or equivalent) file:
</para>
<para>
For 2.0 Kernels:
</para>
<screen>
/sbin/ifconfig eth1 192.168.10.253 broadcast 192.168.10.255 netmask 255.255.255.0
/sbin/route add -net 192.168.10.0 netmask 255.255.255.0 dev eth1
</screen>
<para>
For 2.2 Kernels:
</para>
<screen>
/sbin/ifconfig eth1 192.168.10.253 broadcast 192.168.10.255 netmask 255.255.255.0
</screen>
</sect2>
<sect2>
<title>Filter rules</title>
<para>
To set up the remote office, we will want to set up our filter rules
that allow traffic to go both directions through the tunnel. Add the following
lines to your <filename>/etc/rc.d/rc.inet1</filename> (or equivalent) file:
</para>
<para>
For 2.0 kernels:
</para>
<screen>
/sbin/ipfwadm -F -f
/sbin/ipfwadm -F -p deny
/sbin/ipfwadm -F -a accept -b -S 192.168.10.0/24 -D 192.168.0.0/16
</screen>
<para>
For 2.2 kernels:
</para>
<screen>
/sbin/ipchains -F forward
/sbin/ipchains -P forward DENY
/sbin/ipchains -A forward -j ACCEPT -b -s 192.168.10.0/24 -d 192.168.0.0/16
</screen>
<para>
You may have noticed that these lines look like what we have
on the server. That's because they are the same. These rules
just say where traffic is allowed to go between these
two networks.
</para>
</sect2>
<sect2>
<title>Routing
</title>
<para>
The only extra routes that are needed are created by the script
that bring the tunnel up.
</para>
</sect2>
</sect1>
<sect1>
<title>Client: Configure <command>pppd</command></title>
<para>
You may not need to edit the client's <filename>/etc/ppp/options</filename> file at
all. You will if the "auth" option is present, or some of the other
priveledged options. Try it, and if it fails, a black
<filename>/etc/ppp/options</filename> will work. just keep adding the options from
the old file to figure out which one broke it (if it's not obvious) and
see if you can get around that. Maybe you don't need them at all. You
probably don't if you don't use <command>pppd</command> for anything else.
</para>
</sect1>
<sect1>
<title>Client: Configure <command>ssh</command></title>
<para>
As root on the client, run the following lines:
</para>
<screen>
&num; mkdir /root/.ssh
&num; ssh-keygen -f /root/.ssh/identity.vpn -P ""
</screen>
<para>
This will create two files, <filename>identity.vpn</filename> and <filename>identity.vpn.pub</filename> in the
<filename>.ssh</filename> directory. The first is your private key, and should be kept such.
<emphasis>Never send this over the net</emphasis> unless it is via an encrypted session. The
second file is your public key, and you can send this anywhere you want, it only
serves to allow you access to other systems, and cannot be used to get into your
own. It is a text file with one line in it that is your actual key. At the end
of the line is the comment field which you may change without fear of breaking
the key. an example key looks something like this:
</para>
<screen>
1024 35 1430723736674162619588314275167.......250872101150654839 root@vpn-client.mycompany.com
</screen>
<para>
It's actually a lot longer than that, but it wouldn't fit on the page if I
showed the whole thing. Copy your key into the <filename>/home/vpn-users/.ssh/authorized&lowbar;keys</filename>
file on the server. Make sure that there is only one key per line, and
that each key is not broken onto multiple lines. You may alter
the comment field all that you like in order to help you remember which
line goes with which user. I highly recommend doing so.
</para>
</sect1>
<sect1>
<title>Client: Bring up the connection</title>
<para>
Now we'll try to actually make the connection to the VPN server. First
we'll need to make a single connection to set up the <command>ssh</command> known&lowbar;hosts
file. Run this:
</para>
<screen>
&num; ssh vpn.mycompany.com
</screen>
<para>
Answer <quote>yes</quote> when it asks you if you want to continue connecting. The
server will tell you <quote>permission denied</quote>, but that's okay. It's
important that you use the same name for the server that you are using
in your connection scripts. Now run the following lines. You will
obviously need to change the options to suit your setup.
</para>
<screen>
&num; /usr/sbin/pty-redir /usr/bin/ssh -t -e none -o 'Batchmode yes' -c blowfish -i /root/.ssh/identity.vpn -l vpn-user vpn.mycompany.com &#62; /tmp/vpn-device
(now wait about 10 seconds)
&num; /usr/sbin/pppd `cat /tmp/vpn-device` 192.168.10.254:192.168.40.254
</screen>
<para>
Note the IP addresses specified on the <command>pppd</command> line. The first is the
address of the client end of the tunnel. The second is the address of
the server end of the tunnel, which is set to the server's internal
address. If all of that seemed to work, move on. If not, check that you
have all of the options, and that they are spelled right. If something
is still going wrong, check <xref linkend="pitfalls"/>.
</para>
</sect1>
<sect1>
<title>Client: Set the routes</title>
<para>
Now set the route to send traffic through the tunnel. Just run this:
</para>
<screen>
&num; /sbin/route add -net 192.168.0.0 gw vpn-internal.mycompany.com netmask 255.255.0.0
</screen>
<para>
You should now be able to communicate with machines on the other side of
the tunnel. Give it a try. If it doesn't work, try using
<command>ping</command> and <command>traceroute</command> to figure out where your problem
might be. If in fact it does work, move on to setting up scripts to do
the work for you.
</para>
</sect1>
<sect1>
<title>Client: Scripting</title>
<para>
Use the <xref linkend="vpn-script"/>. Only you may need to
modify it a little. Make the following changes:
</para>
<para>
<itemizedlist>
<listitem>
<para>
Change the variables at the top to match your setup. Most should be just
fine as they are, but you can change them should you need to.
</para>
</listitem>
<listitem>
<para>
Line 27: add the local and remote IP addresses before $PPP&lowbar;OPTIONS
</para>
</listitem>
<listitem>
<para>
Line 31: Change this line, and the two after it to set routes for
your internal nets.
</para>
</listitem>
</itemizedlist>
</para>
<sect2>
<title>Keeping it running</title>
<para>
While bash scripts are generally stable, they have been known to fail.
In order to make sure that the <command>vpnd</command> script keeps running, add
an entry to the client's crontab that runs the <command>check-vpnd</command>
script. I run mine every 5 minutes or so. If <command>vpnd</command> is indeed
running, <command>check-vpnd</command> doesn't use much CPU.
</para>
</sect2>
</sect1>
</chapter>
<chapter>
<title>Addenda</title>
<sect1 id="pitfalls">
<title>Pitfalls</title>
<para>
Here are just a few of the snags that I've run into while using this
system. I put them here so that you can hopefully avoid them. If you
run into any new ones, please <ulink url="mailto:matthew@shinythings.com">
email them to me</ulink> so that I can keep track, and help others avoid
them.</para>
<sect2>
<title>read: I/O error</title>
<para>
This error is associated with mis-matched
versions off pppd. If you get it, try upgrading both ends of the
connection to the latest version of pppd. I've found that pppd version
2.2 has this problem, so use version 2.3.7 or 2.3.8 instead.
</para>
</sect2>
<sect2>
<title>SIOCADDRT: Network is unreachable</title>
<para>
This error is generated by <command>route</command>. I've seen it happen when the
sleep time between <command>ssh</command> and <command>ppd</command> is not long enough. If
you get this error, run <command>ifconfig</command>, and you may see that there is no
pppX interface. This means that <command>ssh</command> was not done
authenticating before <command>pppd</command> was launched, and therefore
<command>pppd</command> did not make the connection. just increase the delay, and
your problems will be solved.
</para>
<para>
I wonder however if there might be some pppd option that will fix this
problem.
</para>
</sect2>
<sect2 id="ipv4forwarding">
<title>IPv4 Forwarding and 2.2 kernels</title>
<para>
In the new 2.2 kernel, you must specifically enable IP forwarding in the
kernel at boot up. This with the following command:
</para>
<screen>
&num; echo 1 &#62; /proc/sys/net/ipv4/ip_forward
</screen>
<para>
Without this, the kernel will not forward any packets, and hence the
server will not work, nor will any of the gatewaying clients.
</para>
</sect2>
<sect2>
<title>Routing</title>
<para>
It should go without saying, but be careful when you are routing real numbers
that you don't route traffic destined for the VPN server's external address
through the tunnel. It won't make it. (yes, this <emphasis>is</emphasis> from personal
experience.)
</para>
</sect2>
</sect1>
<sect1>
<title>Hardware and Software Requirements</title>
<sect2>
<title>Minimum Hardware Requirements</title>
<para>
This system has been run on a 486SX33 with 8
megabytes of RAM. It didn't run very well though, it had trouble
handling heavy traffic.
</para>
<para>
It doesn't take much more to make it work though. This system does work
very well on a Pentium 75 with 16 megs of RAM, using an LRP distribution
running off of a floppy, with a 6 meg ramdisk, and 10 megs of main
memory. I've tested this setup by running a 700kbit RealVideo stream
through it for over an hour.
</para>
<para>
I now typically run it on Pentium 90s, as their PCI clocking plays
nicer with cheap 100Mbit Ethernet cards.
</para>
</sect2>
<sect2>
<title>Software Requirements</title>
<para>
This system works with both the 2.0 and 2.2 kernels. The script to keep
the tunnel up requires a reasonably modern bash. I have however noticed
that certain distribution's versions of bash don't play too well with
the script.
</para>
<para>
Also, if someone could help me refine my scripts (or even write an
executable) that would help a lot. I'm not sure why, but even
my own bash doesn't follow the rules and doesn't seem to interpret
signals correctly. If you do make any improvements, please email me at
<ulink url="mailto:matthew@shinythings.com">matthew@shinythings.com</ulink>.
</para>
</sect2>
</sect1>
</chapter>
</book>