OpenVPN: Add support for 2FA / One-Time Password
Add two-factor authentication (2FA) to OpenVPN host connections with one-time passwords. The 2FA can be enabled or disabled per host connection and requires the client to download it's configuration again after 2FA has beend enabled for it. Additionally the client needs to configure an TOTP application, like "Google Authenticator" which then provides the second factor. To faciliate this every connection with enabled 2FA gets an "show qrcode" button after the "show file" button in the host connection list to show the 2FA secret and an 2FA configuration QRCode. When 2FA is enabled, the client needs to provide the second factor plus the private key password (if set) to successfully authorize. This only supports time based one-time passwords, TOTP with 30s window and 6 digits, for now but we may update this in the future. Signed-off-by: Timo Eissler <timo.eissler@ipfire.org>
This commit is contained in:
parent
dc124917e3
commit
e1e10515ec
|
@ -21,7 +21,7 @@
|
|||
SSLCertificateKeyFile /etc/httpd/server-ecdsa.key
|
||||
|
||||
Header always set X-Content-Type-Options nosniff
|
||||
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
|
||||
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
|
||||
Header always set Referrer-Policy strict-origin
|
||||
Header always set X-Frame-Options sameorigin
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
RewriteRule .* - [F]
|
||||
|
||||
Header always set X-Content-Type-Options nosniff
|
||||
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'"
|
||||
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src: 'self' data:"
|
||||
Header always set Referrer-Policy strict-origin
|
||||
Header always set X-Frame-Options sameorigin
|
||||
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/perl
|
||||
############################################################################
|
||||
# #
|
||||
# This file is part of the IPFire Firewall. #
|
||||
# #
|
||||
# IPFire is free software; you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation; either version 2 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# IPFire is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with IPFire; if not, write to the Free Software #
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
# #
|
||||
# Copyright (C) 2022 IPFire Team <info@ipfire.org>. #
|
||||
# #
|
||||
############################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use MIME::Base64;
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
|
||||
my $cn;
|
||||
my $prefix;
|
||||
my $password;
|
||||
my $otp;
|
||||
my @valid_otps;
|
||||
|
||||
#&General::log("otp-verify DEBUG: ENV:common_name: $ENV{'common_name'}");
|
||||
|
||||
# line 1: <COMMON NAME>
|
||||
# line 2: <CREDENTIALS> e.g.: SCRV1:cGFzc3dvcmQ=:ODg2MTM2
|
||||
while(<>) {
|
||||
#&General::log("otp-verify DEBUG: line: $_");
|
||||
if ($_ =~ /^(?!SCRV[[:digit:]]).+/) {
|
||||
chomp;
|
||||
$cn = $_;
|
||||
#$cn =~ s/\s*$//g;
|
||||
}
|
||||
if ($_ =~ /^SCRV[[:digit:]]:.+/) {
|
||||
($prefix, $password, $otp) = split /:/;
|
||||
$password = decode_base64($password);
|
||||
$otp = decode_base64($otp);
|
||||
}
|
||||
}
|
||||
|
||||
if ($cn == "") {
|
||||
#&General::log("otp-verify DEBUG: no credentials provided by client, setting CN from ENV.");
|
||||
$cn = $ENV{'common_name'};
|
||||
}
|
||||
|
||||
#&General::log("otp-verify DEBUG: CN: \"$cn\"\n");
|
||||
#&General::log("otp-verify DEBUG: PW: \"$password\"\n");
|
||||
#&General::log("otp-verify DEBUG: OTP: \"$otp\"\n");
|
||||
#&General::log("otp-verify DEBUG: ----\n");
|
||||
|
||||
my %confighash = ();
|
||||
if (-f "${General::swroot}/ovpn/ovpnconfig") {
|
||||
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
|
||||
foreach my $key (keys %confighash){
|
||||
if ($cn eq $confighash{$key}[2]) {
|
||||
# Exit successfully for non-roadwarrior connections.
|
||||
exit 0 unless ($confighash{$key}[3] eq "host");
|
||||
|
||||
# Exit successfully for disabled otp connections.
|
||||
exit 0 unless (defined $confighash{$key}[43] and $confighash{$key}[43] eq "on");
|
||||
|
||||
# Exit with failure if required otp config is missing.
|
||||
exit 1 if (not defined $confighash{$key}[42]);
|
||||
exit 1 if (not defined $confighash{$key}[44]);
|
||||
|
||||
#&General::log("otp-verify DEBUG: connection key: $key\n");
|
||||
#&General::log("otp-verify DEBUG: connection type: $confighash{$key}[3]\n");
|
||||
#&General::log("otp-verify DEBUG: CN: $confighash{$key}[2]\n");
|
||||
#&General::log("otp-verify DEBUG: otp Type: $confighash{$key}[42]\n");
|
||||
#&General::log("otp-verify DEBUG: otp State: $confighash{$key}[43]\n");
|
||||
#&General::log("otp-verify DEBUG: otp Secret: $confighash{$key}[44]\n");
|
||||
|
||||
# Get valid OTPs.
|
||||
my @valid_otps = &General::system_output("/usr/bin/oathtool", "--totp", "-w", "3", "$confighash{$key}[44]");
|
||||
foreach (@valid_otps) {
|
||||
# Exit successfully if OTP is correct.
|
||||
exit 0 if ($otp == $_)
|
||||
}
|
||||
|
||||
# Exit with failure if no matching OTP was found.
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Return an error if ovpnconfig could not be found.
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# Exit successfully if no auth-user-pass data received.
|
||||
exit 0;
|
||||
|
||||
# vim: ts=3 sts=3 sw=3 et nu list
|
|
@ -38,8 +38,8 @@ require "${General::swroot}/countries.pl";
|
|||
require "${General::swroot}/location-functions.pl";
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
#use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
use warnings;
|
||||
use CGI::Carp 'fatalsToBrowser';
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::colourgreen}, ${Header::colourblue} );
|
||||
undef (@dummy);
|
||||
|
@ -372,6 +372,9 @@ sub writeserverconf {
|
|||
}
|
||||
print CONF "tls-verify /usr/lib/openvpn/verify\n";
|
||||
print CONF "crl-verify /var/ipfire/ovpn/crls/cacrl.pem\n";
|
||||
print CONF "auth-user-pass-verify \"/usr/lib/openvpn/otp-verify\" via-file\n";
|
||||
print CONF "auth-user-pass-optional\n";
|
||||
print CONF "reneg-sec 86400\n";
|
||||
print CONF "user nobody\n";
|
||||
print CONF "group nobody\n";
|
||||
print CONF "persist-key\n";
|
||||
|
@ -2430,6 +2433,17 @@ else
|
|||
if ($vpnsettings{FRAGMENT} ne '' && $vpnsettings{DPROTOCOL} ne 'tcp' ) {
|
||||
print CLIENTCONF "fragment $vpnsettings{'FRAGMENT'}\r\n";
|
||||
}
|
||||
if ($confighash{$cgiparams{'KEY'}}[43] eq 'on') {
|
||||
print CLIENTCONF "auth-nocache\r\n";
|
||||
print CLIENTCONF "auth-user-pass credentials\r\n";
|
||||
print CLIENTCONF "static-challenge \"One Time Password (OTP): \" 1\r\n";
|
||||
|
||||
open(CLIENTCREDS, ">$tempdir/credentials") or die "Unable to open tempfile: $!";
|
||||
print CLIENTCREDS "user\r\n";
|
||||
print CLIENTCREDS "password";
|
||||
close(CLIENTCREDS);
|
||||
$zip->addFile( "$tempdir/credentials", "credentials") or die "Can't add file credentials\n";
|
||||
}
|
||||
|
||||
if ($include_certs) {
|
||||
print CLIENTCONF "\r\n";
|
||||
|
@ -2617,6 +2631,48 @@ else
|
|||
exit(0);
|
||||
}
|
||||
|
||||
###
|
||||
### Display OTP QRCode
|
||||
###
|
||||
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'show otp qrcode'}) {
|
||||
&General::readhasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
|
||||
|
||||
use MIME::Base32;
|
||||
use MIME::Base64;
|
||||
use Imager::QRCode;
|
||||
my $qrcode = Imager::QRCode->new(
|
||||
size => 6,
|
||||
margin => 0,
|
||||
version => 0,
|
||||
level => 'M',
|
||||
mode => '8-bit',
|
||||
casesensitive => 1,
|
||||
lightcolor => Imager::Color->new(255, 255, 255),
|
||||
darkcolor => Imager::Color->new(0, 0, 0),
|
||||
);
|
||||
my $cn = $confighash{$cgiparams{'KEY'}}[2];
|
||||
my $secret = encode_base32($confighash{$cgiparams{'KEY'}}[44]);
|
||||
my $issuer = "$mainsettings{'HOSTNAME'}.$mainsettings{'DOMAINNAME'}";
|
||||
my $qrcodeimg = $qrcode->plot("otpauth://totp/$cn?secret=$secret&issuer=$issuer");
|
||||
my $qrcodeimgdata;
|
||||
$qrcodeimg->write(data => \$qrcodeimgdata, type=> 'png')
|
||||
or die $qrcodeimg->errstr;
|
||||
$qrcodeimgdata = encode_base64($qrcodeimgdata, '');
|
||||
|
||||
&Header::showhttpheaders();
|
||||
&Header::openpage($Lang::tr{'ovpn'}, 1, '');
|
||||
&Header::openbigbox('100%', 'LEFT', '', '');
|
||||
&Header::openbox('100%', 'LEFT', "$Lang::tr{'otp qrcode'}:");
|
||||
print <<END;
|
||||
$Lang::tr{'secret'}: $secret</br></br>
|
||||
<img alt="$Lang::tr{'otp qrcode'}" src="data:image/png;base64,$qrcodeimgdata">
|
||||
END
|
||||
&Header::closebox();
|
||||
print "<div align='center'><a href='/cgi-bin/ovpnmain.cgi'>$Lang::tr{'back'}</a></div>";
|
||||
&Header::closebigbox();
|
||||
&Header::closepage();
|
||||
exit(0);
|
||||
|
||||
###
|
||||
### Display Diffie-Hellman key
|
||||
###
|
||||
|
@ -3660,6 +3716,7 @@ if ($confighash{$cgiparams{'KEY'}}) {
|
|||
$cgiparams{'DAUTH'} = $confighash{$cgiparams{'KEY'}}[39];
|
||||
$cgiparams{'DCIPHER'} = $confighash{$cgiparams{'KEY'}}[40];
|
||||
$cgiparams{'TLSAUTH'} = $confighash{$cgiparams{'KEY'}}[41];
|
||||
$cgiparams{'OTP_STATE'} = $confighash{$cgiparams{'KEY'}}[43];
|
||||
} elsif ($cgiparams{'ACTION'} eq $Lang::tr{'save'}) {
|
||||
$cgiparams{'REMARK'} = &Header::cleanhtml($cgiparams{'REMARK'});
|
||||
|
||||
|
@ -4422,6 +4479,15 @@ if ($cgiparams{'TYPE'} eq 'net') {
|
|||
$confighash{$key}[41] = "no-pass";
|
||||
}
|
||||
|
||||
$confighash{$key}[42] = 'HOTP/T30/6';
|
||||
$confighash{$key}[43] = $cgiparams{'OTP_STATE'};
|
||||
if (($confighash{$key}[43] == 'on') && ($confighash{$key}[44] == '')) {
|
||||
my @otp_secret = &General::system_output("/usr/bin/openssl", "rand", "-hex", "20");
|
||||
$confighash{$key}[44] = $otp_secret[0];
|
||||
} elsif ($confighash{$key}[43] == '') {
|
||||
$confighash{$key}[44] = '';
|
||||
}
|
||||
|
||||
&General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash);
|
||||
|
||||
if ($cgiparams{'CHECK1'} ){
|
||||
|
@ -4835,6 +4901,7 @@ if ($cgiparams{'TYPE'} eq 'host') {
|
|||
print"</td></tr></table><br><br>";
|
||||
my $name=$cgiparams{'CHECK1'};
|
||||
$checked{'RG'}{$cgiparams{'RG'}} = 'CHECKED';
|
||||
$checked{'OTP_STATE'}{$cgiparams{'OTP_STATE'}} = 'CHECKED';
|
||||
|
||||
if (! -z "${General::swroot}/ovpn/ccd.conf"){
|
||||
print"<table border='0' width='100%' cellspacing='1' cellpadding='0'><tr><td width='1%'></td><td width='30%' class='boldbase' align='center'><b>$Lang::tr{'ccd name'}</td><td width='15%' class='boldbase' align='center'><b>$Lang::tr{'network'}</td><td class='boldbase' align='center' width='18%'><b>$Lang::tr{'ccd clientip'}</td></tr>";
|
||||
|
@ -4970,6 +5037,7 @@ if ($cgiparams{'TYPE'} eq 'host') {
|
|||
|
||||
print <<END;
|
||||
<table border='0' width='100%'>
|
||||
<tr><td width='20%'>$Lang::tr{'enable otp'}:</td><td colspan='3'><input type='checkbox' name='OTP_STATE' $checked{'OTP_STATE'}{'on'} /></td></tr>
|
||||
<tr><td width='20%'>Redirect Gateway:</td><td colspan='3'><input type='checkbox' name='RG' $checked{'RG'}{'on'} /></td></tr>
|
||||
<tr><td colspan='4'><b><br>$Lang::tr{'ccd routes'}</b></td></tr>
|
||||
<tr><td colspan='4'> </td></tr>
|
||||
|
@ -5413,7 +5481,7 @@ END
|
|||
<th width='15%' class='boldbase' align='center'><b>$Lang::tr{'type'}</b></th>
|
||||
<th width='20%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b></th>
|
||||
<th width='10%' class='boldbase' align='center'><b>$Lang::tr{'status'}</b></th>
|
||||
<th width='5%' class='boldbase' colspan='7' align='center'><b>$Lang::tr{'action'}</b></th>
|
||||
<th width='5%' class='boldbase' colspan='8' align='center'><b>$Lang::tr{'action'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
}
|
||||
|
@ -5427,7 +5495,7 @@ END
|
|||
<th width='15%' class='boldbase' align='center'><b>$Lang::tr{'type'}</b></th>
|
||||
<th width='20%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b></th>
|
||||
<th width='10%' class='boldbase' align='center'><b>$Lang::tr{'status'}</b></th>
|
||||
<th width='5%' class='boldbase' colspan='7' align='center'><b>$Lang::tr{'action'}</b></th>
|
||||
<th width='5%' class='boldbase' colspan='8' align='center'><b>$Lang::tr{'action'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
}
|
||||
|
@ -5560,6 +5628,19 @@ END
|
|||
; } else {
|
||||
print "<td> </td>";
|
||||
}
|
||||
|
||||
if ($confighash{$key}[43] eq 'on') {
|
||||
print <<END;
|
||||
<form method='post' name='frm${key}o'><td align='center' $col>
|
||||
<input type='image' name='$Lang::tr{'show otp qrcode'}' src='/images/qr-code.png' alt='$Lang::tr{'show otp qrcode'}' title='$Lang::tr{'show otp qrcode'}' border='0' />
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'show otp qrcode'}' />
|
||||
<input type='hidden' name='KEY' value='$key' />
|
||||
</td></form>
|
||||
END
|
||||
; } else {
|
||||
print "<td $col> </td>";
|
||||
}
|
||||
|
||||
if ($confighash{$key}[4] eq 'cert' && -f "${General::swroot}/ovpn/certs/$confighash{$key}[1].p12") {
|
||||
print <<END;
|
||||
<form method='post' name='frm${key}c'><td align='center' $col>
|
||||
|
@ -5628,6 +5709,8 @@ END
|
|||
<td class='base'>$Lang::tr{'download certificate'}</td>
|
||||
<td> <img src='/images/openvpn.png' alt='?RELOAD'/></td>
|
||||
<td class='base'>$Lang::tr{'dl client arch'}</td>
|
||||
<td> <img src='/images/qr-code.png' alt='$Lang::tr{'show otp qrcode'}'/></td>
|
||||
<td class='base'>$Lang::tr{'show otp qrcode'}</td>
|
||||
</tr>
|
||||
</table><br>
|
||||
END
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 760 B |
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<path d="M0,0v233.739h233.739V0H0z M200.348,200.348H33.391V33.391h166.957V200.348z"/>
|
||||
<rect x="66.783" y="66.783" width="100.174" height="100.174"/>
|
||||
<path d="M278.261,0v233.739H512V0H278.261z M478.609,200.348H311.652V33.391h166.957V200.348z"/>
|
||||
<rect x="345.043" y="66.783" width="100.174" height="100.174"/>
|
||||
<path d="M0,278.261V512h233.739V278.261H0z M200.348,478.609H33.391V311.652h166.957V478.609z"/>
|
||||
<rect x="66.783" y="345.043" width="100.174" height="100.174"/>
|
||||
<polygon points="278.261,278.261 278.261,512 345.043,512 345.043,478.609 311.652,478.609 311.652,411.826 345.043,411.826
|
||||
345.043,378.435 311.652,378.435 311.652,311.652 345.043,311.652 345.043,278.261 "/>
|
||||
<rect x="478.609" y="278.261" width="33.391" height="33.391"/>
|
||||
<polygon points="478.609,478.609 445.217,478.609 445.217,512 512,512 512,356.174 478.609,356.174 "/>
|
||||
<rect x="378.435" y="278.261" width="66.783" height="33.391"/>
|
||||
<polygon points="445.217,411.826 411.826,411.826 411.826,378.435 445.217,378.435 445.217,345.043 378.435,345.043
|
||||
378.435,445.217 445.217,445.217 "/>
|
||||
<rect x="378.435" y="478.609" width="33.391" height="33.391"/>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -979,6 +979,7 @@
|
|||
'empty profile' => 'Unbenannt',
|
||||
'enable ignore filter' => '"Ignorieren"-Filter ein',
|
||||
'enable javascript' => 'Javascript aktivieren',
|
||||
'enable otp' => 'Aktiviere OTP',
|
||||
'enable smt' => 'Simultaneous Multi-Threading (SMT) einschalten',
|
||||
'enable wildcards' => 'Wildcards erlauben:',
|
||||
'enabled' => 'Aktiviert:',
|
||||
|
@ -1903,6 +1904,7 @@
|
|||
'other login script' => 'Anderes Anmeldeskript',
|
||||
'otherip' => 'Andere IP',
|
||||
'otherport' => 'Anderer Port',
|
||||
'otp qrcode' => 'OTP QRCode',
|
||||
'our donors' => 'Unsere Unterstützer',
|
||||
'out' => 'Aus',
|
||||
'outgoing' => 'ausgehend',
|
||||
|
@ -2201,6 +2203,7 @@
|
|||
'secondary ntp server' => 'Sekundärer NTP-Server',
|
||||
'secondary wins server address' => 'Sekundärer WINS-Server',
|
||||
'seconds' => 'Sek.',
|
||||
'secret' => 'Geheimnis',
|
||||
'section' => 'Abschnitt',
|
||||
'secure shell server' => 'Secure Shell Server',
|
||||
'security' => 'Sicherheit',
|
||||
|
@ -2244,6 +2247,7 @@
|
|||
'show last x lines' => 'die letzten x Zeilen anzeigen',
|
||||
'show root certificate' => 'Root-Zertifikat anzeigen',
|
||||
'show share options' => 'Anzeige der Freigabeeinstellungen',
|
||||
'show otp qrcode' => 'Zeige OTP QRCode',
|
||||
'shuffle' => 'Zufall',
|
||||
'shutdown' => 'Herunterfahren',
|
||||
'shutdown ask' => 'Herunterfahren?',
|
||||
|
|
|
@ -1018,6 +1018,7 @@
|
|||
'empty' => 'This field may be left blank',
|
||||
'empty profile' => 'empty',
|
||||
'enable' => 'Enable',
|
||||
'enable otp' => 'Enable OTP',
|
||||
'enable ignore filter' => 'Enable ignore filter',
|
||||
'enable javascript' => 'Enable javascript',
|
||||
'enable smt' => 'Enable Simultaneous Multi-Threading (SMT)',
|
||||
|
@ -1955,6 +1956,7 @@
|
|||
'other login script' => 'Other login script',
|
||||
'otherip' => 'other IP',
|
||||
'otherport' => 'other Port',
|
||||
'otp qrcode' => 'OTP QRCode',
|
||||
'our donors' => 'Our donors',
|
||||
'out' => 'Out',
|
||||
'outgoing' => 'outgoing',
|
||||
|
@ -2253,6 +2255,7 @@
|
|||
'secondary ntp server' => 'Secondary NTP server',
|
||||
'secondary wins server address' => 'Secondary WINS server address',
|
||||
'seconds' => 'Secs',
|
||||
'secret' => 'Secret',
|
||||
'section' => 'Section',
|
||||
'secure shell server' => 'Secure Shell Server',
|
||||
'security' => 'Security',
|
||||
|
@ -2297,6 +2300,7 @@
|
|||
'show host certificate' => 'Show host certificate',
|
||||
'show last x lines' => 'Show last x lines',
|
||||
'show lines' => 'Show lines',
|
||||
'show otp qrcode' => 'Show OTP QRCode',
|
||||
'show root certificate' => 'Show root certificate',
|
||||
'show share options' => 'Show shares options',
|
||||
'show tls-auth key' => 'Show tls-auth key',
|
||||
|
|
|
@ -96,6 +96,9 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
|||
mv -v /var/ipfire/ovpn/verify /usr/lib/openvpn/verify
|
||||
chown root:root /usr/lib/openvpn/verify
|
||||
chmod 755 /usr/lib/openvpn/verify
|
||||
mv -v /var/ipfire/ovpn/otp-verify /usr/lib/openvpn/otp-verify
|
||||
chown root:root /usr/lib/openvpn/otp-verify
|
||||
chmod 755 /usr/lib/openvpn/otp-verify
|
||||
# Add crl updater
|
||||
mv -v /var/ipfire/ovpn/openvpn-crl-updater /etc/fcron.daily
|
||||
chown root:root /etc/fcron.daily/openvpn-crl-updater
|
||||
|
|
Loading…
Reference in New Issue