Skip to content

Commit

Permalink
Merge pull request #1 from kylemanna/master
Browse files Browse the repository at this point in the history
Bring fork up to date
  • Loading branch information
HumanPrinter authored Feb 10, 2021
2 parents d53043e + 1228577 commit 5f68159
Show file tree
Hide file tree
Showing 15 changed files with 141 additions and 183 deletions.
13 changes: 5 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,15 @@ LABEL maintainer="Kyle Manna <[email protected]>"

# Testing: pamtester
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing/" >> /etc/apk/repositories && \
apk add --update openvpn iptables bash easy-rsa openvpn-auth-pam google-authenticator pamtester && \
apk add --update openvpn iptables bash easy-rsa openvpn-auth-pam google-authenticator pamtester libqrencode && \
ln -s /usr/share/easy-rsa/easyrsa /usr/local/bin && \
rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/*

# Needed by scripts
ENV OPENVPN /etc/openvpn
ENV EASYRSA /usr/share/easy-rsa
ENV EASYRSA_PKI $OPENVPN/pki
ENV EASYRSA_VARS_FILE $OPENVPN/vars

# Prevents refused client connection because of an expired CRL
ENV EASYRSA_CRL_DAYS 3650
ENV OPENVPN=/etc/openvpn
ENV EASYRSA=/usr/share/easy-rsa \
EASYRSA_CRL_DAYS=3650 \
EASYRSA_PKI=$OPENVPN/pki

VOLUME ["/etc/openvpn"]

Expand Down
1 change: 0 additions & 1 deletion Dockerfile.aarch64
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ RUN echo "http://dl-4.alpinelinux.org/alpine/edge/community/" >> /etc/apk/reposi
ENV OPENVPN /etc/openvpn
ENV EASYRSA /usr/share/easy-rsa
ENV EASYRSA_PKI $OPENVPN/pki
ENV EASYRSA_VARS_FILE $OPENVPN/vars

# Prevents refused client connection because of an expired CRL
ENV EASYRSA_CRL_DAYS 3650
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,20 @@ a corresponding [Digital Ocean Community Tutorial](http://bit.ly/1AGUZkq).
private key used by the newly generated certificate authority.

docker volume create --name $OVPN_DATA
docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_genconfig -u udp://VPN.SERVERNAME.COM
docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn ovpn_initpki
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://VPN.SERVERNAME.COM
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki

* Start OpenVPN server process

docker run -v $OVPN_DATA:/etc/openvpn -d -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn

* Generate a client certificate without a passphrase

docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn easyrsa build-client-full CLIENTNAME nopass
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full CLIENTNAME nopass

* Retrieve the client configuration with embedded certificates

docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_getclient CLIENTNAME > CLIENTNAME.ovpn
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient CLIENTNAME > CLIENTNAME.ovpn

## Next Steps

Expand All @@ -69,7 +69,7 @@ If you prefer to use `docker-compose` please refer to the [documentation](docs/d

* Create an environment variable with the name DEBUG and value of 1 to enable debug output (using "docker -e").

docker run -v $OVPN_DATA:/etc/openvpn -p 1194:1194/udp --privileged -e DEBUG=1 kylemanna/openvpn
docker run -v $OVPN_DATA:/etc/openvpn -p 1194:1194/udp --cap-add=NET_ADMIN -e DEBUG=1 kylemanna/openvpn

* Test using a client that has openvpn installed correctly

Expand Down
39 changes: 0 additions & 39 deletions bin/easyrsa_vars

This file was deleted.

5 changes: 3 additions & 2 deletions bin/ovpn_otp_user
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ if [ "$2" == "interactive" ]; then
# Always use time base OTP otherwise storage for counters must be configured somewhere in volume
google-authenticator --time-based --force -l "${1}@${OVPN_CN}" -s /etc/openvpn/otp/${1}.google_authenticator
else
# Skip confirmation if not running in interctive mode. Essential for integration tests.
google-authenticator --time-based --disallow-reuse --force --rate-limit=3 --rate-time=30 --window-size=3 \
-l "${1}@${OVPN_CN}" -s /etc/openvpn/otp/${1}.google_authenticator
fi
-l "${1}@${OVPN_CN}" -s /etc/openvpn/otp/${1}.google_authenticator --no-confirm
fi
24 changes: 1 addition & 23 deletions bin/ovpn_revokeclient
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ if [ -z "$EASYRSA_PKI" ]; then
fi

cn="$1"
parm="$2"

if [ ! -f "$EASYRSA_PKI/private/${cn}.key" ]; then
echo "Unable to find \"${cn}\", please try again or generate the key first" >&2
Expand All @@ -37,25 +36,4 @@ revoke_client_certificate(){
chmod 644 "$OPENVPN/crl.pem"
}

remove_files(){
rm -v "$EASYRSA_PKI/issued/${1}.crt"
rm -v "$EASYRSA_PKI/private/${1}.key"
rm -v "$EASYRSA_PKI/reqs/${1}.req"
}

case "$parm" in
"remove")
revoke_client_certificate "$cn"
remove_files "$cn"
;;
"" | "keep")
revoke_client_certificate "$cn"
;;
*)
echo "When revoking a client certificate, this script let you choose if you want to remove the corresponding crt, key and req files." >&2
echo "Pease note that the removal of those files is required if you want to generate a new client certificate using the revoked certificate's CN." >&2
echo " 1. keep (default): Keep the files." >&2
echo " 2. remove: Remove the files." >&2
echo "Please specify one of those options as second parameter." >&2
;;
esac
revoke_client_certificate "$cn"
21 changes: 13 additions & 8 deletions bin/ovpn_run
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ function addArg {
# this allows rules/routing to be altered by supplying this function
# in an included file, such as ovpn_env.sh
function setupIptablesAndRouting {
iptables -t nat -C POSTROUTING -s $OVPN_SERVER -o $OVPN_NATDEVICE -j MASQUERADE || {
iptables -t nat -C POSTROUTING -s $OVPN_SERVER -o $OVPN_NATDEVICE -j MASQUERADE 2>/dev/null || {
iptables -t nat -A POSTROUTING -s $OVPN_SERVER -o $OVPN_NATDEVICE -j MASQUERADE
}
for i in "${OVPN_ROUTES[@]}"; do
iptables -t nat -C POSTROUTING -s "$i" -o $OVPN_NATDEVICE -j MASQUERADE || {
iptables -t nat -C POSTROUTING -s "$i" -o $OVPN_NATDEVICE -j MASQUERADE 2>/dev/null || {
iptables -t nat -A POSTROUTING -s "$i" -o $OVPN_NATDEVICE -j MASQUERADE
}
done
Expand Down Expand Up @@ -87,13 +87,18 @@ fi

ip -6 route show default 2>/dev/null
if [ $? = 0 ]; then
echo "Enabling IPv6 Forwarding"
# If this fails, ensure the docker container is run with --privileged
# Could be side stepped with `ip netns` madness to drop privileged flag
echo "Checking IPv6 Forwarding"
if [ "$(</proc/sys/net/ipv6/conf/all/disable_ipv6)" != "0" ]; then
echo "Sysctl error for disable_ipv6, please run docker with '--sysctl net.ipv6.conf.all.disable_ipv6=0'"
fi

if [ "$(</proc/sys/net/ipv6/conf/default/forwarding)" != "1" ]; then
echo "Sysctl error for default forwarding, please run docker with '--sysctl net.ipv6.conf.default.forwarding=1'"
fi

sysctl -w net.ipv6.conf.all.disable_ipv6=0 || echo "Failed to enable IPv6 support"
sysctl -w net.ipv6.conf.default.forwarding=1 || echo "Failed to enable IPv6 Forwarding default"
sysctl -w net.ipv6.conf.all.forwarding=1 || echo "Failed to enable IPv6 Forwarding"
if [ "$(</proc/sys/net/ipv6/conf/all/forwarding)" != "1" ]; then
echo "Sysctl error for all forwarding, please run docker with '--sysctl net.ipv6.conf.all.forwarding=1'"
fi
fi

echo "Running 'openvpn ${ARGS[@]} ${USER_ARGS[@]}'"
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ The [`ovpn_genconfig`](/bin/ovpn_genconfig) script is intended for simple config

* Start the server with:

docker run -v $PWD:/etc/openvpn -d -p 1194:1194/udp --privileged kylemanna/openvpn
docker run -v $PWD:/etc/openvpn -d -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn
2 changes: 1 addition & 1 deletion docs/tcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ specified protocol, adjust the mapping appropriately:
## Running a Second Fallback TCP Container
Instead of choosing between UDP and TCP, you can use both. A single instance of OpenVPN can only listen for a single protocol on a single port, but this image makes it easy to run two instances simultaneously. After building, configuring, and starting a standard container listening for UDP traffic on 1194, you can start a second container listening for tcp traffic on port 443:

docker run -v $OVPN_DATA:/etc/openvpn --rm -p 443:1194/tcp --privileged kylemanna/openvpn ovpn_run --proto tcp
docker run -v $OVPN_DATA:/etc/openvpn --rm -p 443:1194/tcp --cap-add=NET_ADMIN kylemanna/openvpn ovpn_run --proto tcp

`ovpn_run` will load all the values from the default config file, and `--proto tcp` will override the protocol setting.

Expand Down
46 changes: 29 additions & 17 deletions test/client/wait-for-connect.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,46 @@ set -e

OPENVPN_CONFIG=${1:-/client/config.ovpn}

# Run in background, rely on bash for job management
# For some reason privileged mode creates the char device and cap-add=NET_ADMIN doesn't
mkdir -p /dev/net
if [ ! -c /dev/net/tun ]; then
mknod /dev/net/tun c 10 200
fi

# Run in background using bash job management, setup trap to clean-up
trap "{ jobs -p | xargs -r kill; wait; }" EXIT
openvpn --config "$OPENVPN_CONFIG" --management 127.0.0.1 9999 &

# Spin waiting for interface to exist signifying connection
timeout=10
for i in $(seq $timeout); do
# Allow to start-up
sleep 0.5

# Use bash magic to open tcp socket on fd 3 and break when successful
exec 3<>/dev/tcp/127.0.0.1/9999 && break
done

# Break when connected
#echo state | busybox nc 127.0.0.1 9999 | grep -q "CONNECTED,SUCCESS" && break;
if [ $i -ge $timeout ]; then
echo "Error connecting to OpenVPN mgmt interface, i=$i, exiting."
exit 2
fi

# Bash magic for tcp sockets
if exec 3<>/dev/tcp/127.0.0.1/9999; then
# Consume all header input
while read -t 0.1 <&3; do true; done
echo "state" >&3
read -t 1 <&3
echo -n $REPLY | grep -q "CONNECTED,SUCCESS" && break || true
exec 3>&-
fi
# Consume all header input and echo, look for errors here
while read -t 0.1 <&3; do echo $REPLY; done

# Else sleep
# Request state over mgmt interface
timeout=10
for i in $(seq $timeout); do
echo "state" >&3
state=$(head -n1 <&3)
echo -n "$state" | grep -q 'CONNECTED,SUCCESS' && break
sleep 1
done

if [ $i -ge $timeout ]; then
echo "Error starting OpenVPN, i=$i, exiting."
exit 2;
echo "Error connecting to OpenVPN, i=$i, exiting."
exit 3
fi

# The show is over.
kill %1
exec 3>&-
30 changes: 11 additions & 19 deletions test/tests/basic/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,22 @@ docker run -v $OVPN_DATA:/etc/openvpn --rm $IMG ovpn_getclient $CLIENT | tee $CL
docker run -v $OVPN_DATA:/etc/openvpn --rm $IMG ovpn_listclients | grep $CLIENT

#
# Fire up the server
# Fire up the server and setup a trap to always clean it up
#
sudo iptables -N DOCKER || echo 'Firewall already configured'
sudo iptables -I FORWARD -j DOCKER || echo 'Forward already configured'
# run in shell bg to get logs
docker run --name "ovpn-test" -v $OVPN_DATA:/etc/openvpn --rm -p 1194:1194/udp --privileged $IMG &
trap "{ jobs -p | xargs -r kill; wait; }" EXIT
docker run --name "ovpn-test" -v $OVPN_DATA:/etc/openvpn --rm -e DEBUG --cap-add=NET_ADMIN $IMG &

#for i in $(seq 10); do
# SERV_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}')
# test -n "$SERV_IP" && break
#done
#sed -ie s:SERV_IP:$SERV_IP:g config.ovpn
for i in $(seq 10); do
SERV_IP_INTERNAL=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' "ovpn-test" 2>/dev/null || true)
test -n "$SERV_IP_INTERNAL" && break
sleep 0.1
done
sed -i -e s:$SERV_IP:$SERV_IP_INTERNAL:g ${CLIENT_DIR}/config.ovpn

#
# Fire up a client in a container since openvpn is disallowed by Travis-CI, don't NAT
# the host as it confuses itself:
# "Incoming packet rejected from [AF_INET]172.17.42.1:1194[2], expected peer address: [AF_INET]10.240.118.86:1194"
# Fire up a client in a container since openvpn is disallowed by Travis-CI
#
docker run --rm --net=host --privileged --volume $CLIENT_DIR:/client $IMG /client/wait-for-connect.sh

#
# Client either connected or timed out, kill server
#
kill %1
docker run --rm --cap-add=NET_ADMIN -e DEBUG --volume $CLIENT_DIR:/client $IMG /client/wait-for-connect.sh

#
# Celebrate
Expand Down
35 changes: 21 additions & 14 deletions test/tests/dual-proto/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,32 @@ docker run -v $OVPN_DATA:/etc/openvpn --rm $IMG ovpn_listclients | grep $CLIENT_
#
# Fire up the server
#
sudo iptables -N DOCKER || echo 'Firewall already configured'
sudo iptables -I FORWARD -j DOCKER || echo 'Forward already configured'

# run in shell bg to get logs
docker run --name "ovpn-test-udp" -v $OVPN_DATA:/etc/openvpn --rm -p 1194:1194/udp --privileged $IMG &
docker run --name "ovpn-test-tcp" -v $OVPN_DATA:/etc/openvpn --rm -p 443:1194/tcp --privileged $IMG ovpn_run --proto tcp &
# Run in shell bg to get logs, setup trap to clean-up
trap "{ jobs -p | xargs -r kill; wait; docker volume rm ${OVPN_DATA}; }" EXIT
docker run --name "ovpn-test-udp" -v $OVPN_DATA:/etc/openvpn --rm --cap-add=NET_ADMIN -e DEBUG $IMG &
docker run --name "ovpn-test-tcp" -v $OVPN_DATA:/etc/openvpn --rm --cap-add=NET_ADMIN -e DEBUG $IMG ovpn_run --proto tcp --port 443 &

#
# Fire up a clients in a containers since openvpn is disallowed by Travis-CI, don't NAT
# the host as it confuses itself:
# "Incoming packet rejected from [AF_INET]172.17.42.1:1194[2], expected peer address: [AF_INET]10.240.118.86:1194"
#
docker run --rm --net=host --privileged --volume $CLIENT_DIR:/client $IMG /client/wait-for-connect.sh
docker run --rm --net=host --privileged --volume $CLIENT_DIR:/client $IMG /client/wait-for-connect.sh "/client/config-tcp.ovpn"
# Update configs
for i in $(seq 10); do
SERV_IP_INTERNAL=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' "ovpn-test-udp" 2>/dev/null || true)
test -n "$SERV_IP_INTERNAL" && break
sleep 0.1
done
sed -i -e s:$SERV_IP:$SERV_IP_INTERNAL:g $CLIENT_DIR/config.ovpn

for i in $(seq 10); do
SERV_IP_INTERNAL=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' "ovpn-test-tcp" 2>/dev/null || true)
test -n "$SERV_IP_INTERNAL" && break
sleep 0.1
done
sed -i -e s:$SERV_IP:$SERV_IP_INTERNAL:g $CLIENT_DIR/config-tcp.ovpn

#
# Client either connected or timed out, kill server
# Fire up a clients in a containers since openvpn is disallowed by Travis-CI
#
kill %1 %2
docker run --rm --cap-add=NET_ADMIN -v $CLIENT_DIR:/client -e DEBUG $IMG /client/wait-for-connect.sh
docker run --rm --cap-add=NET_ADMIN -v $CLIENT_DIR:/client -e DEBUG $IMG /client/wait-for-connect.sh "/client/config-tcp.ovpn"

#
# Celebrate
Expand Down
12 changes: 7 additions & 5 deletions test/tests/iptables/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@ docker run -v $OVPN_DATA:/etc/openvpn --rm -it -e "EASYRSA_BATCH=1" -e "EASYRSA_
docker run -d --name $NAME -v $OVPN_DATA:/etc/openvpn --cap-add=NET_ADMIN $IMG

# check default iptables rules
docker exec -ti $NAME bash -c 'source /etc/openvpn/ovpn_env.sh; eval iptables -t nat -C POSTROUTING -s $OVPN_SERVER -o eth0 -j MASQUERADE'
for i in $(seq 10); do
docker exec -ti $NAME bash -c 'source /etc/openvpn/ovpn_env.sh; exec iptables -t nat -C POSTROUTING -s $OVPN_SERVER -o eth0 -j MASQUERADE' && break
echo waiting for server start-up
sleep 1
done

# append new setupIptablesAndRouting function to config
docker exec -ti $NAME bash -c 'echo function setupIptablesAndRouting { iptables -t nat -A POSTROUTING -m comment --comment "test"\;} >> /etc/openvpn/ovpn_env.sh'

# kill server in preparation to modify config
docker kill $NAME
docker rm $NAME
docker rm -f $NAME

# check that overridden function exists and that test iptables rules is active
docker run -d --name $NAME -v $OVPN_DATA:/etc/openvpn --cap-add=NET_ADMIN $IMG
Expand All @@ -33,6 +36,5 @@ docker exec -ti $NAME bash -c 'source /etc/openvpn/ovpn_env.sh; type -t setupIpt
# kill server
#

docker kill $NAME
docker rm $NAME
docker rm -f $NAME
docker volume rm $OVPN_DATA
Loading

0 comments on commit 5f68159

Please sign in to comment.