Merge branch 'dual-proto' of git://github.com/dave-burke/docker-openvpn into dave-burke-dual-proto

This commit is contained in:
Kyle Manna 2016-06-01 14:44:16 -07:00
commit 14827df71d
4 changed files with 115 additions and 9 deletions

View File

@ -22,7 +22,6 @@ VOLUME ["/etc/openvpn"]
# Internally uses port 1194/udp, remap using `docker run -p 443:1194/tcp`
EXPOSE 1194/udp
WORKDIR /etc/openvpn
CMD ["ovpn_run"]
ADD ./bin /usr/local/bin

View File

@ -10,8 +10,32 @@ fi
set -e
cd $OPENVPN
# Build runtime arguments array based on environment
ARGS=("--config" "$OPENVPN/openvpn.conf")
USER_ARGS=("${@}")
ARGS=()
# Checks if ARGS already contains the given value
function hasArg {
local element
for element in "${@:2}"; do
[ "${element}" == "${1}" ] && return 0
done
return 1
}
# Adds the given argument if it's not already specified.
function addArg {
local arg="${1}"
[ $# -ge 1 ] && local val="${2}"
if ! hasArg "${arg}" "${USER_ARGS[@]}"; then
ARGS+=("${arg}")
[ $# -ge 1 ] && ARGS+=("${val}")
fi
}
addArg "--config" "$OPENVPN/openvpn.conf"
source "$OPENVPN/ovpn_env.sh"
@ -21,7 +45,7 @@ if [ ! -c /dev/net/tun ]; then
fi
if [ -d "$OPENVPN/ccd" ]; then
ARGS+=("--client-config-dir" "$OPENVPN/ccd")
addArg "--client-config-dir" "$OPENVPN/ccd"
fi
# When using --net=host, use this to specify nat device.
@ -46,7 +70,7 @@ if [ -r "$EASYRSA_PKI/crl.pem" ]; then
ln "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
chmod 644 "$OPENVPN/crl.pem"
fi
ARGS+=("--crl-verify" "$OPENVPN/crl.pem")
addArg "--crl-verify" "$OPENVPN/crl.pem"
fi
ip -6 route show default 2>/dev/null
@ -59,8 +83,6 @@ if [ $? = 0 ]; then
sysctl -w net.ipv6.conf.all.forwarding=1 || echo "Failed to enable IPv6 Forwarding"
fi
if [ "$#" -gt 0 ]; then
exec openvpn "$@"
else
exec openvpn ${ARGS[@]}
fi
echo "Running 'openvpn ${ARGS[@]} ${USER_ARGS[@]}'"
exec openvpn ${ARGS[@]} ${USER_ARGS[@]}

View File

@ -5,6 +5,8 @@ By default, OpenVPN is configured to use the UDP protocol. Because UDP incurs m
As an example, users connecting from an airplane wifi network may experience high packet drop rates, where the error detection and sliding window control of TCP can more readily adjust to the inconsistent connection.
Another example would be trying to open a VPN connection from within a very restrictive network. In some cases port 1194, or even UDP traffic on any port, may be restricted by network policy. Because TCP traffic on port 443 is used for normal TLS (https) web browsing, it is very unlikely to be blocked.
## Using TCP
Those requiring TCP connections should initialize the data container by specifying the TCP protocol and port number:
@ -16,3 +18,14 @@ specified protocol, adjust the mapping appropriately:
docker run --volumes-from $OVPN_DATA -d -p 443:1194/tcp --cap-add=NET_ADMIN kylemanna/openvpn
## 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 --volumes-from $OVPN_DATA --rm -p 443:1194/tcp --privileged 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.
This allows you to use UDP most of the time, but fall back to TCP on the rare occasion that you need it.
Note that you will need to configure client connections manually. At this time it is not possible to generate a client config that will automatically fall back to the TCP connection.

72
tests/dual-proto.sh Executable file
View File

@ -0,0 +1,72 @@
#!/bin/bash
set -ex
OVPN_DATA=dual-data
CLIENT_UDP=travis-client
CLIENT_TCP=travis-client-tcp
IMG=kylemanna/openvpn
#
# Create a docker container with the config data
#
docker run --name $OVPN_DATA -v /etc/openvpn busybox
ip addr ls
SERV_IP=$(ip -4 -o addr show scope global | awk '{print $4}' | sed -e 's:/.*::' | head -n1)
# get temporary TCP config
docker run --volumes-from $OVPN_DATA --rm $IMG ovpn_genconfig -u tcp://$SERV_IP:443
# nopass is insecure
docker run --volumes-from $OVPN_DATA --rm -it -e "EASYRSA_BATCH=1" -e "EASYRSA_REQ_CN=Travis-CI Test CA" $IMG ovpn_initpki nopass
# gen TCP client
docker run --volumes-from $OVPN_DATA --rm -it $IMG easyrsa build-client-full $CLIENT_TCP nopass
docker run --volumes-from $OVPN_DATA --rm $IMG ovpn_getclient $CLIENT_TCP | tee client/config-tcp.ovpn
# switch to UDP config and gen UDP client
docker run --volumes-from $OVPN_DATA --rm $IMG ovpn_genconfig -u udp://$SERV_IP
docker run --volumes-from $OVPN_DATA --rm -it $IMG easyrsa build-client-full $CLIENT_UDP nopass
docker run --volumes-from $OVPN_DATA --rm $IMG ovpn_getclient $CLIENT_UDP | tee client/config.ovpn
#Verify client configs
docker run --volumes-from $OVPN_DATA --rm $IMG ovpn_listclients | grep $CLIENT_TCP
docker run --volumes-from $OVPN_DATA --rm $IMG ovpn_listclients | grep $CLIENT_UDP
#
# Fire up the server
#
sudo iptables -N DOCKER
sudo iptables -I FORWARD -j DOCKER
# run in shell bg to get logs
docker run --name "ovpn-test-udp" --volumes-from $OVPN_DATA --rm -p 1194:1194/udp --privileged $IMG &
docker run --name "ovpn-test-tcp" --volumes-from $OVPN_DATA --rm -p 443:1194/tcp --privileged $IMG ovpn_run --proto tcp &
#
# 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 $PWD/client:/client $IMG /client/wait-for-connect.sh
docker run --rm --net=host --privileged --volume $PWD/client:/client $IMG /client/wait-for-connect.sh "/client/config-tcp.ovpn"
#
# Client either connected or timed out, kill server
#
kill %1
#
# Celebrate
#
cat <<EOF
____________ ___________
< it worked! > < both ways! >
------------ ------------
\ ^__^ ^__^ /
\ (oo)\______/(oo) /
(__)\ /(__)
||w---w||
|| ||
EOF