1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

two factor authentication in OpenVPN

Discussion in 'Tomato Firmware' started by humba, Oct 6, 2013.

  1. humba

    humba Network Guru Member

    Hi

    Has anyone gotten this working? I've seen plenty of instructions and pre-built modules for x86 but I've not seen anything for routers.
     
  2. lancethepants

    lancethepants Network Guru Member

    Absolutely possible.

    It's a little tricky to setup, but it can be done. Somebody also asked this same thing, except about ssh. I created a guide to do this, and now use it myself.

    The tricky thing is that we need PAM support to use google two-factor authentication. Tomato does not have libpam integrated. I'm not even sure libpam is available in entware. Even if it were, openvpn needs to be re-compiled explicitly with libpam support.

    For this exact reason I created a project of mine called Tomatoware.
    Using Tomatoware (which already has libpam support) you can compile a new version of openvpn that will be able to manage two-factor authentication. From there we can trick the gui to use our own binary using a 'mount' command, throw in a few extra arguments in OpenVPN's custom configuration, and voila.

    At least I think it should be about that easy, haven't tried it myself yet. I'm confident it can be done though. I'll take a look at it in the next few days and see what I can come up with.
     
    Last edited: Oct 7, 2013
  3. lancethepants

    lancethepants Network Guru Member

    Explanation of Tomatoware

    I've decided to use this tutorial to showcase my project called Tomatoware.

    Downloads at http://lancethepants.com/files
    Project hosted at https://github.com/lancethepants/tomatoware

    Tomatoware
    IS similar to optware/entware, in that you install (extract) it to the /opt directory, which is a mounted external USB mass storage device.
    IS NOT a package manager. Any program you may want, you can compile right on the router using Tomatoware. It comes with many utilities; python, perl, pam, openssh, compiler, base set of libraries commonly needed.
    Tomtoware gives you the flexibility and power to do just about do anything you can do on non-embedded linux.

    TUTORIAL

    1. Install (extract) Tomatoware to your CLEAN /opt directory. You NEED Tomatoware v0.5 or later for this tutorial.

    Code:
    tar zxvf opt.tgz -C /opt
    
    Re-login to allow several environment variable now be set.


    2. We need to compile a version of OpenVPN with plugin support.

    Code:
    #compile openvpn with libpam support
    mkdir -p /opt/vpn && cd /opt/vpn
    wget http://swupdate.openvpn.org/community/releases/openvpn-2.3.2.tar.gz
    tar zxvf openvpn-2.3.2.tar.gz
    cd openvpn-2.3.2
    ./configure --prefix=/opt --enable-pam-dlopen
    make
    make install
    


    3. Compile google authentication module

    Code:
    #compile google pam two-factor authentication
    mkdir -p /opt/vpn && cd /opt/vpn
    wget https://google-authenticator.googlecode.com/files/libpam-google-authenticator-1.0-source.tar.bz2
    tar xvjf libpam-google-authenticator-1.0-source.tar.bz2
    cd libpam-google-authenticator-1.0
    make
    cp google-authenticator /opt/bin/
    cp pam_google_authenticator.so /opt/lib/security/
    


    4. Compile libqrencode so we can have nice qr codes our phones can scan.

    Code:
    #compile libqrencode
    mkdir -p /opt/vpn && cd /opt/vpn
    wget http://fukuchi.org/works/qrencode/qrencode-3.4.3.tar.gz
    tar zxvf qrencode-3.4.3.tar.gz
    cd qrencode-3.4.3
    ./configure --prefix=/opt --without-tools
    make
    make install
    


    5. Create user(s), and store them in nvram. Tomato will nicely append these to the passwd/shadow files on boot.

    Code:
    echo "user:x:0:0:root:/opt:/bin/sh" >> /etc/passwd.custom
    echo "user:\$1\$p7ji1sSO\$a0dvOOsF4SGd7TU8.PD101:15850:0:99999:7:::" >> /etc/shadow.custom
    nvram setfile2nvram /etc/passwd.custom
    nvram setfile2nvram /etc/shadow.custom
    nvram commit
    
    Take note of where you're user(s) $HOME directory is. In this case user 'user' has the home directory of /opt. This is where their google authentication file will go. Give your users different home directories if you want each one to have its own google authentication. Otherwise they will share the same one if you leave them the same. This user 'user' has password 'password'.

    If you need to generate new passwords, this is the easiest way to quickly explain a method.
    1. Set password in tomato gui.
    2. Look at /etc/shadow, and copy the root password.
    3. Manually paste it in /etc/shadow.custom for the desired user.
    4. Double check it matches root's and is entered correctly.

    If you use the 'echo' command as above, you must delimit special characters with '\'



    6. Create the /opt/etc/pam.d directory

    Code:
    mkdir -p /opt/etc/pam.d
    


    7. Create file filed called 'openvpn' in /opt/etc/pam.d, with the following contents.

    Code:
    auth       required     pam_google_authenticator.so forward_pass secret=${HOME}/.google_authenticator
    auth    [success=1 default=ignore]      pam_unix.so use_first_pass
    auth    requisite                       pam_deny.so
    auth    required                        pam_permit.so
    
    account [success=1 new_authtok_reqd=done default=ignore]        pam_unix.so
    account requisite                       pam_deny.so
    account required                        pam_permit.so
    
    password        [success=1 default=ignore]      pam_unix.so obscure md5
    password        requisite                       pam_deny.so
    password        required                        pam_permit.so
    
    session [default=1]                     pam_permit.so
    session requisite                       pam_deny.so
    session required                        pam_permit.so
    session required        pam_unix.so
    


    8. Append the following to /opt/.autorun. (Included with Tomatoware). This will make the tomato gui use our newly compiled openvpn binary instead of the one included in tomato.

    Code:
    /bin/mount --bind /opt/sbin/openvpn /usr/sbin/openvpn
    


    9. Create the google authenticator file. Adjust the '-s' option path to your user's set home directory.

    Code:
    google-authenticator -s /opt/.google_authenticator
    
    Scan the barcode with your smart-phone using the google-authenticator app.


    10. Place the following in the OpenVPN server 'custom configuration' in the gui.

    Code:
    plugin /opt/lib/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn
    
    Depending on how you want your OpenVPN server setup, you may wish to use the following OpenVPN custom options. Just something to mention, but this is outside the scope of this article.

    Code:
    client-cert-not-required
    username-as-common-name
    

    That's it as far as the server setup goes. Hopfeully that should cover it. Respond with any issues.
    REBOOT your router once you're all set up.





    Your client will need the following in its config
    Code:
    auth-user-pass
    
    When logging in from your OpenVPN client, using our example user.

    username: user
    password: password######

    Where the six '#' are the (6) digits provided from your google authenticator app.
     
    Last edited: Oct 10, 2013
    Goggy likes this.
  4. z3braman

    z3braman Reformed Router Member

    Wow. That's pretty cool. Even if it doesn't work I've got a month's worth of learning on this page alone!

    Paul
     
  5. lancethepants

    lancethepants Network Guru Member

    It is pretty cool! Tomatoware is perfect for situations like this. It gives you the power to do just about anything you can do on a full linux distibution.

    My next release of Tomatoware, V0.6, whenver I release it, will have a few different options.
    Up to now, tomatoware hasn't been able to co-exist with entware, since both systems are programed to mount to the /opt directory. With V0.6, I will release versions that can be mounted to /mmc, /jffs, or any other requested prefix.
    This way you can get the best of both worlds.
     
    jerrm likes this.
  6. Anoop

    Anoop Network Newbie Member

    if i wanted to use this with another plugin, like duo, can i just compile openvpn as it is and it will include plugin support?

    then i can plugin my duo module which i also plan to compile on tomato.
     
  7. Anoop

    Anoop Network Newbie Member

    The OpenVPN build failed.

    gcc -DHAVE_CONFIG_H -I. -I../.. -I../../include -I../../src/compat -g -O2 -MT options.o -MD -MP -MF .deps/options.Tpo -c -o options.o options.c
    gcc: internal compiler error: Killed (program cc1)
    Please submit a full bug report,
    with preprocessed source if appropriate.
    See <http://gcc.gnu.org/bugs.html> for instructions.
    Makefile:546: recipe for target 'options.o' failed
    make[3]: *** [options.o] Error 4
    make[3]: Leaving directory '/opt/vpn/openvpn-2.3.2/src/openvpn'
    Makefile:334: recipe for target 'all-recursive' failed
    make[2]: *** [all-recursive] Error 1
    make[2]: Leaving directory '/opt/vpn/openvpn-2.3.2/src'
    Makefile:511: recipe for target 'all-recursive' failed
    make[1]: *** [all-recursive] Error 1
    make[1]: Leaving directory '/opt/vpn/openvpn-2.3.2'
    Makefile:398: recipe for target 'all' failed
    make: *** [all] Error 2


    I configured it with

    ./configure --prefix=/opt

    and then make failed.

    any advice?

    thanks.
     
  8. lancethepants

    lancethepants Network Guru Member

    I'm not familiar with duo, but if it's doable on x86 linux with OpenVPN, I'm sure it could probably work on these routers. Can you point me to the source?

    Sometimes the routers get overloaded when compiling. Just run 'make' again and it should pick up from where it stopped.
     
  9. Anoop

    Anoop Network Newbie Member

    Sure. here's the link that discusses it. Seems pretty straight forward. I tried with optware but getting a compiler on it seemed more difficult that i initially expected.

    https://www.duosecurity.com/docs/openvpn

    The compile has failed on me several times now. I'm wondering if my Linksys E3000 just can't handle it.

    I'm trying by killing everything else i can so there's enough memory for it.

    I also noticed that tomatoware by default starts up asterisk. So i killed that too.

    stilll no luck

    Making all in openvpn
    make[3]: Entering directory '/opt/vpn/openvpn-2.3.2/src/openvpn'
    gcc -DHAVE_CONFIG_H -I. -I../.. -I../../include -I../../src/compat -g -O2 -MT options.o -MD -MP -MF .deps/options.Tpo -c -o options.o options.c
    gcc: internal compiler error: Killed (program cc1)
    Please submit a full bug report,
    with preprocessed source if appropriate.
    See <http://gcc.gnu.org/bugs.html> for instructions.
    Makefile:546: recipe for target 'options.o' failed
    make[3]: *** [options.o] Error 4
    make[3]: Leaving directory '/opt/vpn/openvpn-2.3.2/src/openvpn'
    Makefile:334: recipe for target 'all-recursive' failed
    make[2]: *** [all-recursive] Error 1
    make[2]: Leaving directory '/opt/vpn/openvpn-2.3.2/src'
    Makefile:511: recipe for target 'all-recursive' failed
    make[1]: *** [all-recursive] Error 1
    make[1]: Leaving directory '/opt/vpn/openvpn-2.3.2'
    Makefile:398: recipe for target 'all' failed
    make: *** [all] Error 2
     
  10. Anoop

    Anoop Network Newbie Member

    woop!

    shutting off http helped a lot.

    turning it back on took a bit of reading but seems like everything it working.

    So Two factor with duo security is setup somewhat similar to what you have above.

    so now i've got it setup to push to my iphone so that everytime i login, it uses the CN from my cert and then sends a request to duo to send a request to my phone which i then have to approve before the login completes :)

    screen cap

    http://imgur.com/zm5uk04
     
  11. lancethepants

    lancethepants Network Guru Member

    Awesome! I was playing around with it a bit yesterday. Does the CN from the cert need to match a username on duo?
     
  12. Anoop

    Anoop Network Newbie Member

    I believe so. that's the way i've got it setup.

    of course, i'm the only user at the moment but i'm going to recreate my entire PKI from scratch so it's managed a little better.

    it's pretty cool i think and it's free for up to 10 users. :)

    Cheers! and thanks for the howto for openvpn above. works a charm!
     
  13. lancethepants

    lancethepants Network Guru Member

    I finally got it to work. Since you're using the /opt version of Tomatoware, and tomato already include /opt directories in its PATH it works much easier. I use the /mmc version, so I had to modify a couple of things in the source and python interpreter lines to get it to work.

    I really like this setup. I especially like the various ways of authenticating; passcode, sms, phone call. May favorite is the push method, then all you have to do is hit approve on your phone and your connected!

    Slick feature, and thanks for pointing it out to me.
     
  14. Anoop

    Anoop Network Newbie Member

    yeah 'push' is really slick.

    i like that you can push or you can use a code.

    glad you got it working. and it's free :)
     
  15. thEGA

    thEGA Network Newbie Member

    Managed to get everything compiled up and running but all I ever see is
    authpriv.err openvpn(pam_google_authenticator)[2265]: Invalid verification code
    Date/time on the router are good.
     
  16. thEGA

    thEGA Network Newbie Member

    And fixed!
     
  17. lancethepants

    lancethepants Network Guru Member

    Nice, what did it?
     
  18. ilium007

    ilium007 Reformed Router Member

    Sorry - I have double posted this from over at SNB forums. I should have posted here. Apologies also for digging up an old thread.

    I would love to get some help with this. Have spent hours here tonight :(

    I have tomatoware installed and have downloaded the duo security source.

    I have compiled it on both the 1.3 version of arm-soft-mmc.tgz as well as the latest nightly. When I run the compiled baniary on the cmd line I get 'Segmentation fault' and when I try and start openvpn (stock tomato shibby version) I get 'PLUGIN_INIT: could not load plugin shared object /mmc/usr/duo/duo_openvpn.so: File not found' but you can see fro the dir listing it is definitely there !

    Any help would be appreciated.

    root@rtac68u:/mmc/usr/duo# tail -f /mnt/EXTUSB/openvpn/server1/openvpn.log
    Mon Jun 13 23:24:02 2016 us=759337 PLUGIN_INIT: could not load plugin shared object /mmc/usr/duo/duo_openvpn.so: File not found
    Mon Jun 13 23:24:02 2016 us=759676 Exiting due to fatal error
    tail: /mnt/EXTUSB/openvpn/server1/openvpn.log: file truncated
    Mon Jun 13 23:25:01 2016 us=27881 PLUGIN_INIT: could not load plugin shared object /mmc/usr/duo/duo_openvpn.so: File not found
    Mon Jun 13 23:25:01 2016 us=28225 Exiting due to fatal error
    ^C


    root@rtac68u:/mmc/usr/duo# ll /mmc/usr/duo/
    total 44
    -rw-r--r-- 1 root root 7129 Jun 13 23:23 ca_certs.pem
    -rwxr-xr-x 1 root root 12729 Jun 13 23:24 duo_openvpn.py*
    -rwxr-xr-x 1 root root 8324 Jun 13 23:23 duo_openvpn.so*
    -rwxr-xr-x 1 root root 5261 Jun 13 23:23 https_wrapper.py*


    root@rtac68u:/mmc/usr/duo# ./duo_openvpn.so
    Segmentation fault
    root@rtac68u:/mmc/usr/duo#


    I have also updated the python #! in the .py script. And I also modified duo_openvpn.c to include the missing (it wouldn't compile due to being unable to call waitpid() ):

    #include <sys/wait.h>

    This is the stock openvpn:

    root@rtac68u:/mmc/usr/duo# openvpn --version
    OpenVPN 2.3.7 arm-unknown-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [MH] [IPv6] built on Oct 8 2015
    library versions: OpenSSL 1.0.2d 9 Jul 2015, LZO 2.09
    Originally developed by James Yonan
    Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
    Compile time defines: enable_crypto=yes enable_crypto_ofb_cfb=yes enable_debug=no enable_def_auth=yes enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown enable_fast_install=yes enable_fragment=yes enable_http_proxy=yes enable_iproute2=no enable_libtool_lock=yes enable_lzo=yes enable_lzo_stub=no enable_management=yes enable_multi=yes enable_multihome=yes enable_pam_dlopen=no enable_password_save=yes enable_pedantic=no enable_pf=yes enable_pkcs11=no enable_plugin_auth_pam=no enable_plugin_down_root=no enable_plugins=yes enable_port_share=yes enable_selinux=no enable_server=yes enable_shared=yes enable_shared_with_static_runtimes=no enable_small=no enable_socks=no enable_ssl=yes enable_static=yes enable_strict=no enable_strict_options=no enable_systemd=no enable_win32_dll=yes enable_x509_alt_username=no with_crypto_library=openssl with_gnu_ld=yes with_mem_check=no with_plugindir=/lib with_sysroot=no

    Does this need to be re-compiled ?


     
    Last edited: Jun 13, 2016
  19. ilium007

    ilium007 Reformed Router Member

    @Anoop - do you have some more details on how you got this to work ? I have spent hours trying. I have compiled openvpn 2.3.11 as well as the Duo source code (after fixing the missing import in the source) and still can not get it to work.

    This is what I see when I try to connect:

    Tue Jun 14 19:51:10 2016 us=940616 1.132.96.193:61817 PLUGIN_CALL: POST /mmc/duo/duo_openvpn.so/PLUGIN_AUTH_USER_PASS_VERIFY status=2
    Tue Jun 14 19:51:10 2016 us=940876 1.132.96.193:61817 TLS: Username/Password authentication deferred for username 'ilium007'


    Duo login name matches the CN in the cert.

    This is the openvpn that I have compiled:

    root@rtac68u:/tmp/home/root# /mmc/sbin/openvpn --version
    OpenVPN 2.3.11 armv7l-unknown-linux-uclibceabi [SSL (OpenSSL)] [LZO] [EPOLL] [MH] [IPv6] built on Jun 14 2016
    library versions: OpenSSL 1.0.2g 1 Mar 2016, LZO 2.09
    Originally developed by James Yonan
    Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
    Compile time defines: enable_crypto=yes enable_crypto_ofb_cfb=yes enable_debug=yes enable_def_auth=yes enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown enable_fast_install=yes enable_fragment=yes enable_http_proxy=yes enable_iproute2=no enable_libtool_lock=yes enable_lzo=yes enable_lzo_stub=no enable_management=yes enable_multi=yes enable_multihome=yes enable_pam_dlopen=no enable_pedantic=no enable_pf=yes enable_pkcs11=no enable_plugin_auth_pam=yes enable_plugin_down_root=yes enable_plugins=yes enable_port_share=yes enable_selinux=no enable_server=yes enable_shared=yes enable_shared_with_static_runtimes=no enable_small=no enable_socks=yes enable_ssl=yes enable_static=yes enable_strict=no enable_strict_options=no enable_systemd=no enable_win32_dll=yes enable_x509_alt_username=no with_aix_soname=aix with_crypto_library=openssl with_gnu_ld=yes with_mem_check=no with_plugindir='$(libdir)/openvpn/plugins' with_sysroot=no
    root@rtac68u:/tmp/home/root#
     
    Last edited: Jun 14, 2016
  20. lancethepants

    lancethepants Network Guru Member

    @ilium007
    There a lot of steps and checks to get this working
    1. Compile OpenVPN and mount --bind it over the router's version.
    2. Compile duo. Add full path of perl/python in c source file. Modify Makefile prefix to desired destination.
    note: I don't have to add any additional includes or anything for it to compile for me.
    3. setup duo account and phone app or do sms. The name must match the cn (common name) of your OpenVPN client cert.
    4. add the plugin line custom config with your account credentials to openvpn server on the router. remember to add the auth-user-pass line as well to the client config.
     
  21. ilium007

    ilium007 Reformed Router Member

    @lancethepants I had done all of this apart from adding the python path in step 2. Are you referring to setting the full path the python script (#define DUO_SCRIPT_PATH PREFIX "/duo_openvpn.py") or the Python binary (#define INTERPRETER "python").

    Thanks !
     
  22. ilium007

    ilium007 Reformed Router Member

    That worked !! Thank you so much. It was the following line that worked:

    #define INTERPRETER "/mmc/bin/python"
     
    lancethepants likes this.

Share This Page