Yubico Forum
https://forum.yubico.com/

[HOW-TO] - OpenVPN solution without PAM nor remote API
https://forum.yubico.com/viewtopic.php?f=3&t=868
Page 1 of 1

Author:  unicycle [ Mon Oct 08, 2012 5:54 pm ]
Post subject:  [HOW-TO] - OpenVPN solution without PAM nor remote API

Description:
This describes how to enable authentication on OpenVPN, with custom OTP's, but without PAM modules nor online API calls,
using a static file "username".txt (chmod r) and for the anti-replay attack counter "username".cnt (chmod rw).

Requirements:
OpenVPN
Auth::Yubikey_Decrypter perl module

In openvpn's server.conf I point to a perl script (named ovpn-yk-val.pl).
Your config file could have a zillion differences according to your needs, but the 3 lines about the perl is what matters here:
Code:
local 1.2.3.4
port 1194
proto udp
dev tun
#
ca   /usr/local/etc/openvpn/keys/ca.crt
cert /usr/local/etc/openvpn/keys/server.crt
key  /usr/local/etc/openvpn/keys/server.key # This file should be kept secret
dh   /usr/local/etc/openvpn/keys/dh1024.pem
#
server 10.8.0.0 255.255.255.0
#
ifconfig-pool-persist ipp.txt
#
topology subnet
push "dhcp-option DNS 99.99.99.99"
push "redirect-gateway def1 bypass-dhcp"
#
script-security 3
username-as-common-name
auth-user-pass-verify "/usr/local/etc/openvpn/ovpn-yk-val.pl" via-env
#
keepalive 10 120
comp-lzo
#
persist-key
persist-tun
status /var/log/openvpn-status.log
log-append /var/log/openvpn.log
verb 3
#
# client-to-client
# max-clients 25


and ovpn-yk-val.pl itself looks like this:
Code:
#!/usr/bin/perl -T
use strict;
use Auth::Yubikey_Decrypter;

# $ENV{"common_name"};
# $ENV{"username"};
# $ENV{"password"};

my $usr = $ENV{"username"};
$usr =~ m/^([a-zA-Z0-9]+)$/;
exit !(length($1) > 0);
my $credsfile = "/usr/local/etc/openvpn/$1.txt";
my $countfile = "/usr/local/etc/openvpn/$1.cnt";
exit !(-e $credsfile);
exit !(-e $countfile);

# get values
open (FILE1, "<", $credsfile) or die "Could not open yubikey credential file.\n";

my @line = <FILE1>;
chomp $line[0];
my @ykdata = split ":" , $line[0];
close FILE1 or die $!;

my $otp = $ENV{"password"};
$otp =~ m/^([a-zA-Z0-9]+)$/;
exit !(length($1) > 0);

# decrypt:
my ($publicID,$secretid_hex,$counter_dec,$timestamp_dec,$session_use_dec,$random_dec,$crc_dec,$crc_ok) =
      Auth::Yubikey_Decrypter::yubikey_decrypt($1,$ykdata[1]);

# prepare to check replay attacks
my $ctr32 = (($counter_dec & 0x7fff) << 8) + $session_use_dec;

open (FILE2, "+>", $countfile) or die "Could not open yubikey counter file.\n";
my $counter = do { local $/; <FILE2> };
$counter =~ m/^([0-9]+)$/;

# validate:
if ( $ykdata[0] eq $secretid_hex && $crc_ok == 1 && $ctr32 > $1 ) {
  truncate(FILE2, 0);
  print FILE2 $ctr32;
  close FILE2 or die $!;
  exit 0;
  }

close FILE2 or die $!;
exit 1;


identity:
In this example there is a "/usr/local/etc/openvpn/$1.txt" and a "/usr/local/etc/openvpn/$1.cnt".
You'll need to add the Private Identity in for example /usr/local/etc/openvpn/john.txt, such that the perl sript can validate against it.
counter:
And you need to have a 0 (zero) in the counter file, named /usr/local/etc/openvpn/john.cnt (or whatever path you changed above sample code to) - this is to detect and prevent replay attacks.

When (re)starting OpenVPN now should accept OTP's as credentials.

Author:  Tom [ Fri Jan 25, 2013 11:36 am ]
Post subject:  Re: OpenVPN solution without PAM nor remote API

Thank you for this post.

Could you please edit it following the [Guidelines] ?

I'd like to make it sticky.

Page 1 of 1 All times are UTC + 1 hour
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/