Compare commits
71 Commits
docs_syste
...
openvpn-v2
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9be09fec9c | ||
![]() |
925b08fec4 | ||
![]() |
7a29e8e39b | ||
![]() |
16fbc4019d | ||
![]() |
63a2449705 | ||
![]() |
1b8374f818 | ||
![]() |
8d7bc7e2c5 | ||
![]() |
e30ee8eecf | ||
![]() |
469338f550 | ||
![]() |
e00a72a3f6 | ||
![]() |
d974c0ac6a | ||
![]() |
c0ed8d468d | ||
![]() |
2a9059aa36 | ||
![]() |
074a07e40e | ||
![]() |
8c9d88b316 | ||
![]() |
78d612d181 | ||
![]() |
6bff62eb79 | ||
![]() |
8f2f27486c | ||
![]() |
3ee5479d78 | ||
![]() |
909744dd78 | ||
![]() |
5aea8b914c | ||
![]() |
a091bef13b | ||
![]() |
59644d953d | ||
![]() |
dcf3791d54 | ||
![]() |
76546e1823 | ||
![]() |
f996bbaa8e | ||
![]() |
861ed05c48 | ||
![]() |
ce690e5ab1 | ||
![]() |
e4821ec709 | ||
![]() |
808e2448b1 | ||
![]() |
fe2cdebea2 | ||
![]() |
892a3c9a1c | ||
![]() |
a3c96bc881 | ||
![]() |
22fcaf9477 | ||
![]() |
d454a20e80 | ||
![]() |
c8ba567333 | ||
![]() |
21ae2fcef4 | ||
![]() |
24944b0a11 | ||
![]() |
b74cbd5c74 | ||
![]() |
93c3a0453d | ||
![]() |
b868fa9093 | ||
![]() |
fbb97918cf | ||
![]() |
e282e1eed0 | ||
![]() |
5236365fe1 | ||
![]() |
a293af4246 | ||
![]() |
47de917de5 | ||
![]() |
cbf9cbf433 | ||
![]() |
4fd8296a62 | ||
![]() |
0e3f34effd | ||
![]() |
e8b568a0b9 | ||
![]() |
a2adb59d69 | ||
![]() |
f4351bb0dd | ||
![]() |
14c45f418c | ||
![]() |
7627f8e9f9 | ||
![]() |
26635395b2 | ||
![]() |
abdf537da5 | ||
![]() |
1d2a2e8b29 | ||
![]() |
f487184a4a | ||
![]() |
1a984ba9cd | ||
![]() |
aaf2c0fee1 | ||
![]() |
c4fc888dca | ||
![]() |
be165e209e | ||
![]() |
ef8221372d | ||
![]() |
c9ada1eac4 | ||
![]() |
2cc170f001 | ||
![]() |
8f304ea3fe | ||
![]() |
a20c63893e | ||
![]() |
fbdc8e32c6 | ||
![]() |
3ebc4903d8 | ||
![]() |
1129eb09bc | ||
![]() |
b07b4957f8 |
@@ -1,12 +1,12 @@
|
|||||||
# Original credit: https://github.com/jpetazzo/dockvpn
|
# Original credit: https://github.com/jpetazzo/dockvpn
|
||||||
|
|
||||||
# Smallest base image
|
# Smallest base image
|
||||||
FROM alpine:3.5
|
FROM alpine:3.6
|
||||||
|
|
||||||
MAINTAINER Kyle Manna <kyle@kylemanna.com>
|
MAINTAINER Kyle Manna <kyle@kylemanna.com>
|
||||||
|
|
||||||
RUN echo "http://dl-4.alpinelinux.org/alpine/edge/community/" >> /etc/apk/repositories && \
|
# Testing: pamtester
|
||||||
echo "http://dl-4.alpinelinux.org/alpine/edge/testing/" >> /etc/apk/repositories && \
|
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 && \
|
||||||
ln -s /usr/share/easy-rsa/easyrsa /usr/local/bin && \
|
ln -s /usr/share/easy-rsa/easyrsa /usr/local/bin && \
|
||||||
rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/*
|
rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/*
|
||||||
@@ -17,6 +17,9 @@ ENV EASYRSA /usr/share/easy-rsa
|
|||||||
ENV EASYRSA_PKI $OPENVPN/pki
|
ENV EASYRSA_PKI $OPENVPN/pki
|
||||||
ENV EASYRSA_VARS_FILE $OPENVPN/vars
|
ENV EASYRSA_VARS_FILE $OPENVPN/vars
|
||||||
|
|
||||||
|
# Prevents refused client connection because of an expired CRL
|
||||||
|
ENV EASYRSA_CRL_DAYS 3650
|
||||||
|
|
||||||
VOLUME ["/etc/openvpn"]
|
VOLUME ["/etc/openvpn"]
|
||||||
|
|
||||||
# Internally uses port 1194/udp, remap using `docker run -p 443:1194/tcp`
|
# Internally uses port 1194/udp, remap using `docker run -p 443:1194/tcp`
|
||||||
|
34
Dockerfile.aarch64
Normal file
34
Dockerfile.aarch64
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Original credit: https://github.com/jpetazzo/dockvpn
|
||||||
|
|
||||||
|
# Smallest base image
|
||||||
|
FROM aarch64/alpine:3.5
|
||||||
|
|
||||||
|
MAINTAINER Kyle Manna <kyle@kylemanna.com>
|
||||||
|
|
||||||
|
RUN echo "http://dl-4.alpinelinux.org/alpine/edge/community/" >> /etc/apk/repositories && \
|
||||||
|
echo "http://dl-4.alpinelinux.org/alpine/edge/testing/" >> /etc/apk/repositories && \
|
||||||
|
apk add --update openvpn iptables bash easy-rsa openvpn-auth-pam google-authenticator pamtester && \
|
||||||
|
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
|
||||||
|
|
||||||
|
VOLUME ["/etc/openvpn"]
|
||||||
|
|
||||||
|
# Internally uses port 1194/udp, remap using `docker run -p 443:1194/tcp`
|
||||||
|
EXPOSE 1194/udp
|
||||||
|
|
||||||
|
CMD ["ovpn_run"]
|
||||||
|
|
||||||
|
ADD ./bin /usr/local/bin
|
||||||
|
RUN chmod a+x /usr/local/bin/*
|
||||||
|
|
||||||
|
# Add support for OTP authentication using a PAM module
|
||||||
|
ADD ./otp/openvpn /etc/pam.d/
|
32
README.md
32
README.md
@@ -18,11 +18,16 @@ a corresponding [Digital Ocean Community Tutorial](http://bit.ly/1AGUZkq).
|
|||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
* Pick a name for the `$OVPN_DATA` data volume container, it will be created automatically.
|
* Pick a name for the `$OVPN_DATA` data volume container. It's recommended to
|
||||||
|
use the `ovpn-data-` prefix to operate seamlessly with the reference systemd
|
||||||
|
service. Users are encourage to replace `example` with a descriptive name of
|
||||||
|
their choosing.
|
||||||
|
|
||||||
OVPN_DATA="ovpn-data"
|
OVPN_DATA="ovpn-data-example"
|
||||||
|
|
||||||
* Initialize the `$OVPN_DATA` container that will hold the configuration files and certificates
|
* Initialize the `$OVPN_DATA` container that will hold the configuration files
|
||||||
|
and certificates. The container will prompt for a passphrase to protect the
|
||||||
|
private key used by the newly generated certificate authority.
|
||||||
|
|
||||||
docker volume create --name $OVPN_DATA
|
docker volume create --name $OVPN_DATA
|
||||||
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 kylemanna/openvpn ovpn_genconfig -u udp://VPN.SERVERNAME.COM
|
||||||
@@ -40,13 +45,32 @@ a corresponding [Digital Ocean Community Tutorial](http://bit.ly/1AGUZkq).
|
|||||||
|
|
||||||
docker run -v $OVPN_DATA:/etc/openvpn --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
|
||||||
|
|
||||||
|
### More Reading
|
||||||
|
|
||||||
|
Miscellaneous write-ups for advanced configurations are available in the
|
||||||
|
[docs](docs) folder.
|
||||||
|
|
||||||
|
### Systemd Init Scripts
|
||||||
|
|
||||||
|
A `systemd` init script is available to manage the OpenVPN container. It will
|
||||||
|
start the container on system boot, restart the container if it exits
|
||||||
|
unexpectedly, and pull updates from Docker Hub to keep itself up to date.
|
||||||
|
|
||||||
|
Please refer to the [systemd documentation](docs/systemd.md) to learn more.
|
||||||
|
|
||||||
|
### Docker Compose
|
||||||
|
|
||||||
|
If you prefer to use `docker-compose` please refer to the [documentation](docs/docker-compose.md).
|
||||||
|
|
||||||
## Debugging Tips
|
## Debugging Tips
|
||||||
|
|
||||||
* Create an environment variable with the name DEBUG and value of 1 to enable debug output (using "docker -e").
|
* 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 --privileged -e DEBUG=1 kylemanna/openvpn
|
||||||
|
|
||||||
* Test using a client that has openvpn installed correctly
|
* Test using a client that has openvpn installed correctly
|
||||||
|
|
||||||
$ openvpn --config CLIENTNAME.ovpn
|
$ openvpn --config CLIENTNAME.ovpn
|
||||||
|
|
||||||
|
@@ -4,8 +4,6 @@
|
|||||||
# Generate OpenVPN configs
|
# Generate OpenVPN configs
|
||||||
#
|
#
|
||||||
|
|
||||||
USE_DEFAULT_ROUTE=true
|
|
||||||
|
|
||||||
TMP_PUSH_CONFIGFILE=$(mktemp -t vpn_push.XXXXXXX)
|
TMP_PUSH_CONFIGFILE=$(mktemp -t vpn_push.XXXXXXX)
|
||||||
TMP_ROUTE_CONFIGFILE=$(mktemp -t vpn_route.XXXXXXX)
|
TMP_ROUTE_CONFIGFILE=$(mktemp -t vpn_route.XXXXXXX)
|
||||||
TMP_EXTRA_CONFIGFILE=$(mktemp -t vpn_extra.XXXXXXX)
|
TMP_EXTRA_CONFIGFILE=$(mktemp -t vpn_extra.XXXXXXX)
|
||||||
@@ -85,6 +83,7 @@ usage() {
|
|||||||
echo "usage: $0 [-d]"
|
echo "usage: $0 [-d]"
|
||||||
echo " -u SERVER_PUBLIC_URL"
|
echo " -u SERVER_PUBLIC_URL"
|
||||||
echo " [-e EXTRA_SERVER_CONFIG ]"
|
echo " [-e EXTRA_SERVER_CONFIG ]"
|
||||||
|
echo " [-E EXTRA_CLIENT_CONFIG ]"
|
||||||
echo " [-f FRAGMENT ]"
|
echo " [-f FRAGMENT ]"
|
||||||
echo " [-n DNS_SERVER ...]"
|
echo " [-n DNS_SERVER ...]"
|
||||||
echo " [-p PUSH ...]"
|
echo " [-p PUSH ...]"
|
||||||
@@ -94,10 +93,12 @@ usage() {
|
|||||||
echo "optional arguments:"
|
echo "optional arguments:"
|
||||||
echo " -2 Enable two factor authentication using Google Authenticator."
|
echo " -2 Enable two factor authentication using Google Authenticator."
|
||||||
echo " -a Authenticate packets with HMAC using the given message digest algorithm (auth)."
|
echo " -a Authenticate packets with HMAC using the given message digest algorithm (auth)."
|
||||||
|
echo " -b Disable 'push block-outside-dns'"
|
||||||
echo " -c Enable client-to-client option"
|
echo " -c Enable client-to-client option"
|
||||||
echo " -C A list of allowable TLS ciphers delimited by a colon (cipher)."
|
echo " -C A list of allowable TLS ciphers delimited by a colon (cipher)."
|
||||||
echo " -d Disable NAT routing and default route"
|
echo " -d Disable default route"
|
||||||
echo " -D Do not push dns servers"
|
echo " -D Do not push dns servers"
|
||||||
|
echo " -k Set keepalive. Default: '10 60'"
|
||||||
echo " -m Set client MTU"
|
echo " -m Set client MTU"
|
||||||
echo " -N Configure NAT to access external server network"
|
echo " -N Configure NAT to access external server network"
|
||||||
echo " -t Use TAP device (instead of TUN device)"
|
echo " -t Use TAP device (instead of TUN device)"
|
||||||
@@ -118,7 +119,7 @@ process_push_config() {
|
|||||||
local ovpn_push_config=''
|
local ovpn_push_config=''
|
||||||
ovpn_push_config="$1"
|
ovpn_push_config="$1"
|
||||||
echo "Processing PUSH Config: '${ovpn_push_config}'"
|
echo "Processing PUSH Config: '${ovpn_push_config}'"
|
||||||
[[ -n "$ovpn_push_config" ]] && echo "push $ovpn_push_config" >> "$TMP_PUSH_CONFIGFILE"
|
[[ -n "$ovpn_push_config" ]] && echo "push \"$ovpn_push_config\"" >> "$TMP_PUSH_CONFIGFILE"
|
||||||
}
|
}
|
||||||
|
|
||||||
process_extra_config() {
|
process_extra_config() {
|
||||||
@@ -126,7 +127,6 @@ process_extra_config() {
|
|||||||
ovpn_extra_config="$1"
|
ovpn_extra_config="$1"
|
||||||
echo "Processing Extra Config: '${ovpn_extra_config}'"
|
echo "Processing Extra Config: '${ovpn_extra_config}'"
|
||||||
[[ -n "$ovpn_extra_config" ]] && echo "$ovpn_extra_config" >> "$TMP_EXTRA_CONFIGFILE"
|
[[ -n "$ovpn_extra_config" ]] && echo "$ovpn_extra_config" >> "$TMP_EXTRA_CONFIGFILE"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "${DEBUG:-}" == "1" ]; then
|
if [ "${DEBUG:-}" == "1" ]; then
|
||||||
@@ -142,31 +142,52 @@ if [ -z "${EASYRSA_PKI:-}" ]; then
|
|||||||
export EASYRSA_PKI="$OPENVPN/pki"
|
export EASYRSA_PKI="$OPENVPN/pki"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
OVPN_ENV=${OPENVPN}/ovpn_env.sh
|
OVPN_AUTH=''
|
||||||
OVPN_SERVER=192.168.255.0/24
|
OVPN_CIPHER=''
|
||||||
|
OVPN_CLIENT_TO_CLIENT=''
|
||||||
|
OVPN_CN=''
|
||||||
|
OVPN_COMP_LZO=0
|
||||||
OVPN_DEFROUTE=1
|
OVPN_DEFROUTE=1
|
||||||
OVPN_NAT=0
|
|
||||||
OVPN_DNS=1
|
|
||||||
OVPN_DEVICE="tun"
|
OVPN_DEVICE="tun"
|
||||||
OVPN_DEVICEN=0
|
OVPN_DEVICEN=0
|
||||||
OVPN_DNS_SERVERS=("8.8.8.8" "8.8.4.4")
|
OVPN_DISABLE_PUSH_BLOCK_DNS=0
|
||||||
TMP_DNS_SERVERS=()
|
OVPN_DNS=1
|
||||||
|
OVPN_DNS_SERVERS=()
|
||||||
|
OVPN_ENV=${OPENVPN}/ovpn_env.sh
|
||||||
|
OVPN_EXTRA_CLIENT_CONFIG=()
|
||||||
|
OVPN_EXTRA_SERVER_CONFIG=()
|
||||||
|
OVPN_FRAGMENT=''
|
||||||
|
OVPN_KEEPALIVE="10 60"
|
||||||
|
OVPN_MTU=''
|
||||||
|
OVPN_NAT=0
|
||||||
|
OVPN_PORT=''
|
||||||
|
OVPN_PROTO=''
|
||||||
|
OVPN_PUSH=()
|
||||||
|
OVPN_ROUTES=()
|
||||||
|
OVPN_SERVER=192.168.255.0/24
|
||||||
|
OVPN_SERVER_URL=''
|
||||||
OVPN_TLS_CIPHER=''
|
OVPN_TLS_CIPHER=''
|
||||||
OVPN_CIPHER=''
|
|
||||||
OVPN_AUTH=''
|
|
||||||
OVPN_EXTRA_CONFIG=''
|
|
||||||
|
|
||||||
# Import defaults if present
|
# Import existing configuration if present
|
||||||
[ -r "$OVPN_ENV" ] && source "$OVPN_ENV"
|
[ -r "$OVPN_ENV" ] && source "$OVPN_ENV"
|
||||||
|
|
||||||
# Parse arguments
|
# Parse arguments
|
||||||
while getopts ":a:e:C:T:r:s:du:cp:n:DNmf:tz2" opt; do
|
while getopts ":a:e:E:C:T:r:s:du:bcp:n:k:DNm:f:tz2" opt; do
|
||||||
case $opt in
|
case $opt in
|
||||||
a)
|
a)
|
||||||
OVPN_AUTH="$OPTARG"
|
OVPN_AUTH="$OPTARG"
|
||||||
;;
|
;;
|
||||||
e)
|
e)
|
||||||
process_extra_config "$OPTARG"
|
mapfile -t TMP_EXTRA_SERVER_CONFIG < <(echo "$OPTARG")
|
||||||
|
for i in "${TMP_EXTRA_SERVER_CONFIG[@]}"; do
|
||||||
|
OVPN_EXTRA_SERVER_CONFIG+=("$i")
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
E)
|
||||||
|
mapfile -t TMP_EXTRA_CLIENT_CONFIG < <(echo "$OPTARG")
|
||||||
|
for i in "${TMP_EXTRA_CLIENT_CONFIG[@]}"; do
|
||||||
|
OVPN_EXTRA_CLIENT_CONFIG+=("$i")
|
||||||
|
done
|
||||||
;;
|
;;
|
||||||
C)
|
C)
|
||||||
OVPN_CIPHER="$OPTARG"
|
OVPN_CIPHER="$OPTARG"
|
||||||
@@ -175,26 +196,38 @@ while getopts ":a:e:C:T:r:s:du:cp:n:DNmf:tz2" opt; do
|
|||||||
OVPN_TLS_CIPHER="$OPTARG"
|
OVPN_TLS_CIPHER="$OPTARG"
|
||||||
;;
|
;;
|
||||||
r)
|
r)
|
||||||
USE_DEFAULT_ROUTE=false
|
mapfile -t TMP_ROUTES < <(echo "$OPTARG")
|
||||||
process_route_config "$OPTARG"
|
for i in "${TMP_ROUTES[@]}"; do
|
||||||
|
OVPN_ROUTES+=("$i")
|
||||||
|
done
|
||||||
;;
|
;;
|
||||||
s)
|
s)
|
||||||
OVPN_SERVER=$OPTARG
|
OVPN_SERVER="$OPTARG"
|
||||||
;;
|
;;
|
||||||
d)
|
d)
|
||||||
OVPN_DEFROUTE=0
|
OVPN_DEFROUTE=0
|
||||||
|
OVPN_DISABLE_PUSH_BLOCK_DNS=1
|
||||||
;;
|
;;
|
||||||
u)
|
u)
|
||||||
OVPN_SERVER_URL=$OPTARG
|
OVPN_SERVER_URL="$OPTARG"
|
||||||
|
;;
|
||||||
|
b)
|
||||||
|
OVPN_DISABLE_PUSH_BLOCK_DNS=1
|
||||||
;;
|
;;
|
||||||
c)
|
c)
|
||||||
OVPN_CLIENT_TO_CLIENT=1
|
OVPN_CLIENT_TO_CLIENT=1
|
||||||
;;
|
;;
|
||||||
p)
|
p)
|
||||||
process_push_config "$OPTARG"
|
mapfile -t TMP_PUSH < <(echo "$OPTARG")
|
||||||
|
for i in "${TMP_PUSH[@]}"; do
|
||||||
|
OVPN_PUSH+=("$i")
|
||||||
|
done
|
||||||
;;
|
;;
|
||||||
n)
|
n)
|
||||||
TMP_DNS_SERVERS+=("$OPTARG")
|
mapfile -t TMP_DNS_SERVERS < <(echo "$OPTARG")
|
||||||
|
for i in "${TMP_DNS_SERVERS[@]}"; do
|
||||||
|
OVPN_DNS_SERVERS+=("$i")
|
||||||
|
done
|
||||||
;;
|
;;
|
||||||
D)
|
D)
|
||||||
OVPN_DNS=0
|
OVPN_DNS=0
|
||||||
@@ -202,8 +235,11 @@ while getopts ":a:e:C:T:r:s:du:cp:n:DNmf:tz2" opt; do
|
|||||||
N)
|
N)
|
||||||
OVPN_NAT=1
|
OVPN_NAT=1
|
||||||
;;
|
;;
|
||||||
|
k)
|
||||||
|
OVPN_KEEPALIVE="$OPTARG"
|
||||||
|
;;
|
||||||
m)
|
m)
|
||||||
OVPN_MTU=$OPTARG
|
OVPN_MTU="$OPTARG"
|
||||||
;;
|
;;
|
||||||
t)
|
t)
|
||||||
OVPN_DEVICE="tap"
|
OVPN_DEVICE="tap"
|
||||||
@@ -215,7 +251,7 @@ while getopts ":a:e:C:T:r:s:du:cp:n:DNmf:tz2" opt; do
|
|||||||
OVPN_OTP_AUTH=1
|
OVPN_OTP_AUTH=1
|
||||||
;;
|
;;
|
||||||
f)
|
f)
|
||||||
OVPN_FRAGMENT=$OPTARG
|
OVPN_FRAGMENT="$OPTARG"
|
||||||
;;
|
;;
|
||||||
\?)
|
\?)
|
||||||
set +x
|
set +x
|
||||||
@@ -235,11 +271,8 @@ done
|
|||||||
# Create ccd directory for static routes
|
# Create ccd directory for static routes
|
||||||
[ ! -d "${OPENVPN:-}/ccd" ] && mkdir -p ${OPENVPN:-}/ccd
|
[ ! -d "${OPENVPN:-}/ccd" ] && mkdir -p ${OPENVPN:-}/ccd
|
||||||
|
|
||||||
# if dns servers were not defined with -n, use google nameservers
|
|
||||||
[ ${#TMP_DNS_SERVERS[@]} -gt 0 ] && OVPN_DNS_SERVERS=("${TMP_DNS_SERVERS[@]}")
|
|
||||||
|
|
||||||
# Server name is in the form "udp://vpn.example.com:1194"
|
# Server name is in the form "udp://vpn.example.com:1194"
|
||||||
if [[ "${OVPN_SERVER_URL:-}" =~ ^((udp|tcp)://)?([0-9a-zA-Z\.\-]+)(:([0-9]+))?$ ]]; then
|
if [[ "${OVPN_SERVER_URL:-}" =~ ^((udp|tcp|udp6|tcp6)://)?([0-9a-zA-Z\.\-]+)(:([0-9]+))?$ ]]; then
|
||||||
OVPN_PROTO=${BASH_REMATCH[2]};
|
OVPN_PROTO=${BASH_REMATCH[2]};
|
||||||
OVPN_CN=${BASH_REMATCH[3]};
|
OVPN_CN=${BASH_REMATCH[3]};
|
||||||
OVPN_PORT=${BASH_REMATCH[5]};
|
OVPN_PORT=${BASH_REMATCH[5]};
|
||||||
@@ -250,18 +283,13 @@ else
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Apply defaults
|
# Apply defaults. If dns servers were not defined with -n, use google nameservers
|
||||||
|
set +u
|
||||||
|
[ -z "$OVPN_DNS_SERVERS" ] && OVPN_DNS_SERVERS=("8.8.8.8" "8.8.4.4")
|
||||||
[ -z "$OVPN_PROTO" ] && OVPN_PROTO=udp
|
[ -z "$OVPN_PROTO" ] && OVPN_PROTO=udp
|
||||||
[ -z "$OVPN_PORT" ] && OVPN_PORT=1194
|
[ -z "$OVPN_PORT" ] && OVPN_PORT=1194
|
||||||
[ $USE_DEFAULT_ROUTE ] && process_route_config "192.168.254.0/24"
|
set -u
|
||||||
|
[ "${#OVPN_ROUTES[@]}" == "0" ] && [ "$OVPN_DEFROUTE" == "1" ] && OVPN_ROUTES+=("192.168.254.0/24")
|
||||||
export OVPN_SERVER OVPN_ROUTES OVPN_DEFROUTE
|
|
||||||
export OVPN_SERVER_URL OVPN_ENV OVPN_PROTO OVPN_CN OVPN_PORT
|
|
||||||
export OVPN_CLIENT_TO_CLIENT OVPN_PUSH OVPN_NAT OVPN_DNS OVPN_MTU OVPN_DEVICE
|
|
||||||
export OVPN_TLS_CIPHER OVPN_CIPHER OVPN_AUTH
|
|
||||||
export OVPN_COMP_LZO
|
|
||||||
export OVPN_OTP_AUTH
|
|
||||||
export OVPN_FRAGMENT
|
|
||||||
|
|
||||||
# Preserve config
|
# Preserve config
|
||||||
if [ -f "$OVPN_ENV" ]; then
|
if [ -f "$OVPN_ENV" ]; then
|
||||||
@@ -269,7 +297,11 @@ if [ -f "$OVPN_ENV" ]; then
|
|||||||
echo "Backing up $OVPN_ENV -> $bak_env"
|
echo "Backing up $OVPN_ENV -> $bak_env"
|
||||||
mv "$OVPN_ENV" "$bak_env"
|
mv "$OVPN_ENV" "$bak_env"
|
||||||
fi
|
fi
|
||||||
export | grep OVPN_ > "$OVPN_ENV"
|
|
||||||
|
# Save the current OVPN_ vars to the ovpn_env.sh file
|
||||||
|
while read -r var; do
|
||||||
|
echo "declare -x $var" >> "$OVPN_ENV"
|
||||||
|
done < <(set | grep '^OVPN_')
|
||||||
|
|
||||||
conf=${OPENVPN:-}/openvpn.conf
|
conf=${OPENVPN:-}/openvpn.conf
|
||||||
if [ -f "$conf" ]; then
|
if [ -f "$conf" ]; then
|
||||||
@@ -278,6 +310,13 @@ if [ -f "$conf" ]; then
|
|||||||
mv "$conf" "$bak"
|
mv "$conf" "$bak"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Echo extra client configurations
|
||||||
|
if [ ${#OVPN_EXTRA_CLIENT_CONFIG[@]} -gt 0 ]; then
|
||||||
|
for i in "${OVPN_EXTRA_CLIENT_CONFIG[@]}"; do
|
||||||
|
echo "Processing Extra Client Config: $i"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
cat > "$conf" <<EOF
|
cat > "$conf" <<EOF
|
||||||
server $(getroute $OVPN_SERVER)
|
server $(getroute $OVPN_SERVER)
|
||||||
verb 3
|
verb 3
|
||||||
@@ -287,7 +326,7 @@ cert $EASYRSA_PKI/issued/${OVPN_CN}.crt
|
|||||||
dh $EASYRSA_PKI/dh.pem
|
dh $EASYRSA_PKI/dh.pem
|
||||||
tls-auth $EASYRSA_PKI/ta.key
|
tls-auth $EASYRSA_PKI/ta.key
|
||||||
key-direction 0
|
key-direction 0
|
||||||
keepalive 10 60
|
keepalive $OVPN_KEEPALIVE
|
||||||
persist-key
|
persist-key
|
||||||
persist-tun
|
persist-tun
|
||||||
|
|
||||||
@@ -301,38 +340,57 @@ user nobody
|
|||||||
group nogroup
|
group nogroup
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
#This was in the heredoc, we use the new function instead
|
if [ "${OVPN_DISABLE_PUSH_BLOCK_DNS}" == "1" ]; then
|
||||||
process_push_config "block-outside-dns"
|
echo "Disable default push of 'block-outside-dns'"
|
||||||
|
else
|
||||||
|
process_push_config "block-outside-dns"
|
||||||
|
fi
|
||||||
|
|
||||||
[ -n "$OVPN_TLS_CIPHER" ] && echo "tls-cipher $OVPN_TLS_CIPHER" >> "$conf"
|
[ -n "$OVPN_TLS_CIPHER" ] && echo "tls-cipher $OVPN_TLS_CIPHER" >> "$conf"
|
||||||
[ -n "$OVPN_CIPHER" ] && echo "cipher $OVPN_CIPHER" >> "$conf"
|
[ -n "$OVPN_CIPHER" ] && echo "cipher $OVPN_CIPHER" >> "$conf"
|
||||||
[ -n "$OVPN_AUTH" ] && echo "auth $OVPN_AUTH" >> "$conf"
|
[ -n "$OVPN_AUTH" ] && echo "auth $OVPN_AUTH" >> "$conf"
|
||||||
|
|
||||||
[ -n "${OVPN_CLIENT_TO_CLIENT:-}" ] && echo "client-to-client" >> "$conf"
|
[ -n "${OVPN_CLIENT_TO_CLIENT:-}" ] && echo "client-to-client" >> "$conf"
|
||||||
[ -n "${OVPN_COMP_LZO:-}" ] && echo "comp-lzo" >> "$conf"
|
[ "$OVPN_COMP_LZO" == "1" ] && echo "comp-lzo" >> "$conf"
|
||||||
|
|
||||||
[ -n "${OVPN_FRAGMENT:-}" ] && echo "fragment $OVPN_FRAGMENT" >> "$conf"
|
[ -n "${OVPN_FRAGMENT:-}" ] && echo "fragment $OVPN_FRAGMENT" >> "$conf"
|
||||||
|
|
||||||
|
# Append route commands
|
||||||
|
if [ ${#OVPN_ROUTES[@]} -gt 0 ]; then
|
||||||
|
for i in "${OVPN_ROUTES[@]}"; do
|
||||||
|
process_route_config "$i"
|
||||||
|
done
|
||||||
|
echo -e "\n### Route Configurations Below" >> "$conf"
|
||||||
|
cat $TMP_ROUTE_CONFIGFILE >> "$conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Append push commands
|
||||||
[ "$OVPN_DNS" == "1" ] && for i in "${OVPN_DNS_SERVERS[@]}"; do
|
[ "$OVPN_DNS" == "1" ] && for i in "${OVPN_DNS_SERVERS[@]}"; do
|
||||||
process_push_config "dhcp-option DNS $i"
|
process_push_config "dhcp-option DNS $i"
|
||||||
done
|
done
|
||||||
|
|
||||||
# Append route commands
|
[ ${#OVPN_PUSH[@]} -gt 0 ] && for i in "${OVPN_PUSH[@]}"; do
|
||||||
echo -e "\n### Route Configurations Below" >> "$conf"
|
process_push_config "$i"
|
||||||
cat $TMP_ROUTE_CONFIGFILE >> "$conf"
|
done
|
||||||
|
|
||||||
# Append push commands
|
|
||||||
echo -e "\n### Push Configurations Below" >> "$conf"
|
echo -e "\n### Push Configurations Below" >> "$conf"
|
||||||
cat $TMP_PUSH_CONFIGFILE >> "$conf"
|
cat $TMP_PUSH_CONFIGFILE >> "$conf"
|
||||||
|
|
||||||
# Optional OTP authentication support
|
# Append optional OTP authentication support
|
||||||
if [ -n "${OVPN_OTP_AUTH:-}" ]; then
|
if [ -n "${OVPN_OTP_AUTH:-}" ]; then
|
||||||
echo -e "\n\n# Enable OTP+PAM for user authentication" >> "$conf"
|
echo -e "\n\n# Enable OTP+PAM for user authentication" >> "$conf"
|
||||||
echo "plugin /usr/lib/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn" >> "$conf"
|
echo "plugin /usr/lib/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn" >> "$conf"
|
||||||
|
echo "reneg-sec 0" >> "$conf"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "\n### Extra Configurations Below" >> "$conf"
|
# Append extra server configurations
|
||||||
cat $TMP_EXTRA_CONFIGFILE >> "$conf"
|
if [ ${#OVPN_EXTRA_SERVER_CONFIG[@]} -gt 0 ]; then
|
||||||
|
for i in "${OVPN_EXTRA_SERVER_CONFIG[@]}"; do
|
||||||
|
process_extra_config "$i"
|
||||||
|
done
|
||||||
|
echo -e "\n### Extra Configurations Below" >> "$conf"
|
||||||
|
cat $TMP_EXTRA_CONFIGFILE >> "$conf"
|
||||||
|
fi
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
|
|
||||||
|
@@ -35,11 +35,18 @@ get_client_config() {
|
|||||||
client
|
client
|
||||||
nobind
|
nobind
|
||||||
dev $OVPN_DEVICE
|
dev $OVPN_DEVICE
|
||||||
key-direction 1
|
|
||||||
remote-cert-tls server
|
remote-cert-tls server
|
||||||
|
|
||||||
remote $OVPN_CN $OVPN_PORT $OVPN_PROTO
|
remote $OVPN_CN $OVPN_PORT $OVPN_PROTO"
|
||||||
"
|
if [ "$OVPN_PROTO" == "udp6" ]; then
|
||||||
|
echo "remote $OVPN_CN $OVPN_PORT udp"
|
||||||
|
fi
|
||||||
|
if [ "$OVPN_PROTO" == "tcp6" ]; then
|
||||||
|
echo "remote $OVPN_CN $OVPN_PORT tcp"
|
||||||
|
fi
|
||||||
|
for i in "${OVPN_EXTRA_CLIENT_CONFIG[@]}"; do
|
||||||
|
echo "$i"
|
||||||
|
done
|
||||||
if [ "$mode" == "combined" ]; then
|
if [ "$mode" == "combined" ]; then
|
||||||
echo "
|
echo "
|
||||||
<key>
|
<key>
|
||||||
@@ -62,7 +69,6 @@ key ${cn}.key
|
|||||||
ca ca.crt
|
ca ca.crt
|
||||||
cert ${cn}.crt
|
cert ${cn}.crt
|
||||||
tls-auth ta.key 1
|
tls-auth ta.key 1
|
||||||
$OVPN_ADDITIONAL_CLIENT_CONFIG
|
|
||||||
"
|
"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -91,9 +97,13 @@ $OVPN_ADDITIONAL_CLIENT_CONFIG
|
|||||||
echo "auth-nocache"
|
echo "auth-nocache"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$OVPN_COMP_LZO" ]; then
|
if [ "$OVPN_COMP_LZO" == "1" ]; then
|
||||||
echo "comp-lzo"
|
echo "comp-lzo"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -n "$OVPN_OTP_AUTH" ]; then
|
||||||
|
echo reneg-sec 0
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
dir="$OPENVPN/clients/$cn"
|
dir="$OPENVPN/clients/$cn"
|
||||||
@@ -114,9 +124,9 @@ case "$parm" in
|
|||||||
get_client_config "combined" > "$dir/${cn}-combined.ovpn"
|
get_client_config "combined" > "$dir/${cn}-combined.ovpn"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "This script can produce the client configuration in to formats:" >&2
|
echo "This script can produce the client configuration in two formats:" >&2
|
||||||
echo " 1. combined (default): All needed configuration and cryptographic material is in one file (Use \"combined-save\" to write the configuration file in the same path as the separated parameter does)." >&2
|
echo " 1. combined (default): All needed configuration and cryptographic material is in one file (Use \"combined-save\" to write the configuration file in the same path as the separated parameter does)." >&2
|
||||||
echo " 2. separated: Separated files." >&2
|
echo " 2. separated: Separated files." >&2
|
||||||
echo "Please specific one of those options as second parameter." >&2
|
echo "Please specify one of those options as second parameter." >&2
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@@ -38,3 +38,6 @@ openvpn --genkey --secret $EASYRSA_PKI/ta.key
|
|||||||
|
|
||||||
# For a server key with a password, manually init; this is autopilot
|
# For a server key with a password, manually init; this is autopilot
|
||||||
easyrsa build-server-full "$OVPN_CN" nopass
|
easyrsa build-server-full "$OVPN_CN" nopass
|
||||||
|
|
||||||
|
# Generate the CRL for client/server certificates revocation.
|
||||||
|
easyrsa gen-crl
|
||||||
|
61
bin/ovpn_revokeclient
Executable file
61
bin/ovpn_revokeclient
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# Revoke a client certificate
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ "$DEBUG" == "1" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ -z "$OPENVPN" ]; then
|
||||||
|
export OPENVPN="$PWD"
|
||||||
|
fi
|
||||||
|
if ! source "$OPENVPN/ovpn_env.sh"; then
|
||||||
|
echo "Could not source $OPENVPN/ovpn_env.sh."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ -z "$EASYRSA_PKI" ]; then
|
||||||
|
export EASYRSA_PKI="$OPENVPN/pki"
|
||||||
|
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
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
revoke_client_certificate(){
|
||||||
|
easyrsa revoke "$1"
|
||||||
|
echo "Generating the Certificate Revocation List :"
|
||||||
|
easyrsa gen-crl
|
||||||
|
cp -f "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
|
||||||
|
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
|
42
bin/ovpn_run
42
bin/ovpn_run
@@ -35,6 +35,21 @@ function addArg {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# set up iptables rules and routing
|
||||||
|
# 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 -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 -A POSTROUTING -s "$i" -o $OVPN_NATDEVICE -j MASQUERADE
|
||||||
|
}
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
addArg "--config" "$OPENVPN/openvpn.conf"
|
addArg "--config" "$OPENVPN/openvpn.conf"
|
||||||
|
|
||||||
source "$OPENVPN/ovpn_env.sh"
|
source "$OPENVPN/ovpn_env.sh"
|
||||||
@@ -53,23 +68,20 @@ fi
|
|||||||
|
|
||||||
# Setup NAT forwarding if requested
|
# Setup NAT forwarding if requested
|
||||||
if [ "$OVPN_DEFROUTE" != "0" ] || [ "$OVPN_NAT" == "1" ] ; then
|
if [ "$OVPN_DEFROUTE" != "0" ] || [ "$OVPN_NAT" == "1" ] ; then
|
||||||
iptables -t nat -C POSTROUTING -s $OVPN_SERVER -o $OVPN_NATDEVICE -j MASQUERADE || {
|
# call function to setup iptables rules and routing
|
||||||
iptables -t nat -A POSTROUTING -s $OVPN_SERVER -o $OVPN_NATDEVICE -j MASQUERADE
|
# this allows rules to be customized by supplying
|
||||||
}
|
# a replacement function in, for example, ovpn_env.sh
|
||||||
for i in "${OVPN_ROUTES[@]}"; do
|
setupIptablesAndRouting
|
||||||
iptables -t nat -C POSTROUTING -s "$i" -o $OVPN_NATDEVICE -j MASQUERADE || {
|
|
||||||
iptables -t nat -A POSTROUTING -s "$i" -o $OVPN_NATDEVICE -j MASQUERADE
|
|
||||||
}
|
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use a hacky hardlink as the CRL Needs to be readable by the user/group
|
# Use a copy of crl.pem as the CRL Needs to be readable by the user/group
|
||||||
# OpenVPN is running as. Only pass arguments to OpenVPN if it's found.
|
# OpenVPN is running as. Only pass arguments to OpenVPN if it's found.
|
||||||
if [ -r "$EASYRSA_PKI/crl.pem" ]; then
|
if [ "$EASYRSA_PKI/crl.pem" -nt "$OPENVPN/crl.pem" ]; then
|
||||||
if [ ! -r "$OPENVPN/crl.pem" ]; then
|
cp -f "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
|
||||||
ln "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
|
chmod 644 "$OPENVPN/crl.pem"
|
||||||
chmod 644 "$OPENVPN/crl.pem"
|
fi
|
||||||
fi
|
|
||||||
|
if [ -r "$OPENVPN/crl.pem" ]; then
|
||||||
addArg "--crl-verify" "$OPENVPN/crl.pem"
|
addArg "--crl-verify" "$OPENVPN/crl.pem"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -79,10 +91,10 @@ if [ $? = 0 ]; then
|
|||||||
# If this fails, ensure the docker container is run with --privileged
|
# If this fails, ensure the docker container is run with --privileged
|
||||||
# Could be side stepped with `ip netns` madness to drop privileged flag
|
# Could be side stepped with `ip netns` madness to drop privileged flag
|
||||||
|
|
||||||
|
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.default.forwarding=1 || echo "Failed to enable IPv6 Forwarding default"
|
||||||
sysctl -w net.ipv6.conf.all.forwarding=1 || echo "Failed to enable IPv6 Forwarding"
|
sysctl -w net.ipv6.conf.all.forwarding=1 || echo "Failed to enable IPv6 Forwarding"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Running 'openvpn ${ARGS[@]} ${USER_ARGS[@]}'"
|
echo "Running 'openvpn ${ARGS[@]} ${USER_ARGS[@]}'"
|
||||||
exec openvpn ${ARGS[@]} ${USER_ARGS[@]}
|
exec openvpn ${ARGS[@]} ${USER_ARGS[@]}
|
||||||
|
|
||||||
|
@@ -18,4 +18,4 @@ I'd recommend encrypting the archive with something strong (e.g. gpg or openssl
|
|||||||
Creates an volume container named `$OVPN_DATA` to extract the data to.
|
Creates an volume container named `$OVPN_DATA` to extract the data to.
|
||||||
|
|
||||||
docker volume create --name $OVPN_DATA
|
docker volume create --name $OVPN_DATA
|
||||||
xzcat openvpn-backup.tar.xz | docker run $OVPN_DATA:/etc/openvpn -i kylemanna/openvpn tar -xvf - -C /etc
|
xzcat openvpn-backup.tar.xz | docker run -v $OVPN_DATA:/etc/openvpn -i kylemanna/openvpn tar -xvf - -C /etc
|
||||||
|
@@ -34,9 +34,12 @@ After doing so, you will find the following files in each of the `$cn` directori
|
|||||||
|
|
||||||
## Revoking Client Certificates
|
## Revoking Client Certificates
|
||||||
|
|
||||||
Revoke `client1`'s certificate and generate the certificate revocation list (CRL):
|
Revoke `client1`'s certificate and generate the certificate revocation list (CRL) using [`ovpn_revokeclient`](/bin/ovpn_revokeclient) script :
|
||||||
|
|
||||||
docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn easyrsa revoke client1
|
docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_revokeclient client1
|
||||||
docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn easyrsa gen-crl
|
|
||||||
|
|
||||||
The OpenVPN server will read this change every time a client connects (no need to restart server) and deny clients access using revoked certificates.
|
The OpenVPN server will read this change every time a client connects (no need to restart server) and deny clients access using revoked certificates.
|
||||||
|
|
||||||
|
You can optionally pass `remove` as second parameter to ovpn_revokeclient to remove the corresponding crt, key and req files :
|
||||||
|
|
||||||
|
docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_revokeclient client1 remove
|
||||||
|
@@ -2,41 +2,76 @@
|
|||||||
|
|
||||||
* Add a new service in docker-compose.yml
|
* Add a new service in docker-compose.yml
|
||||||
|
|
||||||
version: '2'
|
```yaml
|
||||||
services:
|
version: '2'
|
||||||
openvpn:
|
services:
|
||||||
cap_add:
|
openvpn:
|
||||||
- NET_ADMIN
|
cap_add:
|
||||||
image: kylemanna/openvpn
|
- NET_ADMIN
|
||||||
ports:
|
image: kylemanna/openvpn
|
||||||
- "1194:1194/udp"
|
container_name: openvpn
|
||||||
restart: always
|
ports:
|
||||||
volumes:
|
- "1194:1194/udp"
|
||||||
- ./openvpn/conf:/etc/openvpn
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./openvpn-data/conf:/etc/openvpn
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
* Initialize the configuration files and certificates
|
* Initialize the configuration files and certificates
|
||||||
|
|
||||||
docker-compose run --rm openvpn ovpn_genconfig -u udp://VPN.SERVERNAME.COM
|
```bash
|
||||||
docker-compose run --rm openvpn ovpn_initpki
|
docker-compose run --rm openvpn ovpn_genconfig -u udp://VPN.SERVERNAME.COM
|
||||||
|
docker-compose run --rm openvpn ovpn_initpki
|
||||||
|
```
|
||||||
|
|
||||||
* Fix ownership (depending on how to handle your backups, this may not be needed)
|
* Fix ownership (depending on how to handle your backups, this may not be needed)
|
||||||
|
|
||||||
sudo chown -R $(whoami): ./openvpn
|
```bash
|
||||||
|
sudo chown -R $(whoami): ./openvpn-data
|
||||||
|
```
|
||||||
|
|
||||||
* Start OpenVPN server process
|
* Start OpenVPN server process
|
||||||
|
|
||||||
docker-compose up -d openvpn
|
```bash
|
||||||
|
docker-compose up -d openvpn
|
||||||
|
```
|
||||||
|
|
||||||
* Generate a client certificate without a passphrase
|
* You can access the container logs with
|
||||||
|
|
||||||
docker-compose run --rm openvpn easyrsa build-client-full CLIENTNAME nopass
|
```bash
|
||||||
|
docker-compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
* Generate a client certificate
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export CLIENTNAME="your_client_name"
|
||||||
|
# with a passphrase (recommended)
|
||||||
|
docker-compose run --rm openvpn easyrsa build-client-full $CLIENTNAME
|
||||||
|
# without a passphrase (not recommended)
|
||||||
|
docker-compose run --rm openvpn easyrsa build-client-full $CLIENTNAME nopass
|
||||||
|
```
|
||||||
|
|
||||||
* Retrieve the client configuration with embedded certificates
|
* Retrieve the client configuration with embedded certificates
|
||||||
|
|
||||||
docker-compose run --rm openvpn ovpn_getclient CLIENTNAME > CLIENTNAME.ovpn
|
```bash
|
||||||
|
docker-compose run --rm openvpn ovpn_getclient $CLIENTNAME > $CLIENTNAME.ovpn
|
||||||
|
```
|
||||||
|
|
||||||
|
* Revoke a client certificate
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Keep the corresponding crt, key and req files.
|
||||||
|
docker-compose run --rm openvpn ovpn_revokeclient $CLIENTNAME
|
||||||
|
# Remove the corresponding crt, key and req files.
|
||||||
|
docker-compose run --rm openvpn ovpn_revokeclient $CLIENTNAME remove
|
||||||
|
```
|
||||||
|
|
||||||
## Debugging Tips
|
## Debugging Tips
|
||||||
|
|
||||||
* Create an environment variable with the name DEBUG and value of 1 to enable debug output (using "docker -e").
|
* Create an environment variable with the name DEBUG and value of 1 to enable debug output (using "docker -e").
|
||||||
|
|
||||||
docker-compose run -e DEBUG=1 openvpn
|
```bash
|
||||||
|
docker-compose run -e DEBUG=1 openvpn
|
||||||
|
```
|
||||||
|
@@ -91,4 +91,11 @@ Fire up a web browser and attempt to navigate to [https://ipv6.google.com](https
|
|||||||
|
|
||||||
## Connect to the OpenVPN Server Over IPv6
|
## Connect to the OpenVPN Server Over IPv6
|
||||||
|
|
||||||
Not implemented, yet.
|
This feature requires a docker daemon with working IPv6 support.
|
||||||
|
|
||||||
|
This will allow connections over IPv4 and IPv6.
|
||||||
|
|
||||||
|
Generate server configuration with the udp6 or tcp6 protocol:
|
||||||
|
|
||||||
|
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp6://VPN.SERVERNAME.COM
|
||||||
|
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u tcp6://VPN.SERVERNAME.COM
|
||||||
|
@@ -11,9 +11,11 @@ and use this image to generate user configuration.
|
|||||||
|
|
||||||
In order to enable two factor authentication the following steps are required.
|
In order to enable two factor authentication the following steps are required.
|
||||||
|
|
||||||
* Generate server configuration with `-2` option
|
* Choose a more secure [cipher](https://community.openvpn.net/openvpn/wiki/SWEET32) to use because since [OpenVPN 2.3.13](https://community.openvpn.net/openvpn/wiki/ChangesInOpenvpn23#OpenVPN2.3.13) the default openvpn cipher BF-CBC will cause a renegotiated connection every 64 MB of data
|
||||||
|
|
||||||
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://vpn.example.com -2
|
* Generate server configuration with `-2` and `-C $CIPHER` options
|
||||||
|
|
||||||
|
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://vpn.example.com -2 -C $CIPHER
|
||||||
|
|
||||||
* Generate your client certificate (possibly without a password since you're using OTP)
|
* Generate your client certificate (possibly without a password since you're using OTP)
|
||||||
|
|
||||||
|
@@ -15,11 +15,17 @@ are harmless for those not using IPv6.
|
|||||||
To use and enable automatic start by systemd:
|
To use and enable automatic start by systemd:
|
||||||
|
|
||||||
1. Create a Docker volume container named `ovpn-data-NAME` where `NAME` is the
|
1. Create a Docker volume container named `ovpn-data-NAME` where `NAME` is the
|
||||||
user's choice to describe the use of the container. In the example
|
user's choice to describe the use of the container. In this example
|
||||||
configuration given in the [README](/README.md) `NAME=data`.
|
configuration, `NAME=example`.
|
||||||
2. Initialize the data container according to the [docker-openvpn
|
|
||||||
README](/README.md), but don't start the container. Stop the Docker
|
OVPN_DATA="ovpn-data-example"
|
||||||
container if started.
|
docker volume create --name $OVPN_DATA
|
||||||
|
|
||||||
|
2. Initialize the data container, but don't start the container :
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
3. Download the [docker-openvpn@.service](https://raw.githubusercontent.com/kylemanna/docker-openvpn/master/init/docker-openvpn%40.service)
|
3. Download the [docker-openvpn@.service](https://raw.githubusercontent.com/kylemanna/docker-openvpn/master/init/docker-openvpn%40.service)
|
||||||
file to `/etc/systemd/system`:
|
file to `/etc/systemd/system`:
|
||||||
|
|
||||||
@@ -27,11 +33,11 @@ To use and enable automatic start by systemd:
|
|||||||
|
|
||||||
4. Enable and start the service with:
|
4. Enable and start the service with:
|
||||||
|
|
||||||
systemctl enable --now docker-openvpn@NAME.service
|
systemctl enable --now docker-openvpn@example.service
|
||||||
|
|
||||||
5. Verify service start-up with:
|
5. Verify service start-up with:
|
||||||
|
|
||||||
systemctl status docker-openvpn@NAME.service
|
systemctl status docker-openvpn@example.service
|
||||||
journalctl --unit docker-openvpn@NAME.service
|
journalctl --unit docker-openvpn@example.service
|
||||||
|
|
||||||
For more information, see the [systemd manual pages](https://www.freedesktop.org/software/systemd/man/index.html).
|
For more information, see the [systemd manual pages](https://www.freedesktop.org/software/systemd/man/index.html).
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
# 5. Verify service start-up with:
|
# 5. Verify service start-up with:
|
||||||
# `systemctl status docker-openvpn@NAME.service`
|
# `systemctl status docker-openvpn@NAME.service`
|
||||||
# `journalctl --unit docker-openvpn@NAME.service`
|
# `journalctl --unit docker-openvpn@NAME.service`
|
||||||
#
|
#
|
||||||
# For more information, see the systemd manual pages.
|
# For more information, see the systemd manual pages.
|
||||||
#
|
#
|
||||||
[Unit]
|
[Unit]
|
||||||
@@ -64,7 +64,7 @@ ExecStartPre=-/usr/bin/docker pull $IMG
|
|||||||
ExecStartPre=/bin/sh -c 'test -z "$IP6_PREFIX" && exit 0; sysctl net.ipv6.conf.all.forwarding=1'
|
ExecStartPre=/bin/sh -c 'test -z "$IP6_PREFIX" && exit 0; sysctl net.ipv6.conf.all.forwarding=1'
|
||||||
|
|
||||||
# Main process
|
# Main process
|
||||||
ExecStart=/usr/bin/docker run --rm --privileged -v ${DATA_VOL}:/etc/openvpn:ro --name ${NAME} -p ${PORT} ${IMG} ovpn_run $ARGS
|
ExecStart=/usr/bin/docker run --rm --privileged -v ${DATA_VOL}:/etc/openvpn --name ${NAME} -p ${PORT} ${IMG} ovpn_run $ARGS
|
||||||
|
|
||||||
# IPv6: Add static route for IPv6 after it starts up
|
# IPv6: Add static route for IPv6 after it starts up
|
||||||
ExecStartPost=/bin/sh -c 'test -z "${IP6_PREFIX}" && exit 0; sleep 1; ip route replace ${IP6_PREFIX} via $(docker inspect -f "{{ .NetworkSettings.GlobalIPv6Address }}" $NAME ) dev docker0'
|
ExecStartPost=/bin/sh -c 'test -z "${IP6_PREFIX}" && exit 0; sleep 1; ip route replace ${IP6_PREFIX} via $(docker inspect -f "{{ .NetworkSettings.GlobalIPv6Address }}" $NAME ) dev docker0'
|
||||||
|
@@ -4,5 +4,5 @@ start on filesystem and started docker
|
|||||||
stop on runlevel [!2345]
|
stop on runlevel [!2345]
|
||||||
respawn
|
respawn
|
||||||
script
|
script
|
||||||
exec docker run -v ovpn-data:/etc/openvpn --rm -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn
|
exec docker run -v ovpn-data-example:/etc/openvpn --rm -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn
|
||||||
end script
|
end script
|
||||||
|
@@ -7,10 +7,13 @@ testAlias+=(
|
|||||||
|
|
||||||
imageTests+=(
|
imageTests+=(
|
||||||
[openvpn]='
|
[openvpn]='
|
||||||
paranoid
|
paranoid
|
||||||
conf_options
|
conf_options
|
||||||
|
client
|
||||||
basic
|
basic
|
||||||
dual-proto
|
dual-proto
|
||||||
otp
|
otp
|
||||||
|
iptables
|
||||||
|
revocation
|
||||||
'
|
'
|
||||||
)
|
)
|
||||||
|
84
test/tests/client/container.sh
Normal file
84
test/tests/client/container.sh
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SERV_IP=$(ip -4 -o addr show scope global | awk '{print $4}' | sed -e 's:/.*::' | head -n1)
|
||||||
|
SERVER_CONF="/etc/openvpn/openvpn.conf"
|
||||||
|
TEST1_OVPN="/etc/openvpn/test1.ovpn"
|
||||||
|
|
||||||
|
# Function to fail
|
||||||
|
abort() { cat <<< "$@" 1>&2; exit 1; }
|
||||||
|
|
||||||
|
# Check a config (haystack) for a given line (needle) exit with error if not
|
||||||
|
# found.
|
||||||
|
test_config() {
|
||||||
|
|
||||||
|
local needle="${2}"
|
||||||
|
local file="${1}"
|
||||||
|
|
||||||
|
busybox grep -q "${needle}" "${file}"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
abort "==> Config match not found: ${needle}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check a config (haystack) for absence of given line (needle) exit with error
|
||||||
|
# if found.
|
||||||
|
test_not_config() {
|
||||||
|
|
||||||
|
local needle="${2}"
|
||||||
|
local file="${1}"
|
||||||
|
|
||||||
|
busybox grep -vq "${needle}" "${file}"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
abort "==> Config match found: ${needle}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate openvpn.config file
|
||||||
|
#
|
||||||
|
|
||||||
|
ovpn_genconfig \
|
||||||
|
-u udp://$SERV_IP \
|
||||||
|
-m 1337 \
|
||||||
|
|
||||||
|
|
||||||
|
EASYRSA_BATCH=1 EASYRSA_REQ_CN="Travis-CI Test CA" ovpn_initpki nopass
|
||||||
|
|
||||||
|
easyrsa build-client-full test1 nopass 2>/dev/null
|
||||||
|
|
||||||
|
ovpn_getclient test1 > "${TEST1_OVPN}"
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Simple test cases
|
||||||
|
#
|
||||||
|
|
||||||
|
# 1. client MTU
|
||||||
|
test_config "${TEST1_OVPN}" "^tun-mtu\s\+1337"
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test udp client with tcp fallback
|
||||||
|
#
|
||||||
|
ovpn_genconfig -u udp://$SERV_IP -E "remote $SERV_IP 443 tcp" -E "remote vpn.example.com 443 tcp"
|
||||||
|
# nopass is insecure
|
||||||
|
EASYRSA_BATCH=1 EASYRSA_REQ_CN="Travis-CI Test CA" ovpn_initpki nopass
|
||||||
|
easyrsa build-client-full client-fallback nopass
|
||||||
|
ovpn_getclient client-fallback > "${TEST1_OVPN}"
|
||||||
|
|
||||||
|
test_config "${TEST1_OVPN}" "^remote\s\+$SERV_IP\s\+443\s\+tcp"
|
||||||
|
test_config "${TEST1_OVPN}" "^remote\s\+vpn.example.com\s\+443\s\+tcp"
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test non-defroute config
|
||||||
|
#
|
||||||
|
ovpn_genconfig -d -u udp://$SERV_IP -r "172.33.33.0/24" -r "172.34.34.0/24"
|
||||||
|
# nopass is insecure
|
||||||
|
EASYRSA_BATCH=1 EASYRSA_REQ_CN="Travis-CI Test CA" ovpn_initpki nopass
|
||||||
|
easyrsa build-client-full non-defroute nopass
|
||||||
|
ovpn_getclient non-defroute > "${TEST1_OVPN}"
|
||||||
|
|
||||||
|
# The '!' inverts the match to test that the string isn't present
|
||||||
|
test_not_config "${TEST1_OVPN}" "^redirect-gateway\s\+def1"
|
1
test/tests/client/run.sh
Symbolic link
1
test/tests/client/run.sh
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../run-bash-in-container.sh
|
@@ -1,8 +1,37 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
SERV_IP=$(ip -4 -o addr show scope global | awk '{print $4}' | sed -e 's:/.*::' | head -n1)
|
||||||
|
SERVER_CONF="/etc/openvpn/openvpn.conf"
|
||||||
|
TEST1_OVPN="/etc/openvpn/test1.ovpn"
|
||||||
|
|
||||||
# Function to fail
|
# Function to fail
|
||||||
abort() { cat <<< "$@" 1>&2; exit 1; }
|
abort() { cat <<< "$@" 1>&2; exit 1; }
|
||||||
|
|
||||||
|
# Check a config (haystack) for a given line (needle) exit with error if not found.
|
||||||
|
test_config() {
|
||||||
|
|
||||||
|
local needle="${2}"
|
||||||
|
local file="${1}"
|
||||||
|
|
||||||
|
busybox grep -q "${needle}" "${file}"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
abort "==> Config match not found: ${needle}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check a config (haystack) for absence of given line (needle) exit with error
|
||||||
|
# if found.
|
||||||
|
test_not_config() {
|
||||||
|
|
||||||
|
local needle="${2}"
|
||||||
|
local file="${1}"
|
||||||
|
|
||||||
|
busybox grep -vq "${needle}" "${file}"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
abort "==> Config match found: ${needle}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Generate openvpn.config file
|
# Generate openvpn.config file
|
||||||
@@ -12,154 +41,76 @@ management localhost 7505
|
|||||||
max-clients 10
|
max-clients 10
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
SERV_IP=$(ip -4 -o addr show scope global | awk '{print $4}' | sed -e 's:/.*::' | head -n1)
|
ovpn_genconfig \
|
||||||
ovpn_genconfig -u udp://$SERV_IP -f 1400 -e "$MULTILINE_EXTRA_SERVER_CONF" -e 'duplicate-cn' -e 'topology subnet' -p 'route 172.22.22.0 255.255.255.0'
|
-u udp://$SERV_IP \
|
||||||
|
-f 1400 \
|
||||||
|
-k '60 300' \
|
||||||
|
-e "$MULTILINE_EXTRA_SERVER_CONF" \
|
||||||
|
-e 'duplicate-cn' \
|
||||||
|
-e 'topology subnet' \
|
||||||
|
-p 'route 172.22.22.0 255.255.255.0' \
|
||||||
|
|
||||||
|
# Run ovpn_genconfig a second time with no arguments to test its repeatability.
|
||||||
|
ovpn_genconfig
|
||||||
|
|
||||||
#
|
#
|
||||||
# grep for config lines from openvpn.conf
|
# Simple test cases
|
||||||
# add more tests for more configs as required
|
|
||||||
#
|
#
|
||||||
|
|
||||||
# 1. verb config
|
# 1. verb config
|
||||||
CONFIG_REQUIRED_VERB="verb 3"
|
test_config "${SERVER_CONF}" "^verb\s\+3"
|
||||||
CONFIG_MATCH_VERB=$(busybox grep verb /etc/openvpn/openvpn.conf)
|
|
||||||
|
|
||||||
# 2. fragment config
|
# 2. fragment config
|
||||||
CONFIG_REQUIRED_FRAGMENT="fragment 1400"
|
test_config "${SERVER_CONF}" "^fragment\s\+1400"
|
||||||
CONFIG_MATCH_FRAGMENT=$(busybox grep fragment /etc/openvpn/openvpn.conf)
|
|
||||||
|
|
||||||
## Tests for extra configs
|
## Tests for extra configs
|
||||||
# 3. management config
|
# 3. management config
|
||||||
CONFIG_REQUIRED_MANAGEMENT="^management localhost 7505"
|
test_config "${SERVER_CONF}" "^management\s\+localhost\s\+7505"
|
||||||
CONFIG_MATCH_MANAGEMENT=$(busybox grep management /etc/openvpn/openvpn.conf)
|
|
||||||
|
|
||||||
# 4. max-clients config
|
# 4. max-clients config
|
||||||
CONFIG_REQUIRED_MAX_CLIENTS="^max-clients 10"
|
test_config "${SERVER_CONF}" "^max-clients\s\+10"
|
||||||
CONFIG_MATCH_MAX_CLIENTS=$(busybox grep max-clients /etc/openvpn/openvpn.conf)
|
|
||||||
|
|
||||||
# 5. duplicate-cn config
|
# 5. duplicate-cn config
|
||||||
CONFIG_REQUIRED_DUPCN="^duplicate-cn"
|
test_config "${SERVER_CONF}" "^duplicate-cn"
|
||||||
CONFIG_MATCH_DUPCN=$(busybox grep duplicate-cn /etc/openvpn/openvpn.conf)
|
|
||||||
|
|
||||||
# 6. topology config
|
# 6. topology config
|
||||||
CONFIG_REQUIRED_TOPOLOGY="^topology subnet"
|
test_config "${SERVER_CONF}" "^topology\s\+subnet"
|
||||||
CONFIG_MATCH_TOPOLOGY=$(busybox grep 'topology subnet' /etc/openvpn/openvpn.conf)
|
|
||||||
|
|
||||||
## Tests for push config
|
## Tests for push config
|
||||||
# 7. push route
|
# 7. push route
|
||||||
CONFIG_REQUIRED_PUSH_ROUTE="^push route 172.22.22.0 255.255.255.0"
|
test_config "${SERVER_CONF}" '^push\s\+"route\s\+172.22.22.0\s\+255.255.255.0"'
|
||||||
CONFIG_MATCH_PUSH_ROUTE=$(busybox grep 'push route 172.22.22.0 255.255.255.0' /etc/openvpn/openvpn.conf)
|
|
||||||
|
|
||||||
## Test for default
|
## Test for default
|
||||||
# 8. Should see default route if none provided
|
# 8. Should see default route if none provided
|
||||||
CONFIG_REQUIRED_DEFAULT_ROUTE="^route 192.168.254.0 255.255.255.0"
|
test_config "${SERVER_CONF}" "^route\s\+192.168.254.0\s\+255.255.255.0"
|
||||||
CONFIG_MATCH_DEFAULT_ROUTE=$(busybox grep 'route 192.168.254.0 255.255.255.0' /etc/openvpn/openvpn.conf)
|
|
||||||
|
|
||||||
# 9. Should see a push of 'block-outside-dns' by default
|
# 9. Should see a push of 'block-outside-dns' by default
|
||||||
CONFIG_REQUIRED_DEFAULT_ROUTE="^push block-outside-dns"
|
test_config "${SERVER_CONF}" '^push\s\+"block-outside-dns"'
|
||||||
CONFIG_MATCH_DEFAULT_ROUTE=$(busybox grep 'push block-outside-dns' /etc/openvpn/openvpn.conf)
|
|
||||||
|
|
||||||
# 10. Should see a push of 'dhcp-option DNS' by default
|
# 10. Should see a push of 'dhcp-option DNS' by default
|
||||||
CONFIG_REQUIRED_DEFAULT_DNS_1="^push dhcp-option DNS 8.8.8.8"
|
test_config "${SERVER_CONF}" '^push\s\+"dhcp-option\s\+DNS\s\+8.8.8.8"'
|
||||||
CONFIG_MATCH_DEFAULT_DNS_1=$(busybox grep 'push dhcp-option DNS 8.8.8.8' /etc/openvpn/openvpn.conf)
|
test_config "${SERVER_CONF}" '^push\s\+"dhcp-option\s\+DNS\s\+8.8.4.4"'
|
||||||
CONFIG_REQUIRED_DEFAULT_DNS_2="^push dhcp-option DNS 8.8.4.4"
|
|
||||||
CONFIG_MATCH_DEFAULT_DNS_2=$(busybox grep 'push dhcp-option DNS 8.8.4.4' /etc/openvpn/openvpn.conf)
|
## Test for keepalive
|
||||||
|
# 11. keepalive config
|
||||||
|
test_config "${SERVER_CONF}" '^keepalive\s\+60\s\+300'
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Tests
|
# More elaborate route tests
|
||||||
#
|
#
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_VERB =~ $CONFIG_REQUIRED_VERB ]]
|
|
||||||
then
|
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_VERB == $CONFIG_MATCH_VERB"
|
|
||||||
else
|
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_VERB != $CONFIG_MATCH_VERB"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_FRAGMENT =~ $CONFIG_REQUIRED_FRAGMENT ]]
|
|
||||||
then
|
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_FRAGMENT == $CONFIG_MATCH_FRAGMENT"
|
|
||||||
else
|
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_FRAGMENT != $CONFIG_MATCH_FRAGMENT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_MANAGEMENT =~ $CONFIG_REQUIRED_MANAGEMENT ]]
|
|
||||||
then
|
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_MANAGEMENT == $CONFIG_MATCH_MANAGEMENT"
|
|
||||||
else
|
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_MANAGEMENT != $CONFIG_MATCH_MANAGEMENT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_MAX_CLIENTS =~ $CONFIG_REQUIRED_MAX_CLIENTS ]]
|
|
||||||
then
|
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_MAX_CLIENTS == $CONFIG_MATCH_MAX_CLIENTS"
|
|
||||||
else
|
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_MAX_CLIENTS != $CONFIG_MATCH_MAX_CLIENTS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_DUPCN =~ $CONFIG_REQUIRED_DUPCN ]]
|
|
||||||
then
|
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_DUPCN == $CONFIG_MATCH_DUPCN"
|
|
||||||
else
|
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_DUPCN != $CONFIG_MATCH_DUPCN"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_TOPOLOGY =~ $CONFIG_REQUIRED_TOPOLOGY ]]
|
|
||||||
then
|
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_TOPOLOGY == $CONFIG_MATCH_TOPOLOGY"
|
|
||||||
else
|
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_TOPOLOGY != $CONFIG_MATCH_TOPOLOGY"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_PUSH_ROUTE =~ $CONFIG_REQUIRED_PUSH_ROUTE ]]
|
|
||||||
then
|
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_PUSH_ROUTE == $CONFIG_MATCH_PUSH_ROUTE"
|
|
||||||
else
|
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_PUSH_ROUTE != $CONFIG_MATCH_PUSH_ROUTE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_DEFAULT_ROUTE =~ $CONFIG_REQUIRED_DEFAULT_ROUTE ]]
|
|
||||||
then
|
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_DEFAULT_ROUTE == $CONFIG_MATCH_DEFAULT_ROUTE"
|
|
||||||
else
|
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_DEFAULT_ROUTE != $CONFIG_MATCH_DEFAULT_ROUTE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_DEFAULT_DNS_1 =~ $CONFIG_REQUIRED_DEFAULT_DNS_1 ]]
|
|
||||||
then
|
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_DEFAULT_DNS_1 == $CONFIG_MATCH_DEFAULT_DNS_1"
|
|
||||||
else
|
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_DEFAULT_DNS_1 != $CONFIG_MATCH_DEFAULT_DNS_1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_DEFAULT_DNS_2 =~ $CONFIG_REQUIRED_DEFAULT_DNS_2 ]]
|
|
||||||
then
|
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_DEFAULT_DNS_2 == $CONFIG_MATCH_DEFAULT_DNS_2"
|
|
||||||
else
|
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_DEFAULT_DNS_2 != $CONFIG_MATCH_DEFAULT_DNS_2"
|
|
||||||
fi
|
|
||||||
|
|
||||||
SERV_IP=$(ip -4 -o addr show scope global | awk '{print $4}' | sed -e 's:/.*::' | head -n1)
|
|
||||||
ovpn_genconfig -u udp://$SERV_IP -r "172.33.33.0/24" -r "172.34.34.0/24"
|
ovpn_genconfig -u udp://$SERV_IP -r "172.33.33.0/24" -r "172.34.34.0/24"
|
||||||
|
|
||||||
CONFIG_REQUIRED_ROUTE_1="^route 172.33.33.0 255.255.255.0"
|
test_config "${SERVER_CONF}" "^route\s\+172.33.33.0\s\+255.255.255.0"
|
||||||
CONFIG_MATCH_ROUTE_1=$(busybox grep 'route 172.33.33.0 255.255.255.0' /etc/openvpn/openvpn.conf)
|
test_config "${SERVER_CONF}" "^route\s\+172.34.34.0\s\+255.255.255.0"
|
||||||
|
|
||||||
CONFIG_REQUIRED_ROUTE_2="^route 172.34.34.0 255.255.255.0"
|
|
||||||
CONFIG_MATCH_ROUTE_2=$(busybox grep 'route 172.34.34.0 255.255.255.0' /etc/openvpn/openvpn.conf)
|
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_ROUTE_1 =~ $CONFIG_REQUIRED_ROUTE_1 ]]
|
#
|
||||||
then
|
# Block outside DNS test
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_ROUTE_1 == $CONFIG_MATCH_ROUTE_1"
|
#
|
||||||
else
|
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_ROUTE_1 != $CONFIG_MATCH_ROUTE_1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $CONFIG_MATCH_ROUTE_2 =~ $CONFIG_REQUIRED_ROUTE_2 ]]
|
ovpn_genconfig -u udp://$SERV_IP -b
|
||||||
then
|
|
||||||
echo "==> Config match found: $CONFIG_REQUIRED_ROUTE_2 == $CONFIG_MATCH_ROUTE_2"
|
test_not_config "${SERVER_CONF}" '^push "block-outside-dns"'
|
||||||
else
|
cat ${SERVER_CONF} >&1
|
||||||
abort "==> Config match not found: $CONFIG_REQUIRED_ROUTE_2 != $CONFIG_MATCH_ROUTE_2"
|
|
||||||
fi
|
|
||||||
|
38
test/tests/iptables/run.sh
Executable file
38
test/tests/iptables/run.sh
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
[ -n "${DEBUG+x}" ] && set -x
|
||||||
|
OVPN_DATA=basic-data
|
||||||
|
IMG="kylemanna/openvpn"
|
||||||
|
NAME="ovpn-test"
|
||||||
|
SERV_IP=$(ip -4 -o addr show scope global | awk '{print $4}' | sed -e 's:/.*::' | head -n1)
|
||||||
|
|
||||||
|
# generate server config including iptables nat-ing
|
||||||
|
docker volume create --name $OVPN_DATA
|
||||||
|
docker run --rm -v $OVPN_DATA:/etc/openvpn $IMG ovpn_genconfig -u udp://$SERV_IP -N
|
||||||
|
docker run -v $OVPN_DATA:/etc/openvpn --rm -it -e "EASYRSA_BATCH=1" -e "EASYRSA_REQ_CN=Travis-CI Test CA" $IMG ovpn_initpki nopass
|
||||||
|
|
||||||
|
# Fire up the server
|
||||||
|
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'
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
docker exec -ti $NAME bash -c 'source /etc/openvpn/ovpn_env.sh; type -t setupIptablesAndRouting && iptables -t nat -C POSTROUTING -m comment --comment "test"'
|
||||||
|
|
||||||
|
#
|
||||||
|
# kill server
|
||||||
|
#
|
||||||
|
|
||||||
|
docker kill $NAME
|
||||||
|
docker rm $NAME
|
||||||
|
docker volume rm $OVPN_DATA
|
@@ -17,6 +17,9 @@ SERV_IP=$(ip -4 -o addr show scope global | awk '{print $4}' | sed -e 's:/.*::'
|
|||||||
# Configure server with two factor authentication
|
# Configure server with two factor authentication
|
||||||
docker run -v $OVPN_DATA:/etc/openvpn --rm $IMG ovpn_genconfig -u udp://$SERV_IP -2
|
docker run -v $OVPN_DATA:/etc/openvpn --rm $IMG ovpn_genconfig -u udp://$SERV_IP -2
|
||||||
|
|
||||||
|
# Ensure reneg-sec 0 in server config when two factor is enabled
|
||||||
|
docker run -v $OVPN_DATA:/etc/openvpn --rm $IMG cat /etc/openvpn/openvpn.conf | grep 'reneg-sec 0' || abort 'reneg-sec not set to 0 in server config'
|
||||||
|
|
||||||
# nopass is insecure
|
# nopass is insecure
|
||||||
docker run -v $OVPN_DATA:/etc/openvpn --rm -it -e "EASYRSA_BATCH=1" -e "EASYRSA_REQ_CN=Travis-CI Test CA" $IMG ovpn_initpki nopass
|
docker run -v $OVPN_DATA:/etc/openvpn --rm -it -e "EASYRSA_BATCH=1" -e "EASYRSA_REQ_CN=Travis-CI Test CA" $IMG ovpn_initpki nopass
|
||||||
|
|
||||||
@@ -40,6 +43,9 @@ echo -e "$OTP_USER\n$OTP_TOKEN" > $CLIENT_DIR/credentials.txt
|
|||||||
# Override the auth-user-pass directive to use a credentials file
|
# Override the auth-user-pass directive to use a credentials file
|
||||||
docker run -v $OVPN_DATA:/etc/openvpn --rm $IMG ovpn_getclient $CLIENT | sed 's/auth-user-pass/auth-user-pass \/client\/credentials.txt/' | tee $CLIENT_DIR/config.ovpn
|
docker run -v $OVPN_DATA:/etc/openvpn --rm $IMG ovpn_getclient $CLIENT | sed 's/auth-user-pass/auth-user-pass \/client\/credentials.txt/' | tee $CLIENT_DIR/config.ovpn
|
||||||
|
|
||||||
|
# Ensure reneg-sec 0 in client config when two factor is enabled
|
||||||
|
grep 'reneg-sec 0' $CLIENT_DIR/config.ovpn || abort 'reneg-sec not set to 0 in client config'
|
||||||
|
|
||||||
#
|
#
|
||||||
# Fire up the server
|
# Fire up the server
|
||||||
#
|
#
|
||||||
|
101
test/tests/revocation/run.sh
Executable file
101
test/tests/revocation/run.sh
Executable file
@@ -0,0 +1,101 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
[ -n "${DEBUG+x}" ] && set -x
|
||||||
|
|
||||||
|
OVPN_DATA="basic-data"
|
||||||
|
CLIENT1="travis-client1"
|
||||||
|
CLIENT2="travis-client2"
|
||||||
|
IMG="kylemanna/openvpn"
|
||||||
|
NAME="ovpn-test"
|
||||||
|
CLIENT_DIR="$(readlink -f "$(dirname "$BASH_SOURCE")/../../client")"
|
||||||
|
SERV_IP="$(ip -4 -o addr show scope global | awk '{print $4}' | sed -e 's:/.*::' | head -n1)"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Initialize openvpn configuration and pki.
|
||||||
|
#
|
||||||
|
docker volume create --name $OVPN_DATA
|
||||||
|
docker run --rm -v $OVPN_DATA:/etc/openvpn $IMG ovpn_genconfig -u udp://$SERV_IP
|
||||||
|
docker run --rm -v $OVPN_DATA:/etc/openvpn -it -e "EASYRSA_BATCH=1" -e "EASYRSA_REQ_CN=Travis-CI Test CA" $IMG ovpn_initpki nopass
|
||||||
|
|
||||||
|
#
|
||||||
|
# Fire up the server.
|
||||||
|
#
|
||||||
|
sudo iptables -N DOCKER || echo 'Firewall already configured'
|
||||||
|
sudo iptables -I FORWARD 1 -j DOCKER
|
||||||
|
docker run -d -v $OVPN_DATA:/etc/openvpn --cap-add=NET_ADMIN --privileged -p 1194:1194/udp --name $NAME $IMG
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test that easy_rsa generate CRLs with 'next publish' set to 3650 days.
|
||||||
|
#
|
||||||
|
crl_next_update="$(docker exec $NAME openssl crl -nextupdate -noout -in /etc/openvpn/crl.pem | cut -d'=' -f2 | tr -d 'GMT')"
|
||||||
|
crl_next_update="$(date -u -d "$crl_next_update" "+%s")"
|
||||||
|
now="$(docker exec $NAME date "+%s")"
|
||||||
|
crl_remain="$(( $crl_next_update - $now ))"
|
||||||
|
crl_remain="$(( $crl_remain / 86400 ))"
|
||||||
|
if (( $crl_remain < 3649 )); then
|
||||||
|
echo "easy_rsa CRL next publish set to less than 3650 days." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate a first client certificate and configuration using $CLIENT1 as CN then revoke it.
|
||||||
|
#
|
||||||
|
docker exec -it $NAME easyrsa build-client-full $CLIENT1 nopass
|
||||||
|
docker exec -it $NAME ovpn_getclient $CLIENT1 > $CLIENT_DIR/config.ovpn
|
||||||
|
docker exec -it $NAME bash -c "echo 'yes' | ovpn_revokeclient $CLIENT1 remove"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test that openvpn client can't connect using $CLIENT1 config.
|
||||||
|
#
|
||||||
|
if docker run --rm -v $CLIENT_DIR:/client --cap-add=NET_ADMIN --privileged --net=host $IMG /client/wait-for-connect.sh; then
|
||||||
|
echo "Client was able to connect after revocation test #1." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate and revoke a second client certificate using $CLIENT2 as CN, then test for failed client connection.
|
||||||
|
#
|
||||||
|
docker exec -it $NAME easyrsa build-client-full $CLIENT2 nopass
|
||||||
|
docker exec -it $NAME ovpn_getclient $CLIENT2 > $CLIENT_DIR/config.ovpn
|
||||||
|
docker exec -it $NAME bash -c "echo 'yes' | ovpn_revokeclient $CLIENT2 remove"
|
||||||
|
|
||||||
|
if docker run --rm -v $CLIENT_DIR:/client --cap-add=NET_ADMIN --privileged --net=host $IMG /client/wait-for-connect.sh; then
|
||||||
|
echo "Client was able to connect after revocation test #2." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Restart the server
|
||||||
|
#
|
||||||
|
docker stop $NAME && docker start $NAME
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test for failed connection using $CLIENT2 config again.
|
||||||
|
#
|
||||||
|
if docker run --rm -v $CLIENT_DIR:/client --cap-add=NET_ADMIN --privileged --net=host $IMG /client/wait-for-connect.sh; then
|
||||||
|
echo "Client was able to connect after revocation test #3." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Stop the server and clean up
|
||||||
|
#
|
||||||
|
docker kill $NAME && docker rm $NAME
|
||||||
|
docker volume rm $OVPN_DATA
|
||||||
|
sudo iptables -D FORWARD 1
|
||||||
|
|
||||||
|
#
|
||||||
|
# Celebrate
|
||||||
|
#
|
||||||
|
cat <<EOF
|
||||||
|
___________
|
||||||
|
< it worked >
|
||||||
|
-----------
|
||||||
|
\ ^__^
|
||||||
|
\ (oo)\_______
|
||||||
|
(__)\ )\/\\
|
||||||
|
||----w |
|
||||||
|
|| ||
|
||||||
|
EOF
|
Reference in New Issue
Block a user