Back to Home

How-to-style VPN server (pptpd + mysql + radius) on CentOS6

job · work · pptpd · mysql · radius · vpn · l2tp · xl2tpd

How-to-style VPN server (pptpd + mysql + radius) on CentOS6

    imageAlthough how-to-style articles are not very commented on, and mostly not with positive comments, however, it is them that are most often added to bookmarks.
    Here I will try to describe the process of installing and configuring a VPN server on CentOS6 with users in MySQL and authorizing via radius for an encrypted connection using ms-chap-v2 and mppe.

    Preamble

    Where do these articles come from? Everything is simple. When we look for job seekers, for example, for the position of system administrator, then after selecting candidates for a preliminary interview, test tasks are compiled, implemented on our own, and then we offer them to be solved by applicants. To complete the tasks, the applicant is provided with a virtual machine, Internet access, and a certain time. Time is calculated simply - our implementation * 2. At the same time, you can consider that all the necessary solutions (how-to) can be found on the Internet, however, we take this into account, and therefore we do not take ready-made solutions, but compile and solve them ourselves first, on fresh distributions. By the way, there are times when we come across certain problems during implementation (small, undocumented pranks of developers), and in the case of


    Given

    KVM virtual machine with white IP and freshly installed CentOS6 x86_64 minimal.

    Task

    1. Install and configure in a bunch of pptpd, freeradius2, radiusclient-ng and mysql.
    2. Create 2 clients to connect to the configured VPN server, with access to no through NAT. One client with dynamic address acquisition, the second with a constant IP.
    3. Transfer pool of addresses for distribution to dynamic clients from pptpd to radius.

    Decision

    The first step is to install all the necessary packages. radiusclient-ng and pptpd are not in standard repositories, so for radiusclient-ng we will connect an EPEL repository, and download the pptpd package directly. next, configure mysql and set the password: Actually, let's move on to pptpd configuration. We bring the configuration files to the following form: we are done with pptpd, go on to configure radiusclient-ng: The first problem we encountered is the reluctance of pptpd to work with radiusclient-ng because of the paths where it is installed, so we create a soft link as follows and comment out the file /etc/radiusclient-ng/radiusclient.conf line otherwise swears at an unknown parameter.
    # rpm -Uhv fedora-epel.mirror.lstn.net/6/x86_64/epel-release-6-5.noarch.rpm
    # yum install freeradius freeradius-mysql radiusclient-ng radiusclient-ng-utils freeradius-utils mysql mysql-devel mysql-server
    #rpm -Uhv poptop.sourceforge.net/yum/stable/packages/pptpd-1.3.4-2.el6.x86_64.rpm



    mysql_secure_installation


    # cat /etc/pptpd.conf
    option /etc/ppp/options.pptpd
    logwtmp
    localip 192.168.80.1
    remoteip 192.168.80.5-35


    # cat /etc/ppp/options.pptpd
    name pptpd
    refuse-pap
    refuse-chap
    refuse-mschap
    require-mschap-v2
    require-mppe-128
    proxyarp
    lock
    nobsdcomp
    novj
    novjccomp
    nologfd
    plugin radius.so
    plugin radattr.so





    # ln -s /etc/radiusclient-ng /etc/radiusclient

    #bindaddr *

    edit / etc / radiusclient-ng / servers, add the local radius server that the client will contact
    localhost YouRsUpErpAAs

    The second problem we had to deal with was the absence of mircosoft attributes in the radiusclient-ng package, after googling, the necessary artibuts were found. copy existing files with attributes from / usr / share / radiusclient-ng / to / etc / radiusclient-ng /
    # cp /usr/share/radiusclient-ng/diction* /etc/radiusclient-ng/
    to / etc / radiusclient-ng / create a dictionary.microsoft file with the following contents: edit the file / etc / radiusclient-ng / radiusclient .conf for the subject, edit the file / etc / radiusclient-ng / dictionary, adding to the end with the client also finished, we proceed to configure mysql:
    VENDOR Microsoft 311 Microsoft

    ATTRIBUTE MS-CHAP-Response 1 string Microsoft
    ATTRIBUTE MS-CHAP-Error 2 string Microsoft
    ATTRIBUTE MS-CHAP-CPW-1 3 string Microsoft
    ATTRIBUTE MS-CHAP-CPW-2 4 string Microsoft
    ATTRIBUTE MS-CHAP-LM-Enc-PW 5 string Microsoft
    ATTRIBUTE MS-CHAP-NT-Enc-PW 6 string Microsoft
    ATTRIBUTE MS-MPPE-Encryption-Policy 7 string Microsoft
    ATTRIBUTE MS-MPPE-Encryption-Type 8 string Microsoft
    ATTRIBUTE MS-MPPE-Encryption-Types 8 string Microsoft
    ATTRIBUTE MS-RAS-Vendor 9 integer Microsoft
    ATTRIBUTE MS-CHAP-Domain 10 string Microsoft
    ATTRIBUTE MS-CHAP-Challenge 11 string Microsoft
    ATTRIBUTE MS-CHAP-MPPE-Keys 12 string Microsoft
    ATTRIBUTE MS-BAP-Usage 13 integer Microsoft
    ATTRIBUTE MS-Link-Utilization-Threshold 14 integer Microsoft
    ATTRIBUTE MS-Link-Drop-Time-Limit 15 integer Microsoft
    ATTRIBUTE MS-MPPE-Send-Key 16 string Microsoft
    ATTRIBUTE MS-MPPE-Recv-Key 17 string Microsoft
    ATTRIBUTE MS-RAS-Version 18 string Microsoft
    ATTRIBUTE MS-Old-ARAP-Password 19 string Microsoft
    ATTRIBUTE MS-New-ARAP-Password 20 string Microsoft
    ATTRIBUTE MS-ARAP-PW-Change-Reason 21 integer Microsoft
    ATTRIBUTE MS-Filter 22 string Microsoft
    ATTRIBUTE MS-Acct-Auth-Type 23 integer Microsoft
    ATTRIBUTE MS-Acct-EAP-Type 24 integer Microsoft
    ATTRIBUTE MS-CHAP2-Response 25 string Microsoft
    ATTRIBUTE MS-CHAP2-Success 26 string Microsoft
    ATTRIBUTE MS-CHAP2-CPW 27 string Microsoft
    ATTRIBUTE MS-Primary-DNS-Server 28 ipaddr Microsoft
    ATTRIBUTE MS-Secondary-DNS-Server 29 ipaddr Microsoft
    ATTRIBUTE MS-Primary-NBNS-Server 30 ipaddr Microsoft
    ATTRIBUTE MS-Secondary-NBNS-Server 31 ipaddr Microsoft
    VALUE MS-BAP-Usage Not-Allowed 0
    VALUE MS-BAP-Usage Allowed 1
    VALUE MS-BAP-Usage Required 2
    VALUE MS-ARAP-PW-Change-Reason Just-Change-Password 1
    VALUE MS-ARAP-PW-Change-Reason Expired-Password 2
    VALUE MS-ARAP-PW-Change-Reason Admin-Requires-Password-Change 3
    VALUE MS-ARAP-PW-Change-Reason Password-Too-Short 4
    VALUE MS-Acct-Auth-Type PAP 1
    VALUE MS-Acct-Auth-Type CHAP 2
    VALUE MS-Acct-Auth-Type MS-CHAP-1 3
    VALUE MS-Acct-Auth-Type MS-CHAP-2 4
    VALUE MS-Acct-Auth-Type EAP 5
    VALUE MS-Acct-EAP-Type MD5 4
    VALUE MS-Acct-EAP-Type OTP 5
    VALUE MS-Acct-EAP-Type Generic-Token-Card 6
    VALUE MS-Acct-EAP-Type TLS 13



    dictionary /etc/radiusclient-ng/dictionary


    INCLUDE /etc/radiusclient-ng/dictionary.microsoft
    INCLUDE /etc/radiusclient-ng/dictionary.merit



    the freeradius-mysql package contains the necessary files to import them into mysql, they are located in / etc / raddb / sql / mysql / we
    edit the admin.sql file to set a password different from the standard one , we connect to mysql, create a DB, import tables and create users then we create users and their settings should be as follows fill the table radgroupreply and so on, to get the next fill the table radreply to set a permanent ip for the first client
    vim admin.sql
    :%s/radpass/radpass235/g
    :wq


    mysql -p
    mysql> create database radius;
    mysql> \. admin.sql
    mysql> use radius;
    mysql> \. schema.sql


    mysql> INSERT INTO radusergroup (username,groupname) values ('user1','static-ip-vpn');
    mysql> INSERT INTO radusergroup (username,groupname) values ('user2','dinamic-ip-vpn');


    mysql> select * from radusergroup;
    +----------+----------------+----------+
    | username | groupname | priority |
    +----------+----------------+----------+
    | user1 | static-ip-vpn | 1 |
    | user2 | dinamic-ip-vpn | 1 |
    +----------+----------------+----------+

    mysql> INSERT INTO radcheck (username,attribute,op,value) values ('user1','User-Password','==','pass1');
    mysql> INSERT INTO radcheck (username,attribute,op,value) values ('user2','User-Password','==','pass2');

    mysql> select * from radcheck;
    +----+----------+---------------+----+-------+
    | id | username | attribute | op | value |
    +----+----------+---------------+----+-------+
    | 1 | user1 | User-Password | == | pass1 |
    | 2 | user2 | User-Password | == | pass2 |
    +----+----------+---------------+----+-------+


    mysql> INSERT INTO radgroupreply (groupname, attribute, op, value) values ('dinamic-ip-vpn','Service-Type',':=','Framed-User');

    mysql> select * from radgroupreply;
    +----+----------------+--------------------+----+---------------------+
    | id | groupname | attribute | op | value |
    +----+----------------+--------------------+----+---------------------+
    | 1 | dinamic-ip-vpn | Service-Type | := | Framed-User |
    | 2 | dinamic-ip-vpn | Framed-Protocol | := | PPP |
    | 3 | dinamic-ip-vpn | Framed-Compression | := | Van-Jacobsen-TCP-IP |
    | 4 | static-ip-vpn | Framed-Compression | := | Van-Jacobsen-TCP-IP |
    | 5 | static-ip-vpn | Framed-Protocol | := | PPP |
    | 6 | static-ip-vpn | Service-Type | := | Framed-User |
    +----+----------------+--------------------+----+---------------------+



    mysql> INSERT INTO radreply (username, attribute, op, value) values ('user1','Framed-IP-Netmask',':=','255.255.255.255');
    mysql> INSERT INTO radreply (username, attribute, op, value) values ('user1','Framed-IP-Address',':=','192.168.80.90');

    mysql> select * from radreply;
    +----+----------+-------------------+----+-----------------+
    | id | username | attribute | op | value |
    +----+----------+-------------------+----+-----------------+
    | 1 | user1 | Framed-IP-Netmask | := | 255.255.255.255 |
    | 2 | user1 | Framed-IP-Address | := | 192.168.80.90 |
    +----+----------+-------------------+----+-----------------+

    As a result, we entered this database of 2 clients, user1 with the password pass1 and static ip - 192.168.80.90, and user2 with the password pass2 and getting a dynamic ip from the pool specified in the pptpd settings. Here, users are deliberately divided into groups, taking into account the further increase in customers, it was possible to simply create all the attributes for both customers in the radreply table, but with a large number of customers, it is more convenient to use groups where the same attributes are indicated for customers of the group. Also, in groups you can specify different address pools and much more, but we won’t talk about that now, because we need to solve the problem on time.

    Go to the radius settings. Here I will give examples of files in which changes were made:
    /etc/raddb/clients.conf Third problem
    client 127.0.0.1 {
    secret = YouRsUpErpAAs
    shortname = localhost
    nastype = other
    }


    , at the time of debugging, when radius was not yet connected to mysql, they were faced with the fact that if the clients in the / etc / raddb / users file were not written at the beginning of the file, nothing worked.

    / etc / raddb / users It is necessary to register this so that there are no multiple connections with the same login at the same time /etc/raddb/radiusd.conf in the modules section we remove comments from /etc/raddb/sql.conf we write the data for connecting to mysql / etc / raddb / sites-enabled / default in the authorize, session, post-auth and accounting sections enable sql in the authorize sections enable mschap / etc / raddb / modules / mschap Perhaps the task has been practically solved, some touches remained:
    DEFAULT Simultaneous-Use := 1
    Fall-Through = 1





    $INCLUDE sql.conf



    password = "radpass235"






    mschap {
    use_mppe = yes
    require_encryption = yes
    require_strong = yes
    }




    Configure iptables and enable forward to release clients to the world /etc/sysctl.conf Already at this stage, if we run the installed services, we can connect to our machine via vpn, it remains only to transfer the pool of addresses issued to dynamic clients from pptpd to radius. There are several options for this, down to putting the pool in mysql. We use a simple option. / etc / raddb / modules / ippool in the ippool main_pool section, make edits for our address pool in the file / etc / raddb / sites-enabled / default, add them to the corresponding sections next, create files where the pool will be stored and add it to / etc / raddb / users
    iptables -I INPUT -p gre -j ACCEPT
    iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 1723 -j ACCEPT
    iptables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -I FORWARD -s 192.168.80.0/24 -o eth0 -j ACCEPT
    iptables -I FORWARD -d 192.168.80.0/24 -i eth0 -j ACCEPT
    iptables -t nat -I POSTROUTING -s 192.168.80.0/24 -o eth0 -j MASQUERADE



    net.ipv4.ip_forward = 1
    # sysctl -p






    range-start = 192.168.80.35
    range-stop = 192.168.80.65




    accounting {
    main_pool
    }

    post-auth {
    main_pool
    }



    touch /etc/raddb/db.ipindex /etc/raddb/db.ippool
    chmod 664 /etc/raddb/db.ipindex /etc/raddb/db.ippool
    chown root:radiusd /etc/raddb/db.ipindex /etc/raddb/db.ippool



    DEFAULT Pool-Name := main_pool
    Fall-Through = Yes


    restart radius, and try connecting to the machine via vpn, everything should work. We can see detailed connection statistics in the radius.radacct table of the
    selected addresses from the pool, you can see the command:
    rlm_ippool_tool -av /etc/raddbdb/db.ippool /etc/raddbdb/db.ipindex

    Afterword


    I deliberately emphasized the problems that we had to face. We spent a little over an hour deploying this system. 2.5 hours were allotted for candidates. None of the 4 applicants completed this task in full. Only one of them almost reached the end of the journey. With him, perhaps we will continue to cooperate.
    Of course, I understand that not all employers use this method of testing job seekers. However, I think this is one of the best ways to really test the knowledge and capabilities of candidates. After all, if the candidate has solved (or almost solved) a similar problem, then after some time, joining the team and immersion in the network structure, it is quite possible to rely on him.

    I could name the article - “How we choose workers”, and describe the process of preliminary selection and practical assignment in general terms, but then, the article would not have its value as near-technical, and would not be in the form of how-to, but it would be less useful, in my opinion. I know that there are several similar articles, up to linking with abills, but they are more than one and a half years old and they are under other distros.

    UPD: perhaps job seekers read Habr, and, at last, will see the solution of the task which they did not pass.

    UPD2: Regarding the lack of time for implementation, they write that 2.5 hours is not enough. I emphasize that time is not the main , although significant indicator. The main thing is the “right way”.

    UPD3:Inspired by the comments about the pptp protocol sludge. The situation is identical with l2tp.
    Instead of pptpd, put xl2tpd.
    #yum install xl2tpd
    The settings files are reduced to the following form:
    # cat /etc/xl2tpd/xl2tpd.conf
    [global]
    port = 1701
    auth file = /etc/xl2tpd/l2tp-secrets
    access control = no
    rand source = dev
    [lns default]
    exclusive = no
    ip range = 192.168.80.5-192.168.81.35
    local ip = 192.168.80.1
    require chap = yes
    refuse pap = yes
    require authentication = yes
    name = VPNserver
    ppp debug = yes
    pppoptfile = /etc/ppp/options.xl2tpd
    length bit = yes
    flow bit = yes


    # cat /etc/ppp/options.xl2tpd
    ipcp-accept-local
    ipcp-accept-remote
    lcp-echo-failure 30
    lcp-echo-interval 5
    noccp
    nodeflate
    auth
    crtscts
    idle 1800
    mtu 1410
    mru 1410
    defaultroute
    debug
    proxyarp
    connect-delay 5000
    lock
    plugin radius.so
    plugin radattr.so

    Read Next