📜 ⬆️ ⬇️

Corporate VPN with ACCEL-PPP + IPsec and authorization with Freeradius via AD


In this post I want to show an example of a quick implementation of a corporate VPN server with support for PPTP, L2TP (with and without IPsec), IPSec vpn with a single database that can work with address pools, different groups of users, authorize users from both LDAP and and from the local database, the optional configuration of shaping for groups, as well as for individual users with support for windows, linux, osx, ios, android clients, and all this on open solutions.
PS In this article, aspects of network security will not be touched upon, otherwise it will grow into a huge document, with a bunch of nuances in implementation, maybe I will tell you about the perimeter protection and network security next time.
Who cares, welcome under cat.

Table of contents:
Introduction
Preparatory work on the server
Accel-PPP (PPTP, L2TP)
Strongswan (IPsec)
Freeradius
Samba 4

As a result, we plan to get something like this:

The network has mobile clients, office clients and a secure network with important services, which should only be accessible via VPN, while office clients and mobile clients should receive different subnets from the VPN and have different rights to access resources, something common - only for one or the other, there are also administrators in the network, who should have full access to the company's internal infrastructure, both working from office and away, this scheme does not cover the internal office network with its servers available to the office users. to local users, and to mobile clients via VPN.
Start setting up the server.

0) Preparatory work.



Before proceeding directly to setting up a VPN, let's do some preparatory work.
And so we have a freshly installed server with Debian 7 (it doesn't matter, it will work in the same way on any other linux) in a minimal configuration. Login to it via ssh or in the local console, then:
We set the correct time zone (in the example I put MSK)
mv /etc/localtime /etc/localtime_org && ln -s /usr/share/zoneinfo/"Europe/Moscow" /etc/localtime && date 

Disable IPv6 if you do not plan to use it on this server.
 echo net.ipv6.conf.all.disable_ipv6=1 > /etc/sysctl.d/disableipv6.conf 

We include backports in turnips (so as not to put ancient samba and strongswan in which there are a number of problems), for this we add the following lines to /etc/apt/sources.list :
 deb http://http.debian.net/debian wheezy-backports main contrib non-free deb http://mirror.yandex.ru/debian/ wheezy-backports main contrib non-free 

Install the minimum required packages at this stage.
 apt-get update apt-get install cmake make libssl-dev libpcre3-dev libnet-snmp-perl libtritonus-bin bzip2 checkinstall ntpdate 

Synchronize the time on the server, it is better to immediately with the domain clock, the easiest option through
 ntpdate DC.DOMAIN.COM 

Specify the domain DNS server in /etc/resolv.conf
The firewall settings are specific to the company and are not published here, but based on it, we associate different subnets of VPN clients with different bans and permissions.

Here and below
XX.UY.1.99 - external IP of your server.

1) Accel-PPP - the main service for working with L2TP and PPTP



Description from the project site
ACCEL-PPP is a high-performance VPN / IPoE server for linux.
Its advantage over other solutions is the integration of various popular VPN technologies into a single application.
There are many open solutions for organizing VPN services, but they are all focused on one type of VPN: only PPTP, only PPPOE, only L2TP.
If you want to start a multiservice VPN server, you must study and configure each application separately.
With ACCEL-PPP, you get one application that supports everything, with a single configuration file, unified management and monitoring.
...
The project can be found in more detail here .

This VPN is very dimly lit, there are no references to Habré, more or less discussions revolve on one branch of the Naga , although by the convenience of operation, stability of work and opportunities it bypasses more popular solutions, but let's finish with the lyrics and get started.
')
Download and throw on the server.
 http://downloads.sourceforge.net/project/accel-ppp/accel-ppp-1.9.0.tar.bz2 

unzip
 tar -xjf accel-ppp-1.9.0.tar.bz2 mkdir accel-ppp-build cd accel-ppp-build 

we collect
 cmake -DBUILD_PPTP_DRIVER=FALSE -DLOG_PGSQL=FALSE -DNETSNMP=FALSE -DRADIUS=TRUE -DSHAPER=TRUE /root/accel-ppp-1.9.0/ make checkinstall -D 

Create an autorun script from the example.
 cd ../accel-ppp-1.9.0/contrib/debian cp accel-ppp-init /etc/init.d/accel-ppp 

Determine the directory with the demon
 which accel-pppd 

Most likely for deb will be / usr / local / sbin / accel-pppd
In the start file, change the path to the one obtained above.
 nano /etc/init.d/accel-ppp 

Add to autostart
 insserv -v accel-ppp 

Create a directory for logs
mkdir /var/log/accel-ppp/

Create a file with access to check connections, then replace it with radius authorization
 touch /etc/ppp/chap-secrets 

Format:
login * password ip _ for issue (if you need to take from the pool, then just *)

Create a configuration file /etc/accel-ppp.conf
Content
* tried to comment as much as possible on the options, uncomment chap-secrets during the test and comment out the radius in the modules section
 [modules] path=/usr/local/lib64/accel-ppp #        . log_file #     syslog. #log_syslog #  pptp l2tp #  auth_mschap_v2 auth_mschap_v1 auth_chap auth_pap #   CHAP-secrets   radius #chap-secrets #   RADIUS   chap-secrets radius # IPv4    . ippool sigchld #    ip-up/ip-down      RADIUS CoA . #pppd_compat #   . shaper #   . #connlimit [core] log-error=/var/log/accel-ppp/core.log thread-count=4 [ppp] verbose=0 min-mtu=1280 mtu=1480 mru=1480 #ccp=1 check-ip=1 #           . #    replace - accel-   ,    . #    deny accel-       #single-session=replace #   MPPE (Microsoft Point-to-Point Encryption) # prefer –        mppe=prefer ipv4=prefer #   ,   0,  PPP    LCP  -  n . lcp-echo-interval=300 #   -  ,    n   . lcp-echo-failure=6 [dns] dns1=8.8.8.8 dns2=8.8.4.4 [auth] #any-login=0 #noauth=0 [pptp] bind=..1.99 echo-interval=300 echo-failure=6 verbose=0 [l2tp] bind=..1.99 #ppp-max-mtu=1300 dictionary=/usr/local/share/accel-ppp/l2tp/dictionary hello-interval=300 #timeout=60 #rtimeout=5 retransmit=3 host-name=vpn.mydomain.ru #dir300_quirk=1 #secret= verbose=0 [radius] dictionary=/usr/local/share/accel-ppp/radius/dictionary nas-identifier=cisco nas-ip-address=127.0.0.1 gw-ip-address=..1.99 auth-server=127.0.0.1:1812,Radius-Sicret acct-server=127.0.0.1:1813,Radius-Sicret server=127.0.0.1,Radius-Sicret,auth-port=1812,acct-port=1813,req-limit=0,fail-time=0 dae-server=127.0.0.1:3799,Radius-Sicret timeout=5 max-try=3 acct-timeout=600 acct-delay-time=1 verbose=0 [shaper] attr=Filter-Id #down-burst-factor=1.0 #up-burst-factor=1.0 #latency=50 #mpu=0 #time-range=1,7:00-00:59 #time-range=2,1:00-3:59 #time-range=3,4:00-6:59 #leaf-qdisc=sfq perturb 10 up-limiter=htb down-limiter=htb cburst=1375000 ifb=ifb0 r2q=10 quantum=1500 verbose=0 #   IP-,         : xxxx/mask (for example 10.0.0.0/8) [client-ip-range] #192.168.0.0/18 disable [log] log-file=/var/log/accel-ppp/accel-ppp.log log-emerg=/var/log/accel-ppp/emerg.log log-fail-file=/var/log/accel-ppp/auth-fail.log log-debug=/var/log/accel-ppp/debug.log #syslog=accel-pppd,daemon #log-tcp=127.0.0.1:3000 copy=1 color=1 #per-user-dir=per_user #per-session-dir=per_session #per-session=1 level=0 #    ,     #[chap-secrets] #gw-ip-address=..1.99 #chap-secrets=/etc/ppp/chap-secrets [ip-pool] attr=Framed-Pool gw-ip-address=..1.99 10.65.16.129-254,fullaccess 10.65.17.129-254,mobila 10.65.18.129-254,office [cli] telnet=127.0.0.1:2000 tcp=127.0.0.1:2001 #password=123 #[connlimit] #limit=10/min #burst=3 #timeout=60 



Run
 service accel-ppp start 

If something is wrong, we increase the logging level in the config and look at the logs.

To work under load, a small tuning is needed, if you have less than 500 simultaneous clients on a VPN, you can not do it, except for the item net.ipv4.ip_forward = 1 , it is mandatory.

Add to /etc/sysctl.conf
############################
net.ipv4.ip_forward = 1
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh2 = 2048
net.ipv4.neigh.default.gc_thresh3 = 4096

net.ipv4.netfilter.ip_conntrack_max = 9548576
net.netfilter.nf_conntrack_max = 9548576

# turn select selective ACK and timestamps
net.ipv4.tcp_sack = 0
net.ipv4.tcp_timestamps = 0

# memory allocation min / pressure / max.
# read buffer, write buffer, and buffer space
net.ipv4.tcp_rmem = 10,000,000 10,000,000 10,000,000
net.ipv4.tcp_wmem = 10,000,000 10,000,000 10,000,000
net.ipv4.tcp_mem = 10,000,000 10,000,000 10,000,000

net.core.rmem_max = 524287
net.core.wmem_max = 524287
net.core.rmem_default = 524287
net.core.wmem_default = 524287
net.core.optmem_max = 524287
net.core.netdev_max_backlog = 300000
net.core.netdev_tstamp_prequeue = 0
############################

Apply:
 sysctl -p 

We try to connect with PPTP and L2TP without IPsec with the login and password specified in / etc / ppp / chap-secrets

On the server itself, you can view a list of connected clients
 accel-cmd show session 

I highly recommend reading the accel-cmd help, it has many features, including changing the user authorization method on the fly without interrupting sessions

If everything is OK, go to the next item.

2) IPsec



You can get acquainted with what it is and why you need it briefly here.

install
 apt-get -t wheezy-backports install strongswan libcharon-extra-plugins 

Configs are reduced to the form:
nano /etc/ipsec.conf
ipsec.conf
 # ipsec.conf - strongSwan IPsec configuration file config setup #           strictcrlpolicy=no include /var/lib/strongswan/ipsec.conf.inc conn %default ikelifetime=1440m keylife=60m rekeymargin=3m keyingtries=1 keyexchange=ikev1 authby=xauthpsk #   Dead Peer Detection (DPD)  ,     ,       dpdaction=clear #    DPD # dpddelay=35s #   DPD # dpdtimeout=300s #   .   IPsec  ,    IP-  fragmentation=yes #       . Windows   . rekey=no #  ciphersuites    IKE ike=aes256gcm16-aes256gcm12-aes128gcm16-aes128gcm12-aesxcbc-sha256-sha1-modp4096-modp2048-modp1024,aes256-aes128-sha256-sha1-modp4096-modp2048-modp1024! #  ciphersuites    esp=aes128gcm12-aes128gcm16-aes256gcm12-aes256gcm16-modp4096-modp2048-modp1024,aes128-aes256-sha1-sha256-modp4096-modp2048-modp1024,aes128-sha1-modp1024,aes128-sha1! conn L2TP_Accel-PPP authby=psk rekey=no type=transport esp=aes128-sha1,null-sha1,md5 ike=aes128-sha-modp1024,null-sha1,md5 left=194.135.1.99 leftprotoport=17/%any #  1701    iOS right=%any rightprotoport=17/%any rightsubnetwithin=0.0.0.0/0 auto=add compress=no dpddelay=30 dpdtimeout=120 dpdaction=clear forceencaps=yes conn IPsec authby=secret rekeymargin=3m keyingtries=1 keyexchange=ikev1 leftfirewall=yes rekey=no left=XX.YY.1.99 leftsubnet=0.0.0.0/0 leftauth=psk rightsourceip=%radius rightdns=8.8.8.8 right=%any rightauth=psk rightauth2=xauth-radius dpdaction=clear dpdtimeout = 5s auto=add 



Next, we indicate our private key
nano /etc/ipsec.secrets
: PSK "Sicret-Test-Key"

For further integration with Freeradius we also rule
nano /etc/strongswan.d/charon/eap-radius.conf
eap-radius.conf
 eap-radius { accounting = yes load = yes nas_identifier = StrongSwan #   Radius secret = Radius-Sicret server = 127.0.0.1 dae { enable = yes listen = 127.0.0.1 port = 3799 secret = Radius-Sicret } forward { } servers { } xauth { } } 


Run
 service ipsec start 

Status can be viewed as:
 ipsec statusall 


3) FreeRadius



* for those who do not know what it is.
Install as standard
 apt-get install freeradius freeradius-ldap 

The correct file is /etc/freeradius/clients.conf , which contains settings for FreeRadius users, we have local Accel-PPP and Strongswan demons, the following content is minimal:
 client localhost { ipaddr = 127.0.0.1 secret = Radius-Sicret nastype = cisco shortname = MY_TEST_VPN } 

Now we will prepare a profile for launch, the standard one is here / etc / freeradius / sites-enabled / default
, we need to bring it to mind:
/ etc / freeradius / sites-enabled / default
* LDAP integration is not configured yet. It is necessary to comment out all options related to ldap and ntlm_auth, later we will uncomment one of them, but not both, they conflict, if we don’t need LDAP groups, it’s easier to use ntlm_auth, if groups are needed, then ldap, In the example, the working config is already with groups
 authorize { preprocess chap mschap ldap # ntlm_auth digest suffix eap { ok = return } files expiration logintime pap } authenticate { Auth-Type PAP { pap } Auth-Type CHAP { chap } Auth-Type MS-CHAP { mschap } Auth-Type LDAP { ldap } # Auth-Type ntlm_auth { # ntlm_auth # } digest unix eap } preacct { preprocess acct_unique suffix files } accounting { detail unix radutmp exec attr_filter.accounting_response } session { radutmp } post-auth { exec Post-Auth-Type REJECT { attr_filter.access_reject } } pre-proxy { } post-proxy { eap } 


Now we will create a local user file, as well as a description of settings for various groups from LDAP
/ etc / freeradius / users
 #      ,    , #       #perl -e 'print(crypt("testpassword","abrakadabra")."\n");' #    #testuser Crypt-Password := "abA5hjwYqm1.I" testuser Cleartext-Password := "testpassword" , MS-CHAP-Use-NTLM-Auth := 0 Service-Type = Framed-User, Framed-Protocol = PPP, #     IP,      ,   Framed-Pool Framed-IP-Address = 10.65.18.12, Framed-IP-Netmask = 255.255.255.255, #       ,    ip-pool  accel-ppp Framed-Pool = "office", #      . Filter-Id = "100000/100000", #         ,    Reply-Message = "Accepted from local file" #        #   Idle-Timeout, Acct-Interim-Interval  .. #      LDAP,     # remote-connection   office,    ip-pool  accel-ppp DEFAULT Ldap-Group == "remote-connection" Service-Type = Framed-User, Framed-Protocol = PPP, Framed-Pool = "office", Filter-Id = "100000/100000" #     DEFAULT Ldap-Group == "full-access" Service-Type = Framed-User, Framed-Protocol = PPP, Framed-Pool = "fullaccess" #       # Filter-Id = "100000/100000" DEFAULT Ldap-Group == "mobile-access" Service-Type = Framed-User, Framed-Protocol = PPP, Framed-Pool = "mobila", Filter-Id = "100000/100000" 


Restart radius
 service freeradius restart 

* For debugging, you can run in the output mode of the log to the freeradius-X terminal
If everything is OK and there are no errors in the launch, check the test user:
 radtest testuser testpassword 127.0.0.1 0 Radius-Sicret 

we should get an answer like:
 Sending Access-Request of id 238 to 127.0.0.1 port 1812 User-Name = "testuser" User-Password = "testpassword" NAS-IP-Address = XX.YY.1.99 NAS-Port = 0 Message-Authenticator = 0x00000000000000000000000000000000 rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=238, length=105 Service-Type = Framed-User Framed-Protocol = PPP Framed-IP-Address = 10.65.18.12 Framed-IP-Netmask = 255.255.255.255 Framed-Pool = "office" Filter-Id = "100000/100000" Reply-Message = "Accepted from local file" 

If the answer is an Access-Accept , then everything is fine and you can proceed to setting up the integration of Freeradius with LDAP, put the configs in this section in advance, we need to correct:
nano / etc / freeradius / modules / ntlm_auth
* instead of KR.LOC just specify your domain
 exec ntlm_auth { wait = yes program = "/usr/bin/ntlm_auth --request-nt-key --domain=KR.LOC --username=%{mschap:User-Name} --password=%{User-Password}" } 

Slightly correct authorization through mschap, since pap is not safe to use.
nano / etc / freeradius / modules / mschap
 mschap { #  use_mppe = yes #      ,     ,    -   yes require_encryption = no require_strong = yes with_ntdomain_hack = no ntlm_auth = "/usr/bin/ntlm_auth --request-nt-key --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%{mschap:Challenge}:-00} --nt-response=%{%{mschap:NT-Response}:-00}" } 

well and most importantly, integration with LDAP directly
nano / etc / freeradius / modules / ldap
bring to mind
* Do not forget to change the parameters of access to ldap to your own, user account must have permissions to read profiles in the domain.
 ldap { server = "10.13.205.7" #  identity = "sf-test@KR.LOC" #  password = "987654321" #   basedn = "dc=KR,dc=LOC" #   filter = "(sAMAccountName=%{%{Stripped-User-Name}:-%{User-Name}})" ldap_connections_number = 5 max_uses = 0 #port = 389 timeout = 4 timelimit = 3 net_timeout = 1 tls { start_tls = no } dictionary_mapping = ${confdir}/ldap.attrmap password_attribute = userPassword edir_account_policy_check = no groupname_attribute = cn groupmembership_filter = "(|(&(objectClass=GroupOfNames)(member=%{control:Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{control:Ldap-UserDn})))" groupmembership_attribute = memberOf access_attr_used_for_allow = yes chase_referrals = yes rebind = yes # set_auth_type = yes keepalive { idle = 60 probes = 3 interval = 3 } } 


Another important point is that in order to get the radius attributes for a specific user directly from the domain ldap attributes, you need to adjust their correspondence to each other, this is done in the /etc/freeradius/ldap.attrmap file there is a lot already filled in and intuitively clear, but for example I will show several of their own:
 replyItem Framed-IP-Address msRADIUSFramedIPAddress replyItem Framed-Pool msRADIUSFramedRoute 

Thus, specifying the personal attribute msRADIUSFramedIPAddress in the domain of the user, we will transfer the radius to consider it as the Framed-IP-Address attribute and give it to the user specifically via VPN, for pools by analogy.
From the domain side, it looks like this:

IP needs to be converted to HEX on any IP calculator , you can of course create any of your attributes for ldap, through the attribute editor, but for an accelerated description we will use the standard ones.

* these options will be available after configuring samba4, you need to remember to uncomment the ldap section in / etc / freeradius / sites-enabled / default

4) SAMBA 4



* brief help

First, install everything you need:
 apt-get install krb5-user libpam-krb5 samba winbind libnss-winbind libpam-winbind -t wheezy-backports 

The samba settings are in the /etc/samba/smb.conf file.
smb.conf
* Do not forget to change the domain name to your own.
 [global] obey pam restrictions = Yes log file = /var/log/samba/log.%m log level = 1 socket options = TCP_NODELAY SO_SNDBUF=8192 SO_RCVBUF=8192 encrypt passwords = yes idmap config * : range = 10000-20000 idmap config * : backend = tdb auth methods = winbind name resolve order = hosts bcast lmhosts case sensitive = no dns proxy = no netbios name = SAMBA server string = %v samba password server = DC02.KR.LOC #        realm = KR.LOC client use spnego = yes client signing = yes local master = no domain master = no preferred master = no workgroup = KR debug level = 2 # ads        security = ads unix charset = UTF-8 dos charset = 866 max log size = 50 os level = 0 follow symlinks = yes winbind uid = 10000-20000 winbind gid = 10000-20000 winbind enum groups = yes winbind enum users = yes 


Now we’ll configure winbind (allows Samba to recognize AD users and communicate with them as local).
We need to edit the /etc/nsswitch.conf file, add to it:
 passwd: compat winbind group: compat winbind shadow: compat winbind 


It remains to configure Kerberos (used to integrate Samba into Active Directory)
We bring file / etc / krb5.conf to a type
krb5.conf
* Domain change to your.
  [logging] default = FILE:/var/log/krb5.log kdc = FILE:/var/log/krb5kdc.log [libdefaults] default_realm = KR.LOC clockskew = 500 dns_lookup_realm = false dns_lookup_kdc = true ticket_lifetime = 324000 [realms] KR.LOC = { kdc = DC02.KR.LOC admin_server = DC02.KR.LOC default_domain = KR.LOC } [domain_realm] .kr.loc = KR.LOC [login] krb4_convert = true krb4_get_tickets = false 


Configs corrected, you can restart services:
 service samba restart service winbind restart 

Check for your domain user:
 kinit sf-test@KR.LOC 

We receive a request to enter a password, enter.
 Password for sf-test@KR.LOC: 

If everything is OK, there will be no output on the screen, if everything does output something, carefully read and correct the errors in the config.
We consider that you are fine and enter the server into the domain
 net join –U sf-test@KR.LOC 

Check winbind's work:
 wbinfo -u wbinfo -g 

The output should see a list of domain users and groups.

To check whether domain users are perceived as local, you can use the command:
 id domain_user 

We check the operation of the authentication module (login / password / domain - of course your own)
 ntlm_auth --request-nt-key --domain=KR.LOC --username=sf-test --password=123456789 

Got OK, so you can uncomment the ldap or ntlm_auth module in the radius config (if you don’t need domain groups), restart freeradius and enjoy the work of the VPN server with domain uchetka, but to calm the conscience we’ll check that the radius authorizes domain users:
 radtest -t mschap sf-test 123456789 127.0.0.1 0 Radius-Sicret 

Now you can create a VPN connection at your place and check the entire bundle.

5) Bonus


Scrolling through the note again looked at the network diagram and remembered that we have site-to-site connections for IPsec - this is also convenient if VPN users need to be given access to other networks, all this is implemented by firewall, but the example of setting up strongswan for such connections cite below.
ipsec.conf
Add the following section to /etc/ipsec.conf:
 conn juniper forceencaps=yes dpddelay=30 # Dead peer detection - 30  -   keep-alive  dpdtimeout=120 # dpd  120 ,       # IKE alg 3DES - HASH sha1 - DH group 2 (1024) ike=3des-sha1-modp1024 # IKE lifetime 86400 seconds (24 hours) ikelifetime=86400s # IKE auth method Pre-Shared Key (PSK secret) authby=secret # IPSec type tunnel type=tunnel #  -  #left side (myside) left=..1.99 # OpenSWAN side leftsubnet=10.65.0.0/16 #  ,      right=..116.5 #  rightsubnet=192.168.105.0/24 #   ,     VPN auto=start esp=3des-sha1,3des-md5 keyexchange=ikev1 


Conclusion


I hope everything worked out the first time and immediately worked, if it is not so - ask questions in the comments. The author is pathologically illiterate, if you see a mistake, a typo, not unambiguity or any other moment that interferes with the perception of the note - please inform in a personal. Thank you all for your time.

Source: https://habr.com/ru/post/267103/


All Articles