diff --git a/tests/Makefile.am b/tests/Makefile.am index 33559e58..d900b6d4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -21,7 +21,7 @@ dist_check_SCRIPTS = test-iroute test-pass-script \ radius-test test-gssapi kerberos-test pam-test test-ban \ test-cookie-invalidation radius-test-config proxyproto-test \ proxyproto-unix-test pam-noauth-test otp-test test-user-config \ - test-cookie-rotation + test-cookie-rotation firewall-test if HAVE_CWRAP dist_check_SCRIPTS += test-pass test-pass-cert test-cert test-group-pass \ diff --git a/tests/docker-common.sh b/tests/docker-common.sh index 372a9bbd..b2a04988 100755 --- a/tests/docker-common.sh +++ b/tests/docker-common.sh @@ -131,8 +131,8 @@ if test ! -f $DOCKER_DIR/Dockerfile;then exit 77 fi -rm -f $DOCKER_DIR/ocserv $DOCKER_DIR/ocpasswd $DOCKER_DIR/occtl -cp ../src/ocserv ../src/ocpasswd/ocpasswd ../src/occtl/occtl $DOCKER_DIR/ +rm -f $DOCKER_DIR/ocserv $DOCKER_DIR/ocpasswd $DOCKER_DIR/occtl $DOCKER_DIR/ocserv-fw +cp ../src/ocserv ../src/ocserv-fw ../src/ocpasswd/ocpasswd ../src/occtl/occtl $DOCKER_DIR/ echo "Creating image $IMAGE" $DOCKER build -t $IMAGE $DOCKER_DIR/ diff --git a/tests/docker-ocserv/Dockerfile-fedora-fw b/tests/docker-ocserv/Dockerfile-fedora-fw new file mode 100644 index 00000000..08692c00 --- /dev/null +++ b/tests/docker-ocserv/Dockerfile-fedora-fw @@ -0,0 +1,32 @@ +FROM fedora:23 + +RUN yum install -y gnutls gnutls-utils protobuf-c iproute pcllib http-parser tcp_wrappers pam systemd libseccomp +RUN yum install -y bash openssh-server nuttcp net-tools +RUN yum install -y libnl3 libtalloc +RUN yum install -y freeradius-client +RUN yum install -y lz4 radcli liboauth oathtool procps-ng iputils +RUN yum install -y krb5-libs less +RUN systemctl enable sshd +RUN sed 's/PermitRootLogin without-password/PermitRootLogin yes/g' -i /etc/ssh/sshd_config + +RUN echo 'root:root' |chpasswd +RUN useradd -m -d /home/admin -s /bin/bash admin +RUN echo 'admin:admin' |chpasswd + +RUN mkdir /etc/ocserv + + +ADD key.pem /etc/ocserv/ +ADD cert.pem /etc/ocserv/ +ADD ocserv-fw.conf /etc/ocserv/ocserv.conf +ADD passwd /etc/ocserv/ +ADD ocserv /usr/sbin/ +ADD ocpasswd /usr/bin/ +ADD occtl /usr/bin/ +ADD ocserv-fw /usr/bin/ +ADD fw-script /usr/bin/ +# It's not possible to use mknod inside a container with the default LXC +# template, so we untar it from this archive. +ADD dev-tun.tgz /dev/ + +CMD nuttcp -S;sshd-keygen;/usr/sbin/sshd;mkdir -p /tmp/disconnect/;usr/sbin/ocserv -d 1 -f;sleep 3600 diff --git a/tests/docker-ocserv/fw-script b/tests/docker-ocserv/fw-script new file mode 100755 index 00000000..e1e814a6 --- /dev/null +++ b/tests/docker-ocserv/fw-script @@ -0,0 +1,31 @@ +#!/bin/sh + +if [ "$REASON" = "connect" ];then + iptables -S|grep ocserv-fw|grep 10.48.59.1|grep ACCEPT|grep 53 + if test $? != 0;then + echo "dns was not accepted" + exit 1 + fi + + iptables -S|grep ocserv-fw|grep 10.47.59.0/24|grep ACCEPT + if test $? != 0;then + echo "route was not accepted" + exit 1 + fi + + iptables -S|grep ocserv-fw|grep 10.46.59.0/24|grep DROP + if test $? != 0;then + echo "route was not dropped" + exit 1 + fi + + ip6tables -S|grep ocserv-fw|grep "fd91:6d87:7441:dc6a::/64"|grep ACCEPT + if test $? != 0;then + echo "route6 was not accepted" + exit 1 + fi + + touch /tmp/follow-up-script-was-run +fi + +exit 0 diff --git a/tests/docker-ocserv/ocserv-fw.conf b/tests/docker-ocserv/ocserv-fw.conf new file mode 100644 index 00000000..448ebd8a --- /dev/null +++ b/tests/docker-ocserv/ocserv-fw.conf @@ -0,0 +1,307 @@ +# User authentication method. Could be set multiple times and in that case +# all should succeed. +# Options: certificate, pam. +#auth = "certificate" +auth = "plain[/etc/ocserv/passwd]" +#auth = "pam" + +# Whether to enable support for the occtl tool (i.e., either through D-BUS, +# or via a unix socket). +use-occtl = true + +# socket file used for IPC with occtl. You only need to set that, +# if you use more than a single servers. +#occtl-socket-file = /var/run/occtl.socket + +# The plain option requires specifying a password file which contains +# entries of the following format. +# "username:groupname:encoded-password" +# One entry must be listed per line, and 'ocpasswd' can be used +# to generate password entries. +#auth = "plain[/etc/ocserv/ocpasswd]" + +# A banner to be displayed on clients +#banner = "Welcome" + +# Use listen-host to limit to specific IPs or to the IPs of a provided +# hostname. +#listen-host = [IP|HOSTNAME] + +# Limit the number of clients. Unset or set to zero for unlimited. +#max-clients = 1024 +max-clients = 16 + +# Limit the number of client connections to one every X milliseconds +# (X is the provided value). Set to zero for no limit. +#rate-limit-ms = 100 + +# Limit the number of identical clients (i.e., users connecting +# multiple times). Unset or set to zero for unlimited. +max-same-clients = 2 + +# TCP and UDP port number +tcp-port = 443 +udp-port = 443 + +# Keepalive in seconds +keepalive = 32400 + +# Dead peer detection in seconds. +dpd = 240 + +# Dead peer detection for mobile clients. The needs to +# be much higher to prevent such clients being awaken too +# often by the DPD messages, and save battery. +# (clients that send the X-AnyConnect-Identifier-DeviceType) +mobile-dpd = 1800 + +# MTU discovery (DPD must be enabled) +try-mtu-discovery = false + +# The key and the certificates of the server +# The key may be a file, or any URL supported by GnuTLS (e.g., +# tpmkey:uuid=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx;storage=user +# or pkcs11:object=my-vpn-key;object-type=private) +# +# There may be multiple certificate and key pairs and each key +# should correspond to the preceding certificate. +server-cert = /etc/ocserv/cert.pem +server-key = /etc/ocserv/key.pem + +# Diffie-Hellman parameters. Only needed if you require support +# for the DHE ciphersuites (by default this server supports ECDHE). +# Can be generated using: +# certtool --generate-dh-params --outfile /path/to/dh.pem +#dh-params = /path/to/dh.pem + +# If you have a certificate from a CA that provides an OCSP +# service you may provide a fresh OCSP status response within +# the TLS handshake. That will prevent the client from connecting +# independently on the OCSP server. +# You can update this response periodically using: +# ocsptool --ask --load-cert=your_cert --load-issuer=your_ca --outfile response +# Make sure that you replace the following file in an atomic way. +#ocsp-response = /path/to/ocsp.der + +# In case PKCS #11 or TPM keys are used the PINs should be available +# in files. The srk-pin-file is applicable to TPM keys only, and is the +# storage root key. +#pin-file = /path/to/pin.txt +#srk-pin-file = /path/to/srkpin.txt + +# The Certificate Authority that will be used to verify +# client certificates (public keys) if certificate authentication +# is set. +#ca-cert = /path/to/ca.pem + +# The object identifier that will be used to read the user ID in the client +# certificate. The object identifier should be part of the certificate's DN +# Useful OIDs are: +# CN = 2.5.4.3, UID = 0.9.2342.19200300.100.1.1 +#cert-user-oid = 0.9.2342.19200300.100.1.1 + +# The object identifier that will be used to read the user group in the +# client certificate. The object identifier should be part of the certificate's +# DN. Useful OIDs are: +# OU (organizational unit) = 2.5.4.11 +#cert-group-oid = 2.5.4.11 + +# The revocation list of the certificates issued by the 'ca-cert' above. +#crl = /path/to/crl.pem + +# GnuTLS priority string +tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT" + +# To enforce perfect forward secrecy (PFS) on the main channel. +#tls-priorities = "NORMAL:%SERVER_PRECEDENCE:%COMPAT:-RSA" + +# The time (in seconds) that a client is allowed to stay connected prior +# to authentication +auth-timeout = 40 + +# The time (in seconds) that a client is allowed to stay idle (no traffic) +# before being disconnected. Unset to disable. +#idle-timeout = 1200 + +# The time (in seconds) that a mobile client is allowed to stay idle (no +# traffic) before being disconnected. Unset to disable. +#mobile-idle-timeout = 2400 + +# The time (in seconds) that a client is not allowed to reconnect after +# a failed authentication attempt. +#min-reauth-time = 2 + +#max-ban-score = 50 + +# Cookie validity time (in seconds) +# Once a client is authenticated he's provided a cookie with +# which he can reconnect. This option sets the maximum lifetime +# of that cookie. +cookie-validity = 86400 + +# ReKey time (in seconds) +# ocserv will ask the client to refresh keys periodically once +# this amount of seconds is elapsed. Set to zero to disable. +rekey-time = 172800 + +# ReKey method +# Valid options: ssl, new-tunnel +# ssl: Will perform an efficient rehandshake on the channel allowing +# a seamless connection during rekey. +# new-tunnel: Will instruct the client to discard and re-establish the channel. +# Use this option only if the connecting clients have issues with the ssl +# option. +rekey-method = ssl + +# Script to call when a client connects and obtains an IP +# Parameters are passed on the environment. +# REASON, USERNAME, GROUPNAME, HOSTNAME (the hostname selected by client), +# DEVICE, IP_REAL (the real IP of the client), IP_LOCAL (the local IP +# in the P-t-P connection), IP_REMOTE (the VPN IP of the client), +# ID (a unique numeric ID); REASON may be "connect" or "disconnect". +connect-script = /usr/bin/fw-script +#disconnect-script = /usr/bin/fw-script + +# UTMP +use-utmp = true + +# D-BUS usage. If disabled occtl tool cannot be used. If enabled +# then ocserv must have access to register org.infradead.ocserv +# D-BUS service. See doc/dbus/org.infradead.ocserv.conf +use-dbus = false + +# PID file. It can be overriden in the command line. +pid-file = /var/run/ocserv.pid + +# The default server directory. Does not require any devices present. +#chroot-dir = /path/to/chroot + +# socket file used for IPC, will be appended with .PID +# It must be accessible within the chroot environment (if any) +socket-file = /var/run/ocserv-socket + +# The user the worker processes will be run as. It should be +# unique (no other services run as this user). +run-as-user = nobody +run-as-group = daemon + +# Set the protocol-defined priority (SO_PRIORITY) for packets to +# be sent. That is a number from 0 to 6 with 0 being the lowest +# priority. Alternatively this can be used to set the IP Type- +# Of-Service, by setting it to a hexadecimal number (e.g., 0x20). +# This can be set per user/group or globally. +#net-priority = 3 + +# Set the VPN worker process into a specific cgroup. This is Linux +# specific and can be set per user/group or globally. +#cgroup = "cpuset,cpu:test" + +# +# Network settings +# + +# The name of the tun device +device = vpns + +# The default domain to be advertised +default-domain = example.com + +# The pool of addresses that leases will be given from. +ipv4-network = 192.168.84.0 +ipv4-netmask = 255.255.255.0 + +# The advertized DNS server. Use multiple lines for +# multiple servers. +# dns = fc00::4be0 +dns = 10.48.59.1 + +# The NBNS server (if any) +#nbns = 192.168.1.3 + +# The IPv6 subnet that leases will be given from. +ipv6-network = fd91:6d87:7441:dc6a::/64 + +# The domains over which the provided DNS should be used. Use +# multiple lines for multiple domains. +#split-dns = example.com + +# Prior to leasing any IP from the pool ping it to verify that +# it is not in use by another (unrelated to this server) host. +ping-leases = false + +# Unset to assign the default MTU of the device +# mtu = + +# Unset to enable bandwidth restrictions (in bytes/sec). The +# setting here is global, but can also be set per user or per group. +#rx-data-per-sec = 40000 +#tx-data-per-sec = 40000 + +# The number of packets (of MTU size) that are available in +# the output buffer. The default is low to improve latency. +# Setting it higher will improve throughput. +#output-buffer = 10 + +# Routes to be forwarded to the client. If you need the +# client to forward routes to the server, you may use the +# config-per-user/group or even connect and disconnect scripts. +# +# To set the server as the default gateway for the client just +# comment out all routes from the server. +route = 192.168.84.0/24 +route = 10.47.59.0/24 +#route = 192.168.5.0/255.255.255.0 +route = fd91:6d87:7441:dc6a::/64 + +no-route = 10.46.59.0/24 + +restrict-user-to-routes = true + +# Configuration files that will be applied per user connection or +# per group. Each file name on these directories must match the username +# or the groupname. +# The options allowed in the configuration files are dns, nbns, +# ipv?-network, ipv4-netmask, ipv6-prefix, rx/tx-per-sec, iroute, route, +# net-priority and cgroup. +# +# Note that the 'iroute' option allows to add routes on the server +# based on a user or group. The syntax depends on the input accepted +# by the commands route-add-cmd and route-del-cmd (see below). + +#config-per-user = /etc/ocserv/config-per-user/ +#config-per-group = /etc/ocserv/config-per-group/ + +# The system command to use to setup a route. %R will be replaced with the +# route/mask and %D with the (tun) device. +# +# The following example is from linux systems. %R should be something +# like 192.168.2.0/24 + +#route-add-cmd = "ip route add %R dev %D" +#route-del-cmd = "ip route delete %R dev %D" + +# +# The following options are for (experimental) AnyConnect client +# compatibility. + +# Client profile xml. A sample file exists in doc/profile.xml. +# This file must be accessible from inside the worker's chroot. +# It is not used by the openconnect client. +#user-profile = profile.xml + +# Binary files that may be downloaded by the CISCO client. Must +# be within any chroot environment. +#binary-files = /path/to/binaries + +# Unless set to false it is required for clients to present their +# certificate even if they are authenticating via a previously granted +# cookie and complete their authentication in the same TCP connection. +# Legacy CISCO clients do not do that, and thus this option should be +# set for them. +#cisco-client-compat = false + +#Advanced options + +# Option to allow sending arbitrary custom headers to the client after +# authentication and prior to VPN tunnel establishment. +#custom-header = "X-My-Header: hi there" diff --git a/tests/firewall-test b/tests/firewall-test new file mode 100755 index 00000000..fe30d963 --- /dev/null +++ b/tests/firewall-test @@ -0,0 +1,142 @@ +#!/bin/sh +# +# Copyright (C) 2014 Red Hat +# +# This file is part of ocserv. +# +# ocserv 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. +# +# ocserv 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 ocserv; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +srcdir=${srcdir:-.} + +#this test can only be run as root +id|grep root >/dev/null 2>&1 +if [ $? != 0 ];then + exit 77 +fi + +PORT_OCSERV=443 +CONFIG="fw" +IMAGE=ocserv-fw-test +IMAGE_NAME=test_fw_ocserv +TMP=$IMAGE_NAME.tmp +. ./docker-common.sh + +$DOCKER run -e OCCTL_PAGER=cat -P --privileged=true -p 22 --tty=false -d --name $IMAGE_NAME $IMAGE +if test $? != 0;then + echo "Cannot run docker image" + exit 1 +fi + +echo "ocserv image was run" +#wait for ocserv to server +sleep 5 + +IP=`$DOCKER inspect $IMAGE_NAME | grep IPAddress | cut -d '"' -f 4` +if test -z "$IP";then + echo "Detected IP is null!" + stop +fi +echo "Detected IP: $IP" + +if test ! -z "$QUIT_ON_INIT";then + exit 0 +fi + +$ECHO_E "testuser" >pass-full$TMP +$OPENCONNECT $IP:$PORT_OCSERV -u test --passwd-on-stdin -v --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 --cookieonly < pass-full$TMP +if test $? = 0;then + echo "Authentication with wrong password succeeded!" + stop +fi + +$ECHO_E "test" >pass-full$TMP +$OPENCONNECT $IP:$PORT_OCSERV -u testuser --passwd-on-stdin -v --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 --cookieonly < pass-full$TMP +if test $? = 0;then + echo "Authentication with wrong username succeeded!" + stop +fi + +echo "" +echo "Connecting with correct username" +$ECHO_E "test" >pass-full$TMP +$OPENCONNECT $IP:$PORT_OCSERV -b --pid-file ${srcdir}/pid1.$$ -u test --passwd-on-stdin -v --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 < pass-full$TMP +if test $? != 0;then + echo "Cannot connect to server" + stop +fi + +#wait for openconnect +sleep 5 + +rm -f pass-full$TMP +if [ ! -f ${srcdir}/pid1.$$ ];then + echo "It was not possible to establish session!" + stop +fi + +PID=`cat ${srcdir}/pid1.$$` + +ping -w 5 192.168.84.1 -s 400 +if test $? != 0;then + kill -INT $PID + echo "Cannot ping ocserv" + stop +fi + +ping6 -w 5 fd91:6d87:7441:dc6a::1 +if test $? != 0;then + kill -INT $PID + echo "Cannot ping the IPv6 of ocserv" + stop +fi + +retrieve_user_info test "Restricted to routes: True" + +# There is an issue in nuttcp that makes it crash under docker if +# /proc/sys/net/ipv4/tcp_adv_win_scale does not exist. +if test "$FEDORA" = 1;then +nuttcp -T 10 -t 192.168.84.1 +if test $? != 0;then + echo "Cannot send to ocserv" + exit 77 + kill -INT $PID + stop +fi + +nuttcp -T 10 -r 192.168.84.1 +if test $? != 0;then + echo "Cannot recv from ocserv" + exit 77 + kill -INT $PID + stop +fi +fi + +sleep 2 + +kill -INT $PID + +sleep 4 + +check_for_file /tmp/follow-up-script-was-run +if test $? != 0;then + echo "There was an issue; followup script was not run" + stop +fi + +$DOCKER stop $IMAGE_NAME +$DOCKER rm $IMAGE_NAME + +exit $ret diff --git a/tests/full-test b/tests/full-test index 933c069b..967753e6 100755 --- a/tests/full-test +++ b/tests/full-test @@ -91,21 +91,21 @@ PID=`cat ${srcdir}/pid1.$$` # The client IP depends on the username so it shouldn't change. ping -w 5 192.168.79.1 if test $? != 0;then - kill $PID + kill -INT $PID echo "Cannot ping ocserv" stop fi ping -w 5 192.168.79.1 -s 1500 if test $? != 0;then - kill $PID + kill -INT $PID echo "Cannot ping ocserv" stop fi ping6 -w 5 fd91:6d87:7341:db6a::1 if test $? != 0;then - kill $PID + kill -INT $PID echo "Cannot ping the IPv6 of ocserv" stop fi @@ -119,7 +119,7 @@ nuttcp -T 10 -t 192.168.79.1 if test $? != 0;then echo "Cannot send to ocserv" exit 77 - kill $PID + kill -INT $PID stop fi @@ -127,14 +127,14 @@ nuttcp -T 10 -r 192.168.79.1 if test $? != 0;then echo "Cannot recv from ocserv" exit 77 - kill $PID + kill -INT $PID stop fi fi sleep 2 -kill $PID +kill -INT $PID sleep 4