VPN Server setup for Windows Clients
This howto explains the steps required to set up a VPN server that will accept connections for users on Windows clients. No additional software is required on the M$ side of things meaning you can use the builtin VPN adapter in Dial up networking.
The author is assuming you are comfortable enough with Basic FreeBSD administration including using CVSup, installing ports, recompiling the kernel, editing rc files and basic networking knowledge.
This solution is an excellent example of how FreeBSD can be used on older hardware to provide a useful service for businesses at next to nothing. You can also add support for Cisco PIX 501 hardware VPN routers to link into the same box for branch office connectivity providing an all in one VPN solution, however that will be covered in the next article ;)
Basic Requirements ------------------------
The setup I have for my VPN server is:
- Pentium III 800Mhz
- 256MB RAM
- 20GB EIDE Hard Drive
This hardware happily supports 50 simultaneous connections, however that is by no means the limit, more like thats all the VPN users I can throw at it at the moment!
This server has its own dedicated public IP address for the VPN tunnels to connect to. Shouldn't be a problem for people who have a /29 or greater.
It is possible to do this if you have a single static IP address from your provider, but you will need to add things such as NAT support for it to act like your regular firewall for clients behind it. This won't be covered in this article.
Setting up the Box ------------------------
Assuming you have the hardware and network requirements above you should grab yourself the latest -release from the F reeBSD 4.X branch, and do a minimal install with at least kernel sources and ports collection.
While your waiting for the install, it might be worth getting your public and private IP addresses ready. I like to give the external address that the VPN clients connect to the name vpn-access.domain.com in DNS.
Once you have configured your new server the way you like it, you need to recompile the kernel with the following options:
options IPFIREWALL options IPFIREWALL_VERBOSE options IPFIREWALL_VERBOSE_LIMIT=100 options IPSEC options IPSEC_ESP
* note - be sure to leave IPv6 enabled
BEFORE your reboot, you will want to get a very basic firewall setup so you are not locked out of your machine! Personally I don't like adding bits to the default firewall file, so I set the following in rc.conf:
firewall_enable="YES" firewall_script="/etc/firewall.rules" firewall_quiet="NO"
Also while your at it add the following lines to rc.conf:
gateway_enable="YES" tcp_extensions="YES"
Now create the file /etc/firewall.rules, and add the following:
#+--------- # Firewall config
fwcmd="/sbin/ipfw"
# Flush Old rules
$fwcmd -f flush
# Allow everything for the moment
$fwcmd add allow ip from any to any
Once we have the VPN up and working we will revisit the firewall rules to make them a bit more secure, but leave them out at the moment to make sure a rouge rule doesn't interfere with our VPN configuration.
Once you have completed the above steps, reboot!
When the box comes up, cvsup your ports.
You now need to install the following ports:
/usr/ports/net/mpd /usr/ports/net/poptop
Make sure the daemons are set to start up at boot in /usr/local/etc/rc.d (mpd.sh and pptpd.sh)
Now on to editing the daemon configuration files. The first one we will look at is poptop. Poptop is what listens for the incoming PPTP connections and passes them on to a PPP daemon. In this example we will setup the VPN server to allow 6 incoming connections.
remove the /usr/local/etc/pptpd.conf file and replace with the following:
#+----------------- # Poptop config file
speed 115200 debug localip 192.168.0.251 remoteip 192.168.0.240-245
The local IP should be the IP address of your inside/private interface, and the remote IP should be a range of IP addresses to assign to the PPTP connections.
Now on to the longer part MPD config. MPD is the daemon that actually handles the PPP connections, including encryption. It makes use of the netgraph modules.
Change to the /usr/local/etc/mpd directory.
The first and most simple file to create is the username and password file. Edit mpd.secret and use:
testuser1 "testpass1" testuser2 "testpass2"
Or populate with your own username and passwords :)
Onto mpd.links and mpd.conf. These files were frustrating in the fact I had to create an entry for every tunnel I wanted to support. I would suggest whipping up a perl script if your using more than 30 connections unless you like typing!
In mpd.conf, do the following:
default: load pptp0 load pptp1 load pptp2 load pptp3 load pptp4 load pptp5
pptp0: new -i ng0 pptp0 pptp0 set iface disable on-demand set bundle disable multilink set iface enable proxy-arp set link yes acfcomp protocomp set link no pap chap set link enable chap set link keep-alive 60 180 set ipcp yes vjcomp set ipcp ranges 192.168.0.251/32 192.168.0.240/32 set ipcp dns 192.168.0.1 set ipcp nbns 192.168.0.2 set bundle enable compression set ccp yes mppc set ccp yes mpp-e40 set ccp yes mpp-e128 set ccp yes mpp-stateless set bundle yes crypt-reqd
pptp1: new -i ng1 pptp1 pptp1 set iface disable on-demand set bundle disable multilink set iface enable proxy-arp set link yes acfcomp protocomp set link no pap chap set link enable chap set link keep-alive 60 180 set ipcp yes vjcomp set ipcp ranges 192.168.0.251/32 192.168.0.241/32 set ipcp dns 192.168.0.1 set ipcp nbns 192.168.0.2 set bundle enable compression set ccp yes mppc set ccp yes mpp-e40 set ccp yes mpp-e128 set ccp yes mpp-stateless set bundle yes crypt-reqd
pptp2: new -i ng2 pptp2 pptp2 set iface disable on-demand set bundle disable multilink set iface enable proxy-arp set link yes acfcomp protocomp set link no pap chap set link enable chap set link keep-alive 60 180 set ipcp yes vjcomp set ipcp ranges 192.168.0.251/32 192.168.0.242/32 set ipcp dns 192.168.0.1 set ipcp nbns 192.168.0.2 set bundle enable compression set ccp yes mppc set ccp yes mpp-e40 set ccp yes mpp-e128 set ccp yes mpp-stateless set bundle yes crypt-reqd
pptp3: new -i ng3 pptp3 pptp3 set iface disable on-demand set bundle disable multilink set iface enable proxy-arp set link yes acfcomp protocomp set link no pap chap set link enable chap set link keep-alive 60 180 set ipcp yes vjcomp set ipcp ranges 192.168.0.251/32 192.168.0.243/32 set ipcp dns 192.168.0.1 set ipcp nbns 192.168.0.2 set bundle enable compression set ccp yes mppc set ccp yes mpp-e40 set ccp yes mpp-e128 set ccp yes mpp-stateless set bundle yes crypt-reqd
pptp4: new -i ng4 pptp4 pptp4 set iface disable on-demand set bundle disable multilink set iface enable proxy-arp set link yes acfcomp protocomp set link no pap chap set link enable chap set link keep-alive 60 180 set ipcp yes vjcomp set ipcp ranges 192.168.0.251/32 192.168.0.244/32 set ipcp dns 192.168.0.1 set ipcp nbns 192.168.0.2 set bundle enable compression set ccp yes mppc set ccp yes mpp-e40 set ccp yes mpp-e128 set ccp yes mpp-stateless set bundle yes crypt-reqd
pptp5: new -i ng5 pptp5 pptp5 set iface disable on-demand set bundle disable multilink set iface enable proxy-arp set link yes acfcomp protocomp set link no pap chap set link enable chap set link keep-alive 60 180 set ipcp yes vjcomp set ipcp ranges 192.168.0.251/32 192.168.0.245/32 set ipcp dns 192.168.0.1 set ipcp nbns 192.168.0.2 set bundle enable compression set ccp yes mppc set ccp yes mpp-e40 set ccp yes mpp-e128 set ccp yes mpp-stateless set bundle yes crypt-reqd
Still there? ;)
Just to explain a few of the lines in the above file for you to tweak for your setup:
set ipcp ranges 192.168.0.251/32 192.168.0.240/32
This sets the IP address for the connection. We will already have set the range in the poptop config. The format is: set ipcp ranges insideinterfaceip/32 firstipinrange/32
set ipcp dns 192.168.0.1
This sets the IP address of your internal DNS server. Put your ISP's if you don't have an internal DNS.
set ipcp nbns 192.168.0.2
Useful for businesses running SAMBA or any SMB/CIFS server. Put the IP address of your WINS server here or if you don't have a WINS server the ip of the fileserver itself.
in the mpd.links file, create the following:
pptp0: set link type pptp set pptp self 1.2.3.4 set pptp enable incoming set pptp disable originate
pptp1: set link type pptp set pptp self 1.2.3.4 set pptp enable incoming set pptp disable originate
pptp2: set link type pptp set pptp self 1.2.3.4 set pptp enable incoming set pptp disable originate
pptp3: set link type pptp set pptp self 1.2.3.4 set pptp enable incoming set pptp disable originate
pptp4: set link type pptp set pptp self 1.2.3.4 set pptp enable incoming set pptp disable originate
pptp5: set link type pptp set pptp self 1.2.3.4 set pptp enable incoming set pptp disable originate
This file specifies some basic behaviour for listening, you need to create one for each tunnel entry in mpd.conf. the 1.2.3.4 ip address should be the IP address of your external interface.
Assuming that the two daemons can start from /usr/local/etc/rc.d, do the following:
/usr/local/etc/rc.d/mpd.sh start; /usr/local/etc/rc.d/pptpd.sh start;
Or reboot if that would make you happier!
Your VPN server should now be up and running :)
Just to recap, we have set up a PPTP server for Microsoft Windows clients which will support 6 concurrent connections. It might be worth testing the box:
In this example we will use Windows XP as the client:
1) In Dialup Networking, Click "Create new Connection". Select "Connect to a Private network using Dialup or VPN at my workplace". On the next option choose Virtual Private Network Connection.
2) Choose a name for the connection in the next box. You may want it to automatically establish your Internet connection in the next box, I normally do it manually. For the hostname either enter the external IP address of your vpn server, or if you did decide to name it, vpn-access.domain.com (Or whatever you called it). Click Finish and your done! One option that might be worth changing is the routing.
3) Go into the newly created connection as if you are going to dial it, and click properties. Click the networking tab, and select "Internet Protocol (TCP/IP)" and click properties. Click the advanced tab, and untick "Use default gateway on remote network". This will only send traffic destined for your network to you :) If you run into problems though I would suggest rechecking it.
Now back to the firewall setup. I can't dictate what will bne best in every situation so I will give you my firewall config as a starting point:
#+-------------- # Firewall Config
fwcmd="/sbin/ipfw"
# Flush Previous
$fwcmd -f flush
# Allow internal communication
$fwcmd add allow ip from any to any in via xl0 $fwcmd add allow ip from any to any out via xl0
# Allow VPN
$fwcmd add allow tcp from any to 1.2.3.4 1723 in via xl1 $fwcmd add allow tcp from 1.2.3.4 1723 to any out via xl1 $fwcmd add allow gre from any to 1.2.3.4 in via xl1 $fwcmd add allow gre from 1.2.3.4 to any out via xl1
# Allow established connections
$fwcmd add allow ip from any to any via ng0 $fwcmd add allow ip from any to any via ng1 $fwcmd add allow ip from any to any via ng2 $fwcmd add allow ip from any to any via ng3 $fwcmd add allow ip from any to any via ng4 $fwcmd add allow ip from any to any via ng5
# Block, and log, anything else
$fwcmd add deny log ip from any to any
This basic setup will allow incoming pptp connections to the machine (replace 1.2.3.4 with your external IP) and allow it back. It also passes GRE (Generic Routing Encapsulation) through the firewall which is needed. The ng0 interfaces are created when a VPN connection is established.
I hope this article has been of use to anyone interested in VPN's in FreeBSD, any questions email me at jamie@blackh0le.net or catch me in the #freebsdhelp channel on EFnet as sparc^ .
cheers
Jamie Heckford
Sparc^
|