Role that installs OpenVPN. Supports ldap authentication.

This commit is contained in:
Andrea Dell'Amico 2020-04-28 18:40:18 +02:00
parent ee94b2a18e
commit a6d8cf04fe
18 changed files with 1022 additions and 11 deletions

View File

@ -1,23 +1,26 @@
Role Name
OpenVPN
=========
A brief description of the role goes here.
Role that installs OpenVPN
Requirements
------------
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
letsencrypt-acme-sh-client role if letsencrypt is being used (best not if you are relying on client certificates for authentication).
Role Variables
--------------
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
Important in a multihost installation are the variables:
openvpn_is_master_host: bool
openvpn_net_octet: int
That must differ from host to host. The first one must be set to *True* on one host only
Dependencies
------------
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Example Playbook
----------------
@ -30,9 +33,9 @@ Including an example of how to use your role (for instance, with variables passe
License
-------
BSD
EUPL 1.2+
Author Information
------------------
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
Andrea Dell'Amico <andrea.dellamico@isti.cnr.it>

View File

@ -1,2 +1,111 @@
---
# defaults file for ansible-role-template
openvpn_enabled: True
openvpn_enable_system_forward: True
openvpn_management_enabled: False
openvpn_management_ip: 127.0.0.1
openvpn_management_port: 1195
openvpn_management_file: '{{ openvpn_conf_dir }}/auth/management.txt'
# openvpn_management_password: 'set into a vault file'
openvpn_pkg_state: latest
openvpn_pkgs:
- openvpn
# Authentication choices
openvpn_cert_auth_enabled: True
openvpn_username_pam_auth: False
openvpn_radius_auth: False
openvpn_radius_pkg:
- openvpn-auth-radius
# With openvpn-auth-ldap. Broken on Ubuntu trusty
openvpn_ldap_auth: False
openvpn_ldap_pkg:
- openvpn-auth-ldap
openvpn_ldap_perl_auth: False
openvpn_perl_pkg:
- libnet-ldap-perl
# Server conf parameters
openvpn_conf_dir: /etc/openvpn
openvpn_conf_name: openvpn.conf
openvpn_mode: server
openvpn_dev: tun
openvpn_port: 1194
openvpn_protocol: udp
openvpn_server_net: '192.168.254.0 255.255.255.0'
#openvpn_push_routes: []
# - '192.168.253.0 255.255.255.0'
#openvpn_push_settings:
# - "dhcp-option DNS 10.66.0.4"
#openvpn_remote_servers: []
openvpn_force_ccd: False
# openvpn_users_customizations:
# - { cn: 'Joe Bar', ip: '<Client IP>', netmask: '<openvpn_server_net netmask>', routes: [ '192.168.253.0 255.255.255.0' ] }
openvpn_tls_server: True
openvpn_dh: /etc/openvpn/dh2048.pem
openvpn_tls_auth: '/etc/openvpn/ta.key'
openvpn_install_alternative_ca: False
openvpn_alternative_ca_name: ca.pem
openvpn_ca_dir: False
openvpn_ca: '/var/lib/acme/live/{{ ansible_fqdn }}/chain'
openvpn_cert: '/var/lib/acme/live/{{ ansible_fqdn }}/cert'
openvpn_key: '/var/lib/acme/live/{{ ansible_fqdn }}/privkey'
openvpn_ha: False
# Not a real master. It is only the host where the dh.pem and ta.key are generated
openvpn_master_host: 'localhost'
openvpn_is_master_host: False
openvpn_compression_enabled: False
openvpn_keepalive: '10 120'
openvpn_max_clients: 100
openvpn_run_unprivileged: True
openvpn_unprivileged_user: nobody
openvpn_unprivileged_group: nogroup
# Not recommended. Use a private CA if possible
openvpn_letsencrypt_managed: False
openvpn_verbosity_log: 3
openvpn_mute_after: 20
# LDAP conf
openvpn_ldap_uri: 'ldap:'
openvpn_ldap_host: ldap.example.org
openvpn_ldap_url: '{{ openvpn_ldap_uri }}//{{ openvpn_ldap_host }}'
openvpn_ldap_anon_bind: True
openvpn_ldap_binddn: uid=admin
openvpn_ldap_bindpwd: test
openvpn_ldap_ca: '{{ openvpn_ca }}'
openvpn_ldap_use_ca_dir: False
openvpn_ldap_ca_dir: /etc/ssl/certs
openvpn_ldap_starttls: False
openvpn_ldap_tls_auth: False
openvpn_ldap_tls_cert: '{{ openvpn_cert }}'
openvpn_ldap_tls_key: '{{ openvpn_key }}'
openvpn_ldap_tls_ciphersuite: 'ALL:!ADH:@STRENGTH'
# LDAP auth
openvpn_ldap_base_dn: 'ou=People,dc=example,dc=org'
openvpn_ldap_user_search: '(&(uid=%u))'
openvpn_ldap_require_group: False
# See https://github.com/threerings/openvpn-auth-ldap/issues/7
openvpn_ldap_without_posix_groups: True
openvpn_ldap_group_base: 'ou=Groups,dc=example,dc=org'
openvpn_ldap_group_filter: '(|(cn=developers)(cn=artists))'
openvpn_ldap_group_member_attr: uniqueMember
# Perl LDAP conf
openvpn_ldap_perl_auth_ssl: True
openvpn_ldap_perl_auth_sslport: 636
openvpn_ldap_perl_auth_group: vpn_ldap_posix_group
openvpn_nagios_checks: False
openvpn_nagios_deb_deps:
- libnet-telnet-perl

View File

@ -0,0 +1,28 @@
#!/bin/bash
H_NAME=$( hostname -f )
LE_SERVICES_SCRIPT_DIR=/usr/lib/acme/hooks
LE_CERTS_DIR=/var/lib/acme/live/$H_NAME
LE_LOG_DIR=/var/log/letsencrypt
DATE=$( date )
[ ! -d $LE_LOG_DIR ] && mkdir $LE_LOG_DIR
echo "$DATE" >> $LE_LOG_DIR/openvpn.log
if [ -f /etc/default/letsencrypt ] ; then
. /etc/default/letsencrypt
else
echo "No letsencrypt default file" >> $LE_LOG_DIR/openvpn.log
fi
echo "Reload the openvpn service" >> $LE_LOG_DIR/openvpn.log
if [ -x /bin/systemctl ] ; then
systemctl restart openvpn >> $LE_LOG_DIR/openvpn.log 2>&1
else
service openvpn restart >> $LE_LOG_DIR/openvpn.log 2>&1
fi
echo "Done." >> $LE_LOG_DIR/openvpn.log
exit 0

View File

@ -1,2 +1,13 @@
---
# handlers file for ansible-role-template
# OpenVPN does not support a service reload
- name: Reload OpenVPN
service: name=openvpn state=restarted
when: openvpn_enabled
- name: Restart OpenVPN
service: name=openvpn state=restarted
when: openvpn_enabled
- name: Reload systemd
systemd: daemon_reload=yes
when: ansible_service_mgr == 'systemd'

View File

@ -0,0 +1,14 @@
---
- name: Create the acme hooks directory if it does not yet exist
file: dest={{ letsencrypt_acme_services_scripts_dir }} state=directory owner=root group=root
when:
- openvpn_letsencrypt_managed
- letsencrypt_acme_install
tags: [ 'openvpn', 'letsencrypt' ]
- name: Install a script that fix the letsencrypt certificate for openvpn and then reload the service
copy: src=openvpn-letsencrypt-acme.sh dest={{ letsencrypt_acme_services_scripts_dir }}/openvpn owner=root group=root mode=4555
when:
- openvpn_letsencrypt_managed
- letsencrypt_acme_install
tags: [ 'openvpn', 'letsencrypt' ]

View File

@ -1,2 +1,8 @@
---
# tasks file for ansible-role-template
- import_tasks: openvpn.yml
- import_tasks: letsencrypt-openvpn.yml
when: openvpn_letsencrypt_managed | bool
- import_tasks: openvpn-nagios.yml
when:
- nagios_enabled is defined and nagios_enabled | bool
- openvpn_nagios_checks | bool

18
tasks/openvpn-nagios.yml Normal file
View File

@ -0,0 +1,18 @@
---
- name: Nagios check configuration for openvpn (NRPE required)
block:
- name: Install the nagios check deb deps
apt: pkg={{ openvpn_nagios_deb_deps }} state={{ openvpn_pkg_state }} update_cache=yes cache_valid_time=1800
- name: Install the nagios check script
template: src=check_openvpn.pl.j2 dest={{ nagios_plugins_dir }}/check_openvpn owner=root group=root mode=0755
- name: Install the nagios nrpe configuration
template: src=openvpn-nrpe.cfg.j2 dest={{ nrpe_include_dir }}/openvpn.cfg owner=root group=nagios mode=0440
notify: Reload NRPE server
when:
- openvpn_enabled | bool
- ansible_distribution_file_variety == "Debian"
tags: [ 'openvpn', 'openvpn_nagios', 'nagios' ]

209
tasks/openvpn.yml Normal file
View File

@ -0,0 +1,209 @@
---
- block:
- name: Install the OpenVPN main packages
apt: pkg={{ openvpn_pkgs }} state={{ openvpn_pkg_state }} update_cache=yes cache_valid_time=1800
- name: Create the auth, ipp, ccd and status subdirs
file: dest={{ openvpn_conf_dir }}/{{ item }} state=directory owner={{ openvpn_unprivileged_user }} group=root mode=0770
with_items:
- ipp
- status
- auth
- ccd
when: openvpn_enabled | bool
tags: openvpn
- block:
- name: Install the OpenVPN radius auth plugin package
apt: pkg={{ openvpn_radius_pkg }} state={{ openvpn_pkg_state }} update_cache=yes cache_valid_time=1800
when: openvpn_radius_auth | bool
tags: [ 'openvpn', 'openvpn_radius' ]
- block:
- name: Install the OpenVPN radius auth plugin package
template: src=management.txt.j2 dest={{ openvpn_management_file }} owner=root group=root mode=0400
when: openvpn_management_enabled | bool
tags: [ 'openvpn', 'openvpn_management' ]
- block:
- name: Install the OpenVPN ldap auth plugin package
apt: pkg={{ openvpn_ldap_pkg }} state={{ openvpn_pkg_state }} update_cache=yes cache_valid_time=1800
- name: Install the LDAP auth configuration file
template: src=auth-ldap.conf.j2 dest={{ openvpn_conf_dir }}/auth/auth-ldap.conf owner=root group={{ openvpn_unprivileged_group }} mode=0440
notify: Reload OpenVPN
when: openvpn_ldap_auth
tags: [ 'openvpn', 'openvpn_ldap', 'openvpn_basic_conf' ]
- block:
- name: Remove the LDAP auth configuration file if LDAP is not used
file: dest={{ openvpn_conf_dir }}/auth/auth-ldap.conf state=absent
notify: Reload OpenVPN
when: not openvpn_ldap_auth
tags: [ 'openvpn', 'openvpn_ldap', 'openvpn_basic_conf' ]
- block:
- name: Install the perl libraries needed by the LDAP client authentication script
apt: pkg={{ openvpn_perl_pkg }} state={{ openvpn_pkg_state }} update_cache=yes cache_valid_time=1800
- name: Install the perl LDAP auth script
template: src=auth-ldap.pl.j2 dest={{ openvpn_conf_dir }}/auth/auth-ldap owner=root group={{ openvpn_unprivileged_group }} mode=0550
when: openvpn_ldap_perl_auth
tags: [ 'openvpn', 'openvpn_ldap' ]
- block:
- name: Install the main OpenVPN configuration file on the servers
template: src=server.conf.j2 dest={{ openvpn_conf_dir }}/{{ openvpn_conf_name }} owner=root group={{ openvpn_unprivileged_group }} mode=0440
notify: Restart OpenVPN
tags: [ 'openvpn', 'openvpn_conf', 'openvpn_conf_file', 'openvpn_basic_conf' ]
- name: Install the custom configuration for specific OpenVPN users in the servers
template: src=user-ccd.conf.j2 dest={{ openvpn_conf_dir }}/ccd/{{ item.cn }} owner=root group={{ openvpn_unprivileged_group }} mode=0440
with_items: '{{ openvpn_users_customizations | default([]) }}'
tags: [ 'openvpn', 'openvpn_conf', 'openvpn_ccd' ]
- name: Install the easy-rsa package on servers when we use the certificate authentication
apt: pkg=easy-rsa state={{ openvpn_pkg_state }} update_cache=yes cache_valid_time=1800
when:
- openvpn_cert_auth_enabled | bool
- openvpn_is_master_host | bool
when: openvpn_mode == 'server'
tags: [ 'openvpn', 'openvpn_conf' ]
- block:
- name: Install the main OpenVPN configuration file on the clients
template: src=client.conf.j2 dest={{ openvpn_conf_dir }}/{{ openvpn_conf_name }} owner=root group={{ openvpn_unprivileged_group }} mode=0440
notify: Restart OpenVPN
when: openvpn_mode != 'server'
tags: [ 'openvpn', 'openvpn_conf' ]
- block:
- name: Install the OpenVPN init defaults
template: src=openvpn-defaults.j2 dest=/etc/default/openvpn owner=root group=root mode=0444
notify:
- Restart OpenVPN
- Reload systemd
tags: [ 'openvpn', 'openvpn_conf' ]
- block:
- name: Create the dh file
shell: openssl dhparam -out {{ openvpn_conf_dir }}/dh2048.pem 2048
args:
creates: '{{ openvpn_conf_dir }}/dh2048.pem'
- name: Fix the dh file permissions
file: dest={{ openvpn_conf_dir }}/dh2048.pem owner=root group=root mode=0444
- name: Create the ta key
shell: cd {{ openvpn_conf_dir }} && openvpn --genkey --secret ta.key
args:
creates: '{{ openvpn_conf_dir }}/ta.key'
- name: Fix the ta.key file permissions
file: dest={{ openvpn_conf_dir }}/ta.key owner=root group=root mode=0400
when: openvpn_is_master_host | bool or not openvpn_ha | bool
tags: [ 'openvpn', 'openvpn_conf' ]
- block:
- name: Get the dh file from the master host
synchronize:
src: '{{ openvpn_conf_dir }}/dh2048.pem'
#dest: 'rsync://root@{{ ansible_fqdn }}/{{ openvpn_conf_dir }}/dh2048.pem'
dest: '/{{ openvpn_conf_dir }}/dh2048.pem'
delegate_to: '{{ openvpn_master_host }}'
ignore_errors: True
- name: Relax the ta.key file permissions so that it can be copied around
file: dest={{ openvpn_conf_dir }}/ta.key owner=root group=root mode=0444
delegate_to: '{{ openvpn_master_host }}'
ignore_errors: True
- name: Get the ta key from the master host
synchronize:
src: '{{ openvpn_conf_dir }}/ta.key'
#dest: 'rsync://root@{{ ansible_fqdn }}/{{ openvpn_conf_dir }}/ta.key'
dest: '/{{ openvpn_conf_dir }}/ta.key'
delegate_to: '{{ openvpn_master_host }}'
ignore_errors: True
- name: Fix the ta.key file permissions
file: dest={{ openvpn_conf_dir }}/ta.key owner=root group=root mode=0400
- name: Fix the ta.key file permissions on the master host
file: dest={{ openvpn_conf_dir }}/ta.key owner=root group=root mode=0400
delegate_to: '{{ openvpn_master_host }}'
ignore_errors: True
when:
- openvpn_ha | bool
- not openvpn_is_master_host | bool
tags: [ 'openvpn', 'openvpn_conf', 'openvpn_shared_secrets' ]
- block:
- name: Get the dh file from the master host
synchronize:
src: '{{ openvpn_conf_dir }}/dh2048.pem'
#dest: 'rsync://root@{{ ansible_fqdn }}/{{ openvpn_conf_dir }}/dh2048.pem'
dest: '/{{ openvpn_conf_dir }}/dh2048.pem'
delegate_to: '{{ openvpn_master_host }}'
- name: Relax the ta.key file permissions so that it can be copied around
file: dest={{ openvpn_conf_dir }}/ta.key owner=root group=root mode=0444
delegate_to: '{{ openvpn_master_host }}'
- name: Get the ta key from the master host
synchronize:
src: '{{ openvpn_conf_dir }}/ta.key'
#dest: 'rsync://root@{{ ansible_fqdn }}/{{ openvpn_conf_dir }}/ta.key'
dest: '/{{ openvpn_conf_dir }}/ta.key'
delegate_to: '{{ openvpn_master_host }}'
ignore_errors: True
- name: Fix the ta.key file permissions
file: dest={{ openvpn_conf_dir }}/ta.key owner=root group=root mode=0400
- name: Fix the ta.key file permissions on the master host
file: dest={{ openvpn_conf_dir }}/ta.key owner=root group=root mode=0400
delegate_to: '{{ openvpn_master_host }}'
when: openvpn_mode != 'server'
tags: [ 'openvpn', 'openvpn_conf', 'openvpn_shared_secrets' ]
- block:
- name: Enable kernel forwarding
sysctl: name={{ item }} value=1 reload=yes state=present
with_items:
- net.ipv4.ip_forward
# - net.ipv6.conf.all.forwarding
when:
- openvpn_enable_system_forward | bool
- openvpn_enabled | bool
- name: Disable kernel forwarding
sysctl: name={{ item }} value=0 reload=yes state=present
with_items:
- net.ipv4.ip_forward
# - net.ipv6.conf.all.forwarding
when: not openvpn_enable_system_forward
- name: Ensure that the OpenVPN service is enabled and running
service: name=openvpn state=started enabled=yes
when: openvpn_enabled | bool
- name: Ensure that the OpenVPN service is stopped and disabled
service: name=openvpn state=stopped enabled=no
when: not openvpn_enabled | bool
tags: openvpn

View File

@ -0,0 +1,72 @@
<LDAP>
# LDAP server URL
URL {{ openvpn_ldap_url }}
{% if not openvpn_ldap_anon_bind %}
# Bind DN (If your LDAP server doesn't support anonymous binds)
BindDN "{{ openvpn_ldap_binddn }}"
# Bind Password
Password "{{ openvpn_ldap_bindpwd }}"
{% endif %}
# Network timeout (in seconds)
Timeout 15
{% if openvpn_ldap_starttls %}
# Enable Start TLS
TLSEnable yes
{% else %}
TLSEnable no
{% endif %}
{% if not openvpn_ldap_anon_bind %}
# Follow LDAP Referrals (anonymously)
FollowReferrals no
{% else %}
FollowReferrals yes
{% endif %}
# TLS CA Certificate File
TLSCACertFile {{ openvpn_ldap_ca }}
{% if openvpn_ldap_use_ca_dir %}
# TLS CA Certificate Directory
# TLSCACertDir {{ openvpn_ldap_ca_dir }}
{% endif %}
{% if openvpn_ldap_tls_auth %}
# Client Certificate and key
# If TLS client authentication is required
TLSCertFile {{ openvpn_ldap_tls_cert }}
TLSKeyFile {{ openvpn_ldap_tls_key }}
{% endif %}
# Cipher Suite
# The defaults are usually fine here
#TLSCipherSuite {{ openvpn_ldap_tls_ciphersuite }}
</LDAP>
<Authorization>
# Base DN
BaseDN "{{ openvpn_ldap_base_dn }}"
# User Search Filter
SearchFilter "{{ openvpn_ldap_user_search }}"
# Require Group Membership
RequireGroup {{ openvpn_ldap_require_group }}
{% if openvpn_ldap_require_group %}
# Add non-group members to a PF table (disabled)
#PFTable ips_vpn_users
<Group>
BaseDN "{{ openvpn_ldap_group_base }}"
SearchFilter "{{ openvpn_ldap_group_filter }}"
RFC2307bis {{ openvpn_ldap_without_posix_groups }}
MemberAttribute {{ openvpn_ldap_group_member_attr }}
# Add group members to a PF table (disabled)
# #PFTable ips_vpn_eng
</Group>
{% endif %}
</Authorization>

42
templates/auth-ldap.pl.j2 Normal file
View File

@ -0,0 +1,42 @@
#!/usr/bin/perl -w
{% if openvpn_ldap_perl_auth_ssl %}
use Net::LDAPS;
{% else %}
use Net::LDAP;
{% endif %}
use strict;
my $ldap;
my $result;
my $opt_uri = "{{ openvpn_ldap_host }}";
my $opt_user = $ENV{'username'};
my $opt_passwd = $ENV{'password'};
my $opt_group = "cn={{ openvpn_ldap_perl_auth_group }},{{ openvpn_ldap_group_base }}";
my $opt_binddn = "uid=".$opt_user.",{{ openvpn_ldap_base_dn }}";
{% if openvpn_ldap_perl_auth_ssl %}
$ldap = Net::LDAPS->new($opt_uri, version => 3,
port => '{{ openvpn_ldap_perl_auth_sslport }}',
verify => 'require',
{% if openvpn_ca_dir %}
capath => '{{ openvpn_ldap_ca }}'
{% else %}
cafile => '{{ openvpn_ldap_ca }}'
{% endif %}
) or die("LDAPS connect to $opt_uri failed!");
{% else %}
$ldap = Net::LDAP->new($opt_uri) or die("LDAP connect to $opt_uri failed!");
{% endif %}
{% if openvpn_ldap_nonanon_bind %}
$result = $ldap->bind('{{ openvpn_ldap_binddn }}', password => '{{ openvpn_ldap_bindpwd | default('') }}');
{% else %}
$result = $ldap->bind($opt_binddn, password => $opt_passwd);
{% endif %}
$result->code and die($result->error);
$result = $ldap->search(base=>$opt_group, filter => "(&({{ openvpn_ldap_group_member_attr }}=$opt_user))");
$result->code();
if ($result->count == 1) { exit 0; }
unless($result->count){ exit 1; }

View File

@ -0,0 +1,219 @@
#!/usr/bin/perl -w
#######################################################################
#
# Copyright (c) 2007 Jaime Gascon Romero <jgascon@gmail.com>
#
# License Information:
# This program 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 3 of the License, or
# (at your option) any later version.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
# $Id: check_openvpn.pl,v 1.0 2007/07/15 16:07:20 jgr Exp jgr $
# $Revision: 1.0 $
# Home Site: http://emergeworld.blogspot.com/
# #####################################################################
use diagnostics;
use strict;
use Net::Telnet ();
use Getopt::Long qw(:config no_ignore_case);
use vars qw($PROGNAME $VERSION);
{% if ansible_distribution_file_variety == "Debian" %}
use lib "/usr/lib/nagios/plugins";
{% elif ansible_distribution_file_variety == "Debian" %}
use lib "/usr/lib64/nagios/plugins";
{% endif %}
use utils qw(%ERRORS);
$PROGNAME = "check_openvpn";
$VERSION = '$Revision: 1.0 $';
$ENV{'PATH'}='';
$ENV{'BASH_ENV'}='';
$ENV{'ENV'}='';
my ($opt_h, $opt_H, $opt_p, $opt_P, $opt_t, $opt_i, $opt_n, $opt_c, $opt_w, $opt_C, $opt_r);
sub print_help ();
sub print_usage ();
GetOptions
("h" => \$opt_h, "help" => \$opt_h,
"H=s" => \$opt_H, "host=s" => \$opt_H,
"p=i" => \$opt_p, "port=i" => \$opt_p,
"P=s" => \$opt_P, "password=s" => \$opt_P,
"t=i" => \$opt_t, "timeout=i" => \$opt_t,
"i" => \$opt_i, "ip" => \$opt_i,
"n" => \$opt_n, "numeric" => \$opt_n,
"c" => \$opt_c, "critical" => \$opt_c,
"w" => \$opt_w, "warning" => \$opt_w,
"C=s" => \$opt_C, "common_name=s" => \$opt_C,
"r=s" => \$opt_r, "remote_ip=s" => \$opt_r,
) or exit $ERRORS{'UNKNOWN'};
# default values
unless ( defined $opt_t ) {
$opt_t = 10;
}
if ($opt_h) {print_help(); exit $ERRORS{'OK'};}
if ( ! defined($opt_H) || ! defined($opt_p) ) {
print_usage();
exit $ERRORS{'UNKNOWN'}
}
my @lines;
my @clients;
my @clients_ip;
my $t;
eval {
$t = new Net::Telnet (Timeout => $opt_t,
Port => $opt_p,
Prompt => '/END$/'
);
$t->open($opt_H);
if ( defined $opt_P ) {
$t->waitfor('/ENTER PASSWORD:$/');
$t->print($opt_P);
}
$t->waitfor('/^$/');
@lines = $t->cmd("status 2");
$t->close;
};
if ($@) {
print "OpenVPN Critical: Can't connect to server\n";
exit $ERRORS{'CRITICAL'};
}
if (defined $opt_i || defined $opt_r) {
foreach (@lines) {
if ($_ =~ /CLIENT_LIST,.*,(\d+\.\d+\.\d+\.\d+):\d+,/) {
push @clients_ip, $1;
}
}
if (defined $opt_i) {
print "OpenVPN OK: "."@clients_ip ";
exit $ERRORS{'OK'};
} elsif (defined $opt_r) {
if ( ! grep /\b$opt_r\b/, @clients_ip) {
if (defined $opt_c) {
print "OpenVPN CRITICAL: $opt_r don't found";
exit $ERRORS{'CRITICAL'};
} else {
print "OpenVPN WARNING: $opt_r don't found";
exit $ERRORS{'WARNING'};
}
}
print "OpenVPN OK: "."@clients_ip ";
exit $ERRORS{'OK'};
}
}
foreach (@lines) {
if ($_ =~ /CLIENT_LIST,(.*),\d+\.\d+\.\d+\.\d+:\d+,/) {
push @clients, $1;
}
}
if (defined $opt_C) {
if ( ! grep /\b$opt_C\b/, @clients) {
if (defined $opt_c) {
print "OpenVPN CRITICAL: $opt_C don't found";
exit $ERRORS{'CRITICAL'};
} else {
print "OpenVPN WARNING: $opt_C don't found";
exit $ERRORS{'WARNING'};
}
}
}
if (defined $opt_n) {
print "OpenVPN OK: ".@clients." connected clients.";
exit $ERRORS{'OK'};
}
print "OpenVPN OK: "."@clients ";
exit $ERRORS{'OK'};
#######################################################################
###### Subroutines ####################################################
sub print_usage() {
print "Usage: $PROGNAME -H | --host <IP or hostname> -p | --port <port number> [-P | --password] <password> [-t | --timeout] <timeout in seconds>
[-i | --ip] [-n | --numeric] [-C | --common_name] <common_name> [-r | --remote_ip] <remote_ip> [-c | --critical] [-w | --warning]\n\n";
print " $PROGNAME [-h | --help]\n";
}
sub print_help() {
print "$PROGNAME $VERSION\n\n";
print "Copyright (c) 2007 Jaime Gascon Romero
Nagios plugin to check the clients connected to a openvpn server.
";
print_usage();
print "
-H | --host
IP address or hostname of the openvpn server.
-p | --port
Management port interface of the openvpn server.
-P | --password
Password for the management interface of the openvpn server.
-t | --timeout
Timeout for the connection attempt. Optional, default 10 seconds.
Optional parameters
===================
-i | --ip
Prints the IP address of the remote client instead of the common name.
-n | --numeric
Prints the number of clients connected to the openvpn server.
Matching Parameters
===================
-C | --common_name
The common name, as it is specified in the client certificate, who is wanted to check.
-r | --remote_ip
The client remote ip address who is wanted to check.
-c | --critical
Exits with CRITICAL status if the client specified by the common name or the remote ip address is not connected.
-w | --warning
Exits with WARNING status if the client specified by the common name or the remote ip address is not connected.
Other Parameters
================
-h | --help
Show this help.
";
}
# vim:sts=2:sw=2:ts=2:et

32
templates/client.conf.j2 Normal file
View File

@ -0,0 +1,32 @@
client
dev {{ openvpn_dev }}
proto {{ openvpn_protocol }}
{% for srv in openvpn_remote_servers %}
remote {{ srv.host }} {{ srv.port }}
{% endfor %}
remote-random
resolv-retry infinite
nobind
{% if openvpn_run_unprivileged %}
# Downgrade privileges after initialization (non-Windows only)
user {{ openvpn_unprivileged_user }}
group {{ openvpn_unprivileged_group }}
{% endif %}
# Try to preserve some state across restarts.
persist-key
persist-tun
ca {{ openvpn_ca }}
cert {{ openvpn_cert }}
key {{ openvpn_key }}
{% if openvpn_cert_auth_enabled %}
tls-client
remote-cert-tls server
{% endif %}
tls-auth {{ openvpn_tls_auth }} 1
key-direction 1
cipher AES-256-CBC
keepalive {{ openvpn_keepalive }}
# Set log file verbosity.
verb {{ openvpn_verbosity_log }}
# Silence repeating messages
mute {{ openvpn_mute_after }}

View File

@ -0,0 +1 @@
{{ openvpn_management_password }}

View File

@ -0,0 +1,36 @@
# This is the configuration file for /etc/init.d/openvpn
#
# Start only these VPNs automatically via init script.
# Allowed values are "all", "none" or space separated list of
# names of the VPNs. If empty, "all" is assumed.
# The VPN name refers to the VPN configutation file name.
# i.e. "home" would be /etc/openvpn/home.conf
#
# If you're running systemd, changing this variable will
# require running "systemctl daemon-reload" followed by
# a restart of the openvpn service (if you removed entries
# you may have to stop those manually)
#
AUTOSTART="all"
#AUTOSTART="none"
#AUTOSTART="home office"
#
# WARNING: If you're running systemd the rest of the
# options in this file are ignored.
#
# Refresh interval (in seconds) of default status files
# located in /var/run/openvpn.$NAME.status
# Defaults to 10, 0 disables status file generation
#
#STATUSREFRESH=10
#STATUSREFRESH=0
# Optional arguments to openvpn's command line
OPTARGS=""
#
# If you need openvpn running after sendsigs, i.e.
# to let umountnfs work over the vpn, set OMIT_SENDSIGS
# to 1 and include umountnfs as Required-Stop: in openvpn's
# init.d script (remember to run insserv after that)
#
OMIT_SENDSIGS=0

View File

@ -0,0 +1,2 @@
# OpenVPN connected users
command[openvpn_users]={{ nagios_plugins_dir }}/check_openvpn -H {{ openvpn_management_ip }} -p {{ openvpn_management_port }} -P {{ openvpn_management_password }}

126
templates/openvpn.conf.j2 Normal file
View File

@ -0,0 +1,126 @@
mode {{ openvpn_mode }}
dev {{ openvpn_dev }}
port {{ openvpn_port }}
proto {{ openvpn_protocol }}
{% if openvpn_tls_server %}
tls-server
{% endif %}
dh {{ openvpn_dh }}
ca {{ openvpn_ca }}
cert {{ openvpn_cert }}
key {{ openvpn_key }}
topology subnet
server {{ openvpn_server_net }}
ifconfig-pool-persist ipp/ipp.txt
client-config-dir ccd
# EXAMPLE: Suppose the client
# having the certificate common name "Thelonious"
# also has a small subnet behind his connecting
# machine, such as 192.168.40.128/255.255.255.248.
# First, uncomment out these lines:
;client-config-dir ccd
;route 192.168.40.128 255.255.255.248
# Then create a file ccd/Thelonious with this line:
# iroute 192.168.40.128 255.255.255.248
# This will allow Thelonious' private subnet to
# access the VPN. This example will only work
# if you are routing, not bridging, i.e. you are
# using "dev tun" and "server" directives.
# EXAMPLE: Suppose you want to give
# Thelonious a fixed VPN IP address of 10.9.0.1.
# First uncomment out these lines:
;client-config-dir ccd
;route 10.9.0.0 255.255.255.252
# Then add this line to ccd/Thelonious:
# ifconfig-push 10.9.0.1 10.9.0.2
# Suppose that you want to enable different
# firewall access policies for different groups
# of clients. There are two methods:
# (1) Run multiple OpenVPN daemons, one for each
# group, and firewall the TUN/TAP interface
# for each group/daemon appropriately.
# (2) (Advanced) Create a script to dynamically
# modify the firewall in response to access
# from different clients. See man
# page for more info on learn-address script.
;learn-address ./script
{% for route in openvpn_push_routes %}
push "route {{ route }}"
{% endfor %}
{% for route in openvpn_push_routes %}
push "route {{ route }}"
{% endfor %}
{% if openvpn_push_settings is defined %}
{% for dhcp_opt in openvpn_push_settings %}
push "{{ dhcp_opt }}"
{% endfor %}
{% endif %}
tls-auth {{ openvpn_tls_auth }}
# Select a cryptographic cipher.
# This config item must be copied to
# the client config file as well.
# Note that v2.4 client/server will automatically
# negotiate AES-256-GCM in TLS mode.
# See also the ncp-cipher option in the manpage
cipher AES-256-CBC
{% if openvpn_compression_enabled %}
compress lz4-v2
push "compress lz4-v2"
{% endif %}
keepalive {{ openvpn_keepalive }}
{% if not openvpn_cert_auth_enabled %}
# Disable cert-auth
client-cert-not-required
{% endif %}
{% if openvpn_username_pam_auth %}
username-as-common-name
# PAM login
plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so login
{% endif %}
{% if openvpn_ldap_auth %}
plugin /usr/lib/openvpn/openvpn-auth-ldap.so /etc/openvpn/auth/auth-ldap.conf
{% endif %}
{% if openvpn_ldap_perl_auth %}
auth-user-pass-verify /etc/openvpn/auth/auth-ldap via-env
#script-security 3 execve
{% endif %}
max-clients {{ openvpn_max_clients }}
persist-tun
persist-key
status status/openvpn-status.log
{% if openvpn_run_unprivileged %}
user {{ openvpn_unprivileged_user }}
group {{ openvpn_unprivileged_group }}
{% endif %}
verb {{ openvpn_verbosity_log }}
mute {{ openvpn_mute_after }}
# Notify the client that when the server restarts so it
# can automatically reconnect.
explicit-exit-notify 1

79
templates/server.conf.j2 Normal file
View File

@ -0,0 +1,79 @@
mode {{ openvpn_mode }}
{% if openvpn_management_enabled %}
management {{ openvpn_management_ip }} {{ openvpn_management_port }} {{ openvpn_management_file }}
{% endif %}
dev {{ openvpn_dev }}
port {{ openvpn_port }}
proto {{ openvpn_protocol }}
topology subnet
server {{ openvpn_server_net }}
{% if openvpn_ifconfig_pool is defined %}
# Works in bridge mode only
#ifconfig-pool {{ openvpn_ifconfig_pool }}
{% endif %}
ifconfig-pool-persist ipp/ipp.txt
client-config-dir ccd
{% if openvpn_force_ccd %}
ccd-exclusive
{% endif %}
{% if openvpn_client_routes is defined %}
{% for route in openvpn_client_routes %}
route {{ route }}
{% endfor %}
{% endif %}
{% if openvpn_push_routes is defined %}
{% for route in openvpn_push_routes %}
push "route {{ route }}"
{% endfor %}
{% endif %}
{% if openvpn_push_settings is defined %}
{% for dhcp_opt in openvpn_push_settings %}
push "{{ dhcp_opt }}"
{% endfor %}
{% endif %}
cipher AES-256-CBC
{% if openvpn_compression_enabled %}
compress lz4-v2
push "compress lz4-v2"
{% endif %}
keepalive {{ openvpn_keepalive }}
{% if openvpn_cert_auth_enabled %}
tls-server
{% endif %}
tls-auth {{ openvpn_tls_auth }} 0
key-direction 0
dh {{ openvpn_dh }}
ca {{ openvpn_ca }}
cert {{ openvpn_cert }}
key {{ openvpn_key }}
{% if not openvpn_cert_auth_enabled %}
# Disable cert-auth
client-cert-not-required
{% endif %}
{% if openvpn_username_pam_auth %}
username-as-common-name
# PAM login
plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so login
{% endif %}
{% if openvpn_ldap_auth %}
plugin /usr/lib/openvpn/openvpn-auth-ldap.so /etc/openvpn/auth/auth-ldap.conf
{% endif %}
{% if openvpn_ldap_perl_auth %}
auth-user-pass-verify /etc/openvpn/auth/auth-ldap via-env
script-security 3 execve
{% endif %}
max-clients {{ openvpn_max_clients }}
persist-tun
persist-key
status status/openvpn-status.log
{% if openvpn_run_unprivileged %}
user {{ openvpn_unprivileged_user }}
group {{ openvpn_unprivileged_group }}
{% endif %}
verb {{ openvpn_verbosity_log }}
mute {{ openvpn_mute_after }}
{% if openvpn_protocol == 'udp' %}
# Notify the client that when the server restarts so it
# can automatically reconnect.
explicit-exit-notify 1
{% endif %}

View File

@ -0,0 +1,4 @@
ifconfig-push {{ item.ip }} {{ item.netmask }}
{% for net in item.routes %}
push "route {{ net }}"
{% endfor %}