Creating a radius based VPN with support for Windows clients
This article discusses setting up up an integrated IPSec/L2TP VPN using Radius and integrating it with Microsoft Windows clients.
Introduction and Planning
The software installed is going to be based on Debian packages as far as it is possible.
If we need to rely on a product not within Debian, then it's source code will be retrieved and rebuilt.
Also sometimes the Debian packages are available, but have a compilation feature switched off (usually SSL support).
Where necessary that Debian package will need to be recompiled too.
Overall Setup
The goal of this article is to set up a Linux based VPN server compatible with MS-Windows IPSec/L2TP clients, where users are authenticated against a RADIUS server.
Each main service in this document should have it's own IP address assigned to it. That way services can be moved to different hosts in the future.
While the VPN server uses the ppp daemon as part of it's solution, a separate IP needs to be allocated to that.
It is the point where the VPN tunnels terminate and route into the network.
For this document, the IP addresses assigned to the services follows.
Note that these will need to change based on your real-world rollout.
Base Operating System: 10.10.0.216 MySQL Database Server: 10.10.0.217 FreeRADIUS Server: 10.10.0.218 IPSec VPN Server: 10.10.0.219 ppp Device: 10.10.0.220For redundancy, these services will be mirrored on the 10.10.1.* address range.
IMPORTANT NOTE: For MS windows clients that are to have the VPNs set up, make sure that the following registry key does not exist, or is set to 0.
It should be like this out of the box, but if the user ever setup a non-MS IPSec connection (such as a link to Fortigate VPNs) then this may be set to 1.
I wasted a full working day because I had the key set to 1:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\RasMan\Parameters\ProhibitIPSecIn creating this documentation, I read a LOT of online documentation.
What I found was that there was a lot of conflicting settings across the range of documentation out there.
There was a lot of things that were incorrect, and just a lot of mis-information in general. After spending nearly two weeks of pulling my hair out, I finally found the solution to the problems and this should work.
Operating System
Start with base install of Debian 'testing' using Linux kernel 2.6 The 'testing' distribution is used since it is more up to date than the 'stable' distribution while still protecting from the constant change of the 'unstable' distribution.
NOTE: I actually deviated from this and used the 'unstable' distribution since it had the l2tpd daemon that I required since I could not get l2tpns working.
For a production environment you may want to recompile a newer version of the 2.6 Linux kernel with just the features needed (ppp, IPSec stuff).
It isn't necessary in order to set things up, so this can be left as a last optimisation step.
If you want MPPE ppp encryption (which isn't necessary) then you will have to patch and recompile the kernel.
Create required device nodes - The IPSec VPN server requires a /dev/net/tun device entry created that isn't made in the default Debian install:
# cd /dev # MAKEDEV tunEdit the /etc/hosts file and add entries for all of the services except the ppp device:
10.10.0.217 mysql1.example.org mysql1 10.10.0.218 radius1.example.org radius1 10.10.0.219 vpn1.example.org vpn1Also define these new addresses in the /etc/network/interfaces file like so:
auto eth0:0 iface eth0:0 inet static address 10.10.0.217 netmask 255.255.255.0 network 10.10.0.0 broadcast 10.10.0.255 gateway 10.10.0.1 auto eth0:1 iface eth0:1 inet static address 10.10.0.218 netmask 255.255.255.0 network 10.10.0.0 broadcast 10.10.0.255 gateway 10.10.0.1 auto eth0:2 iface eth0:2 inet static address 10.10.0.219 netmask 255.255.255.0 network 10.10.0.0 broadcast 10.10.0.255 gateway 10.10.0.1(This gives the single machine the virtual addresses so that all the services can have their own IP address despite being upon the same physical host.
)
You can bring the interfaces up with the following:
# ifup eth0:0 # ifup eth0:1 # ifup eth0:2
SSL encryption support
A lot of the products will be relying on X.509 certificates for authenticating and encrypting. In order to generate these certicates we'll need to install OpenSSL.
Install the openssl package:
# apt-get install opensslEdit the /etc/ssl/openssl.cnf file. In the [req_distinguished_name] section, set the following variables to suit your site. For my testing I used the following values:
countryName_default = AU stateOrProvinceName_default = Western Australia localityName_default = Perth 0.organizationName_default = My Company
Certificates and Keys
You'll need all your keys signed by a Certification Authority.
In our case, rather than using Verisign, or some company like that, we wish to be our own Certification Authority. (It could be that we already have a certificate made up, if so it should be copied to the /etc/ssl/certs directory of the server and then the appropriate symlink made (see below).)
If we don't have a proper certificate yet then we'll need to generate one. The steps to do this are as follows:
To create your own Certification Authority Certificate (valid for 10 years or 3650 days):
# cd /etc/ssl/certs # openssl req -x509 -new -days 3650 -newkey rsa -nodes -keyout \ /etc/ssl/private/example-key.pem -out example-cert.pem Generating a 1024 bit RSA private key ........++++++ ...............................++++++ writing new private key to '/etc/ssl/private/example-key.pem' You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]: State or Province Name (full name) [Western Australia]: Locality Name (eg, city) [Perth]: Organization Name (eg, company) [Example Company]: Organizational Unit Name (eg, section) []: Common Name (eg, YOUR name) []:Example Certification Authority Email Address []:hostmaster@example.org # ln -s example-cert.pem $(openssl x509 -noout -hash < example-cert.pem).0After the above steps you should see something like the following:
# ls -l /etc/ssl/certs /etc/ssl/private /etc/ssl/certs: total 4 -rw-r--r-- 1 root root 1391 Sep 1 09:06 example-cert.pem lrwxrwxrwx 1 root root 18 Sep 1 09:09 d5160794.0 -> example-cert.pem /etc/ssl/private: total 4 -rw-r--r-- 1 root root 887 Sep 1 09:06 example-key.pemNote: the symlink won't have the same hex digits because it will be unique every time you generate a new certificate.
Server Keys and Certificates
For each service that requires keys, you'll need to generate a public/private key pair for each, and then sign them with the Certification Authority certificate we generated in the above section.
The server keys are created in the configuration areas of the software that is going to be using them.
An example of how to create a server certificate:
# openssl req -new -newkey rsa -nodes -keyout \ server-key.pem -out server-csr.pemEnter a suitable Common Name such as "MySQL Server", "VPN Server", "Web Server", etc.
Enter an email address suitable for the administrator responsible for the service.
Leave the challenge phrase blank.
Remove the passphrase/challenge from the server key:
# openssl rsa -in server-key.pem -out server-key.pemSign it with the Certification Authority created in the section above:
# openssl x509 -req -days 3650 -CA /etc/ssl/certs/example-cert.pem \ -CAkey /etc/ssl/private/example-key.pem \ -CAcreateserial -CAserial ca-srl.txt -in server-csr.pem \ -out server-cert.pem
Client Keys and Certificates
Client certificates are to be given to each client.
Create the client keys in a dedicated directory somewhere (to be defined later). Perhaps in the future they'll be put into some sort of PKI.
You'll want to issue each client with their own keys and certificates.
These keys need to be imported into their windows machines.
An example of how to create a client certificate:
openssl req -new -newkey rsa -nodes -keyout client-key.pem -out client-csr.pemEnter a suitable Common Name such as "Dr Nick", "Anonymous Client", etc. Enter an email address suitable for the client using the key. eg. "dr_nick@example.com.au"
Leave the challenge phrase blank.
Remove the passphrase/challenge from the key:
# openssl rsa -in client-key.pem -out client-key.pemSign it by the Certification Authority:
# openssl x509 -req -days 3650 -CA /etc/ssl/certs/example-cert.pem \ -CAkey /etc/ssl/private/example-key.pem \ -CAcreateserial -CAserial ca-srl.txt -in client-csr.pem \ -out client-cert.pem
Importing client keys into MS Windows
For Windows Clients you need to convert the PEM key format into pkcs#12 exchange format:
# openssl pkcs12 -export -inkey client-key.pem -in client-cert.pem \ -certfile /etc/ssl/certs/example-cert.pem \ -out export.p12 -name "Windows Cert"Remember the password you enter since this will need to be supplied to the client when for their use to import the key.
(That is, unless we automate a way to install the keys for them - there are certainl ytools out there for this.)
Install the client certificates. First copy the client's export.p12 file to the Windows host, then import it like so:
- Click "Start" and then "Run"
- Enter "mmc" and click "OK"
- Select "File" and then "Add/Remove Snap-in..."
- Click "Add"
- Select "Certifictes" snap-in and click "Add".
- Select "Computer account" radio button and then click "Next".
- Select "Local Computer" radio button (probably already selected) and then click "Finish".
- Select "Close" and then "OK".
- Expand the "Certificates (Local Computer)".
- Right click on "Personal" branch and choose "All tasks" and then "Import".
- Click "Next"
- Click "Browse..."
- Change "Files of type" to "Personal Information Exchange (*.pfx, *.p12)"
- Choose the export.p12 file and then click "Open"
- Click "Next"
- Enter the password you entered when exporting the key into p12 format then click "Next".
- Select "Automatically select the certificate store based on the type of certificate" radio button and click "Next".
- Click "Finish" then hopefully you see a window saying the certificate was successfully imported... click "OK".
- Click "Action" and then "Refresh" and the new certificate should show up.
- Select "File" and then "Exit".
- Saving the settings is optional, but allows you to skip the first few steps of this next time if you want to import another certificate.
MySQL Database Server
First install the appropriate MySQL server package. For this documentation, I'll install the mysql-server-5.0 package.
Select a new password for mysql root (not the same as the Linux root user):
# /usr/bin/mysqladmin -u root password 'mysql_password'Now that the password is changed, for the MySQL cronjobs to continue working correctly do the following:
# touch /root/.my.cnf # chmod 600 /root/.my.cnfEdit the /root/.my.cnf file and add the following:
[mysqladmin] user = root password = mysql_passwordCheck if the MySQL binary is SSL enabled by running the following query:
# mysql -u root -p -e 'SHOW VARIABLES LIKE "%ssl%"' Enter password: +---------------+-------+ | Variable_name | Value | +---------------+-------+ | have_openssl | NO | +---------------+-------+If the binary isn't SSL enabled and you want it to support encrypted connections to it, then you'll have to build it yourself using the following section.
Note, that all the mysql-client libraries that connect to it will need SSL support too and will also need to be rebuilt.
Reconfigure MySQL to bind to the correct IP address. Edit the file /etc/mysqy/my.cnf, and change the bind-address setting appropriately:
bind-address = 10.10.0.217Then restart MySQL:
# /etc/init.d/mysql restartYou should still be able to connect via localhost, but you won't be authorised to connect via 10.10.0.217 yet.
MySQL Database Server with SSL support (Optional)
The MySQL binary package for Debian does not support SSL out of the box (as of the time of writing).
So we have to rebuild it. We actually need to rebuild all the various versions of the server offered, since different debian packages seem to use different MySQL client library versions. The alternative is to rebuild all these packages to use the appropriate version of the MySQL client you want to use.
This is beyond the scope of this document at the moment, however once we actually roll out the network, we'll probably need to maintain our own customised versions of some Debian packages that enable extra compilation options.
I think it would be wise to have a dedicated machine for building packages on. These re-built packages could then by copied over to the server that they will be installed on.
We can use the Debian tools to rebuild the MySQL server with OpenSSL support like so. Install the tools required to build the server.
# apt-get build-dep mysql-server-5.0 # apt-get install libssl-devMake a directory somewhere and get the server's source code.
# mkdir -p /usr/local/src/debian-mysql # cd /usr/local/src/debian-mysql # apt-get source mysql-server-5.0Amend the default Debian build options:
# vi /usr/local/src/debian-mysql/mysql-dfsg-5.0-5.0.7beta/debian/rules(Change --without-openssl to --with-openssl)
Build the new MySQL binary packages:
# cd mysql-dfsg-5.0-5.0.7beta # ./debian/rules binaryInstall the newly built packages in place of the non-SSL debian ones:
# dpkg -i mysql-server-5.0_5.0.7beta-1_i386.deb \ mysql-common_5.0.7beta-1_all.deb \ mysql-client-5.0_5.0.7beta-1_i386.deb \ libmysqlclient15_5.0.7beta-1_i386.debGo to the /etc/mysql directory and create a Certificate Authority and Signed Server Certificates as per the SSL section.
Set up the certificates and keys in the /etc/mysql directory.
You'll need to create a server key and certificate and sign them with the certificate authority.
You should create a symlink to the certificate authority like so:
# cd /etc/mysql # ln -s /etc/ssl/certs/example-cert.pem cacert.pemEdit the /etc/mysql/my.cnf file and uncomment the following lines in the [mysqld] section:
ssl-ca=/etc/mysql/cacert.pem ssl-cert=/etc/mysql/server-cert.pem ssl-key=/etc/mysql/server-key.pemRestart MySQL and test that you can connect to it:
# /etc/init.d/mysql restart
RADIUS server
Install the freeradius and freeradius-mysql package:
apt-get install freeradius freeradius-mysqlCreate the radius database:
# gunzip /usr/share/doc/freeradius/examples/db_mysql.sql.gz # cp /usr/share/doc/freeradius/examples/db_mysql.sql /tmp/db_mysql.sqlDue to a bug you will need to edit the /tmp/db_mysql.sql file and in the creation of the 'nas' table at the end of the script:
Remove: DEFAULT '0' From: id int(10) DEFAULT '0' NOT NULL auto_increment So it looks like: id int(10) NOT NULL auto_incrementCreate the radius database and populate it:
# mysqladmin create radius # cat /tmp/db_mysql.sql | mysql -p radiusCreate a new radius user in the database and then grant it full rights to the newly created radius database.
For a non-SSL setup create a 'radius' user with a password.
For an SSL setup create a 'radius' user with no password but with references to the appropriately signed keys.
There is much more involved for the SSL setup as all the clients that talk to the RADIUS server will need to support it as well.
I have played a bit with the SSL and radius enough to prove that the following SSL steps do work:
non-SSL:
# mysql -p GRANT ALL ON radius.* TO 'radius'@'localhost' IDENTIFIED BY 'radius_password'; GRANT ALL ON radius.* TO 'radius'@'%' IDENTIFIED BY 'radius_password';SSL:
First to get the SUBJECT and ISSUER strings using the following commands on the appropriate certificate files:
# openssl verify client-cert.pem # openssl verify server-cert.pemThen use these when generating the following commands.
# mysql -p GRANT ALL ON radius.* TO 'radius'@'localhost' REQUIRE SUBJECT "/C=AU/ST=Western Australia/L=Perth/O=Example/CN=Radius Client/emailAddress=hostmaster@example.org" AND ISSUER "/C=AU/ST=Western Australia/L=Perth/O=My Company/CN=MySQL Server/emailAddress=hostmaster@example.org"; GRANT ALL ON radius.* TO 'radius'@'%' REQUIRE SUBJECT "/C=AU/ST=Western Australia/L=Perth/O=My Company/CN=Radius Client/emailAddress=hostmaster@example.org" AND ISSUER "/C=AU/ST=Western Australia/L=Perth/O=My Company/CN=MySQL Server/emailAddress=hostmaster@example.org";It is possible that we will still want to have a password associated with the user. That way to connect to RADIUS you'd have to know the correct password as well as possess the correct keys. To add the password, just use the "IDENTIFIED BY 'radius_password'" the same was as done in the non-SSL section.
Edit the /etc/freeradius/sql.conf file and set the server, login, and password variables to the correct values:
server = "mysql1.example.org" login = "radius" password = "radius_password"Edit the /etc/freeradius/clients.conf file:
Set a new secret password (radius_secret) in the client 127.0.0.1 {} section.
Create the new following section under the client 127.0.0.1{} section:
client 10.10.0.218 { secret = radius_secret shortname = radius1 nastype = other }You can also specify network masks such as "client 10.10.0.216/29 {" for example.
Edit the /etc/freeradius/radiusd.conf file:
- Uncomment 'sql' in the authorise{}, accounting{}, and session{} sections.
- Also comment out radutmp in the accounting{} and session{} sections since it is a performance hit, and unnecessary now that we are using the SQL backend.
Restart FreeRADIUS:
# /etc/init.d/freeradius restartPopulate the MySQL tables with your users. The bare minimum for testing is:
INSERT INTO radcheck (UserName, Attribute, op, Value) VALUES ('user1', 'User-Password', '==', 'password1');A lot of documentation talks about adding Auth-Type := Local in the radgroupcheck table. This doesn't work if using MS-CHAPv2, so don't do it. In theory, the authentication modules should detect the correct Auth-Type and go from there.
Adding an Auth-Type tends to lock only one method as being valid to the exclusion of all others which is probably not whatwe want.
The use of some of the tables are as follows:
- The radcheck table contains the username and password pairs.
- An entry for each VPN user must be in this table.
- The radreply table contains custom user-specific radius reply attributes.
- The usergroup table contains a username entry mapping to a group name.
- The group names are used to determine any custom radius reply attributes for the group.
- The radgroupreply table contains the custom attributes to be returned for particular groups.
The following is some examples of how to populate these tables. You'll need to customise for a real world roll-out.
# Define the users and their passwords. # INSERT INTO radcheck (UserName, Attribute, op, Value) VALUES ('user1', 'User-Password', '==', 'password1'), ('user2', 'User-Password', '==', 'password2') ; # Define the users and the group they are in. # INSERT INTO usergroup (UserName, GroupName) VALUES ('user1', 'dynamic'), ('user2', 'static') ; # Return attributes for particular users. # INSERT INTO radreply (UserName, Attribute, op, Value) VALUES ('user2', 'Cisco-Avpair', ':=', 'throttle=yes'); ('user2', 'Framed-IP-Address', ':=', '10.10.0.247'); # Return attributes for particular groups. # This is suboptimal as it contains a lot of DEFAULT values. # Defaults are supposed to be left out of the database # and put into the config file for performance reasons. # INSERT INTO radgroupreply (GroupName, Attribute, op, Value) VALUES ('static', 'Cisco-Avpair', ':=', 'throttle=no'); ('dynamic', 'Cisco-Avpair', ':=', 'throttle=yes'); ('dynamic', 'Framed-Compression', ':=', 'Van-Jacobsen-TCP-IP'), ('dynamic', 'Framed-IP-Address', ':=', '255.255.255.254'), ('dynamic', 'Framed-MTU', ':=', '1500'), ('dynamic', 'Framed-Protocol', ':=', 'PPP'), ('dynamic', 'Framed-Route', ':=', '10.10.0.1'), ('dynamic', 'Service-Type', ':=', 'Framed-User') ;Again note that a lot of the entries that I put into the radgroupreply shouldn't be there since they should be default values which the doco recommends is kept out of the database and stored in the freeradius config files.
You should be able to test that the RADIUS server is working using the radtest program:
# radtest user1 password1 localhost 1812 radius_secret # radtest user1 password1 10.10.0.218 1812 radius_secret
VPN Server
After a lot of research I've settled on an IPSec based solution that can handle NAT-T.
An easier solution to implement is PPTP, however all sources I refer to say that the protocol itself is inherently insecure. The only reason it is used is because it is easy. IPSec is regarded as a well understood and secure protocol.
The IPSec packets will be handled by the inbuilt IPSec layer in the Linux 2.6 kernel.
Racoon will be used as the Internet Key Exchange (IKE) daemon for automatically keying IPSec connections. Racoon supports NAT-T but perhaps only in Tunnel mode. The Window clients use Transport mode.
It is possible that Racoon may not support NAT-T in transport mode.
Install the ipsec-tools and racoon packages:
apt-get install ipsec-tools racoonChoose the 'direct' mode for racoon configuration.
If using the modutils package instead of module-init-tools (unlikely if you're using a 2.6 kernel) allow the kernel to autoload the correct IPSec modules create the /etc/modutils/ipsec file with the following lines:
alias xfrm-type-2-50 esp4 alias xfrm-type-2-51 ah4 alias xfrm-type-2-108 ipcomp alias xfrm-type-10-50 esp6 alias xfrm-type-10-51 ah6 alias xfrm-type-10-108 ipcomp6Then rebuild the /etc/modules.conf file to include these entries:
# update-modulesThese entries were already in the /etc/modprob.d/aliases file as supplied by the modules-init-tools Debian package.
Edit the /etc/racoon/racoon.conf and comment out the 'path pre_shared_key' variable and then add the following lines:
listen { isakmp 10.10.0.219[500]; isakmp_natt 10.10.0.219[4500]; } padding { randomize off; exclusive_tail off; } remote anonymous { exchange_mode main; my_identifier asn1dn; # Extract id from public key peers_identifier asn1dn; # Extract id from public key verify_identifier on; certificate_type x509 "server-cert.pem" "server-key.pem"; verify_cert off; passive on; # Racoon should not start the connection itself. generate_policy on; # Create policy when connection is initiated. nat_traversal on; # NAT-T is used when a NAT gateway is detected between the peers. proposal { encryption_algorithm 3des; hash_algorithm sha1; authentication_method rsasig; # Use X.509 RSA public/private key dh_group modp1024; } } sainfo anonymous { lifetime time 28800 sec; encryption_algorithm 3des; authentication_algorithm hmac_md5; compression_algorithm deflate; }Make a directory for the racoon certificates and generate and sign the required server certificates and keys:
# mkdir /etc/racoon/certs # chmod 700 /etc/racoon/certsCreate a server key and certificate using a Common Name of "IPSec Server" or "VPN server" or something like that.
Create symlinks to Certificate Authorisation keys (copy them to the host if necessary).
# ln -s /etc/ssl/certs/example-cert.pem $(cat /etc/ssl/certs/example-cert.pem | openssl x509 -noout -hash ).0 # ln -s /etc/ssl/certs/example-cert.pem cacert.pemRestart racoon:
# /etc/init.d/racoon restart
L2TP
Because of Microsoft's IPSec implementation, I also have to support L2TP.
This has PPP packets that are encapsulated within L2TP packets which are further encapsulated within IPSec (and with NAT-T turned on, further encapsulated within UDP packets). That's a lot of overhead.
The L2TP layer is unnecessary, and my cynical view is this it is probably a ploy by Microsoft to lock customers into buying more, licenses by having to use Microsoft's VPN server solutions.
It is possible to hack the windows registry to allow it to just use TCP/IP within IPSec, removing the need for L2TP. However hacking the registry is undesirable on the client computers, so I'll just have to live with the more complicated server setup, and the extra overhead of the network packets.
l2tpns
No matter what I tried, the l2tpns package just would not work from either 'testing' or 'unstable' :(
It is supposed to be better than lt2pd. But it isn't, if it is impossible to get working. The problem is that it didn't seem to try and contact the RADIUS server. No connection attempt at all that I could see.
I have no idea what it was waiting for and the debugging output gave me no clues. Nor was the web useful for finding the solution... Trust me, I spent HOURS on this.
l2tpd and ppp
Because of my failure to get l2tpns working I used the l2tpd and pppd option.
This is the setup that is probably used by more users on the Internet, so there is more documentation about it.
NOTE: l2tpd is no longer under active development like the l2tpns product is. Bug and security fixes only.
Unfortunately the l2tpd program is only available in the 'unstable' distribution so requires mucking around to get into 'testing' (which I won't go into here).
Install the l2tpd and ppp packages.
Edit /etc/l2tpd/l2tpd.conf and add the following:
[global] listen-addr = 10.10.0.219 port = 1701 [lns default] ip range = 10.10.0.248 - 10.10.0.254 local ip = 10.10.0.220 hostname = vpn1 ppp debug = yes pppoptfile = /etc/ppp/options.l2tpd length bit = yesNOTE: the 'local ip' is not the address bound to any interfaces already on the host. This is a new IP address that will be assigned to the ppp device that gets created when a connection is established.
All VPN traffic will route via this ppp device.
ALSO NOTE: A lot of doco on the net tells you to put in the refuse and require entries for pap, chap, and authentication. DONT. These override the authentication settings in the ppp daemon, and they don't actually work anyway.
(i.e. if you refuse PAP here, the client can still connect with PAP if so configured. Also all the more appropriate access controls in the ppp options file will be ignored, but they are more flexible, so we want them to work.)
Create /etc/ppp/options.l2tpd with the following contents:
# Specify which DNS Servers the incoming Win95 or WinNT Connection should use. # Two Servers can be remotely configured. # ms-dns 10.10.0.100 #ms-dns 192.168.1.2 # Specify which WINS Servers the incoming connection Win95 or WinNT should use. # ms-wins 10.10.0.100 # Require the peer to authenticate itself before allowing network packets to be sent or received. # auth # Use hardware flow control. # crtscts # Specifies that pppd should use a UUCP-style locks to ensure exclusive access to the device. # lock # Set the MRU [Maximum Receive Unit] value to for negotiation. # Set the MTU [Maximum Transmit Unit] value to . # mru 1400 mtu 1400 # Don't fork to become a background process. # nodetach # Turn on debugging. This can be turned off once everything is working. # debug # Add an entry to this system's ARP table with the IP address of the peer and the Ethernet address of this system. # proxyarp # pppd will accept the peer's idea of our local IP address, # even if the local IP was specified in an option. # pppd will accept the peer's idea of its (remote) IP address, # even if the remote IP was specified in an option. # ipcp-accept-local ipcp-accept-remote # Specifies that pppd should disconnect if the link is idle for seconds. # idle 1800 # Wait for up n milliseconds after the connect script finishes for a valid PPP packet from the peer. # connect-delay 5000 # Tell the windows client to to get a default route from the connection. # nodefaultroute # Force MS-CHAP-v2 authentication since it is more secure than the other options. # Though it probably doesn't matter too much since it all happens inside an IPSec tunnel anyway. # If you have an MPPE enabled kernel you can turn on support for MPPE, but it isn't necessary. # refuse-pap refuse-chap refuse-mschap require-mschap-v2 #require-mppe # Do not sent output from plugins to the pty or the stream from clients may be released. # nologfd # Turn on the RADIUS plugin. # #plugin radius.soAdd an entry to the /etc/ppp/chap-secrets file like so:
user1 * "password1" 10.10.0.248/29 * user1 "password1" 10.10.0.248/29Restart the l2tpd daemon:
# /etc/init.d/l2tpd restartGenerate and import client certificates into a Windows client and then connect to the VPN server. (Instructions for configuring the VPN client software on Windows should be written but is straight forward with no special options requiring to be ticked/unticked, etc).
If all is good, then we can move on to integrating PPP with the RADIUS server.
Integrating pppd and RADIUS
This is the trickiest part since there is so much bad information out there. It looks simple when it's written down like this though doesn't it :) Hopefully these are the steps that will bring you success.
Delete the 'user1' entries out of the /etc/ppp/chap-secrets file again.
Install the radiusclient1 package.
Edit /etc/radiusclient/servers file and add the following:
radius1.example.org radius_secretEdit /etc/radiusclient/radiusclient.conf and change the following lines from localhost:
authserver radius1.example.org acctserver radius1.example.orgEdit the /etc/ppp/option.l2tp file and uncomment the 'plugin radius.so' entry at the bottom.
Radiusclient Dictionaries
For MS-CHAP protocols to work with the radius server it is critical that the radiusclient setup has the microsoft dictionaries.
Unfortunately these aren't installed with the radiusclient1 package.
Even more unfortunate is that the format of these dictionary files have evolved over time and the radius.so plugin that is part of the ppp package only understands an very old format.
Also the radius plugin is very fussy about the INCLUDE statements used in the dictionary files.
The comments in the files provided with the radiusclient1 package suggest that you'd add an entry like:
$INCLUDE dictionary.microsoftWhen in fact, the radius.so plugin requires it to look like:
INCLUDE /etc/radiusclient/dictionary.microsoftNote the lack of a leading $ sign, and the full path used in the file.
The steps to getting a working dictionary.microsoft file are as follows:
Copy the freeradius dictionary.microsoft file to the radiusclient1 area:
# cp /usr/share/freeradius/dictionary.microsoft /etc/radiusclient/Edit the file to change it's format back to an older format understood by the radius.so plugin.
# vi /etc/radiusclient/dictionary.microsoftChange all occurances of the word "octects" to "string".
Delete the following lines:
BEGIN-VENDOR Microsoft END-VENDOR MicrosoftDelete all "encrypt=1", and "encrypt=2" entries from the end of the ATTRIBUTES that have them.
At the end of each ATTRIBUTE line add a new field to the end that says "Microsoft" without the quotes.
Watch out for the lines that have comments at the end. The new field must be before them so it isn't part of the comment.
Now edit the /etc/radiusclient/dictionary file and add the following to the end of it:
INCLUDE /etc/radiusclient/dictionary.microsoftYou should now be able to connect with the VPN client and this time it will be authenticated against the radius server.
If it fails for any reason, shutdown the freeradius server, and run it manually with debugging turned on to see what is happening like so:
# /etc/init.d/freeradius stop # freeradius -XOn a new connection from the VPN client you should see a whole heap of logs starting with something like:
rad_recv: Access-Request packet from host 10.10.0.218:1026, id=244, length=133 Service-Type = Framed-User Framed-Protocol = PPP User-Name = "user1" MS-CHAP-Challenge = 0xa6f98c2e3c2157432ae1622d9bad2e64 MS-CHAP2-Response = 0xe500f87302def6dbfc274ac1cb1b5ee6bcf00000000000000000497a4622ec34eff1375a80058ad318233f21aa1ec25ea2d0 NAS-IP-Address = 10.10.0.216 NAS-Port = 0If the MS-CHAP-Challenge, or MS-CHAP2-Response entries are not there, then there is something wrong with the dictionary setup described above, so double check it all.
The dictionaries are critical to getting this to work.
Creating a radius based VPN with support for Windows clients的更多相关文章
- [2018.05].NET Core 3 and Support for Windows Desktop Applications
.NET Core 3 and Support for Windows Desktop Applications Richard 微软官网的内容...net 3.0 升级任务 任重道远 https:/ ...
- windows 10 上源码编译OpenCV并支持CUDA | compile opencv with CUDA support on windows 10
本文首发于个人博客https://kezunlin.me/post/6580691f/,欢迎阅读! compile opencv with CUDA support on windows 10 Ser ...
- SharePoint 2013 Support for Windows Server 2012 R2
Summary Currently, Microsoft SharePoint Server 2013 is not supported for installation on computers r ...
- Creating Context Menu / 创建上下文菜单项 / VC++, Windows, DLL, ATL, COM
创建上下文菜单项 1.新建一个ATL Project. 2.建议将Project Property中Linker – General - “Register Output” 设为no,C/C++ - ...
- 通过基于 Linux 的软件 VPN 设备连接到 Windows Azure 虚拟网络
摘要 本文章将说明如何通过使用软件 VPN 设备,将本地办公室或站点连接到 Windows Azure 虚拟网络.在构建原型或在构建可以尽快利用云的"开发/测试"工作流时,软件VP ...
- (转)手把手教你如何架设VPN
简介 让远程用户连接Exchange Server的传统解决方案是使用Outlook Web Access.然而,为何不使用虚拟专用网(Virtual Private Network,VPN)让你的远 ...
- Radius 认证协议介绍-兼rfc导读
老规矩, 先看维基: 远端用户拨入验证服务(RADIUS, Remote Authentication Dial In User Service)是一个AAA协议,意思就是同时兼顾验证(authent ...
- Cisco VPN can't work in Win8
Goto HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CvirtA Change DisplayName to "Cisco ...
- 跨云应用部署第一步:使用IPSEC VPN连接AWS中国版和Windows Azure中国版
随着公有云的普及,越来越多的客户将关键应用迁移到云端.但是事实证明,没有哪家云服务提供商可以提供100%的SLA,无论是例行维护还是意外中断服务,对于客户的关键应用而言,都会受到不同程度的影响.此外, ...
随机推荐
- 登录phpmyadmin提示: #1045 无法登录 MySQL 服务器
打开phpmyadmin,进行登录,出现以下问题,提示:#1045 无法登录 MySQL 服务器 或许出现以下错误情况:phpmyadmin:#1045 无法登录 MySQL 服务器.Access d ...
- 【转】对MVC、MVP、MVVM的懂得
[转]对MVC.MVP.MVVM的懂得 转载地址:http://www.myexception.cn/vc-mfc/1612241.html 对MVC.MVP.MVVM的理解 最近看了一堆js框架的文 ...
- 什么是html技术
HTML(Hyper Text Mark-up Language )即超文本标记语言,是 WWW 的描述语言,由 Tim Berners-lee提出.设计 HTML 语言的目的是为了能把存放在一台电脑 ...
- HDU 1010 Tempter of the Bone(深度+剪枝)
http://acm.hdu.edu.cn/showproblem.php?pid=1010 题意:就是给出了一个迷宫,小狗必须经过指定的步数到达出口,并且每个格子只能走一次. 首先先来介绍一下奇偶性 ...
- Servlet页面登录的数据库验证程序(一)
一.基本思想是MVC模式,一个登录页面login.jsp,一个服务器处理程序Servlet.java,一个MySql数据库userinfo. 另外还有相关的数据封装类User和数据库连接类GetDat ...
- 想让你的java代码更漂亮,用枚举吧
枚举是java 5之后添加的一个重要特性,这个特性不能提高性能,但是能让java程序员写出更优雅的代码. 我之前看到过挺多介绍java枚举的不错的帖子,我也来参与以下这个话题. 1. 枚举基本用法 / ...
- Java后台判断请求来自PC端还是移动端
核心代码
- Character类的2个定义大小写方法以及charAt(int index)方法
API文档charAt(int index)是这样定义的: charAt(char index):Returns the char value at the specified index.在指定的索 ...
- Python set集合类型操作总结
Python中除了字典,列表,元组还有一个非常好用的数据结构,那就是set了,灵活的运用set可以减去不少的操作(虽然set可以用列表代替) 小例子 1.如果我要在许多列表中找出相同的项,那么用集合是 ...
- PHP 数组转码
/** * 数组转码 * @param array $arr 要转码的数组 * @param string $in_charset 输入的字符集 * @param string $out_charse ...