diff options
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | images/obfsvpn/Dockerfile | 40 | ||||
-rw-r--r-- | images/obfsvpn/README.md | 31 | ||||
-rw-r--r-- | images/obfsvpn/config/client.ovpn | 18 | ||||
-rw-r--r-- | images/obfsvpn/config/server.conf | 26 | ||||
-rw-r--r-- | images/obfsvpn/scripts/functions.sh | 45 | ||||
-rwxr-xr-x | images/obfsvpn/scripts/start.sh | 101 | ||||
-rwxr-xr-x | images/obfsvpn/scripts/start_obfs4.sh | 10 |
8 files changed, 278 insertions, 0 deletions
@@ -1,5 +1,7 @@ OBFS4_ENDPOINT ?= OBFS4_CERT ?= +TAG ?= 0.1 +OBFSVPN_IMAGE_NAME ?= leap/obfsvpn-test-server certs: curl -k https://black.riseup.net/ca.crt > /tmp/ca.crt @@ -45,3 +47,8 @@ test: check-yawning-obfs4: ./scripts/check-go-modules.sh + +obfsvpn-server-container: + docker build -t ${OBFSVPN_IMAGE_NAME}:${TAG} -f images/obfsvpn/Dockerfile \ + . --no-cache + diff --git a/images/obfsvpn/Dockerfile b/images/obfsvpn/Dockerfile new file mode 100644 index 0000000..9a779a3 --- /dev/null +++ b/images/obfsvpn/Dockerfile @@ -0,0 +1,40 @@ +FROM golang:1.17 AS build + +ENV SOURCE_PATH ${GOPATH}/src/0xacab.org/leap/obfsvpn +COPY . ${SOURCE_PATH}/ +WORKDIR ${SOURCE_PATH} +RUN cd server && make build && cp server /obfsvpn-server + + +FROM alpine:3.14.1 + +ENV APP_NAME Dockovpn +ENV APP_INSTALL_PATH /opt/${APP_NAME} +ENV APP_PERSIST_DIR /opt/${APP_NAME}_data +ENV OBFS4_DATA_DIR /opt/obfsvpn-server-data +ENV PROTO tcp +ENV PORT 5540 + +ENV OBFS4_HOST 0.0.0.0 +ENV OBFS4_PORT 4430 + +WORKDIR ${APP_INSTALL_PATH} + +RUN apk add --no-cache openvpn easy-rsa bash netcat-openbsd zip dumb-init + +COPY --from=build /obfsvpn-server . + +COPY images/obfsvpn/scripts . +COPY images/obfsvpn/config ./config +COPY server/test_data ./obfsvpn-server-data + +RUN mkdir -p ${APP_PERSIST_DIR} && \ + cd ${APP_INSTALL_PATH} && \ + cp config/server.conf /etc/openvpn/server.conf + +EXPOSE 5540/tcp + +VOLUME [ "/opt/Dockovpn_data" ] + +ENTRYPOINT [ "dumb-init", "./start.sh" ] +CMD [ "" ] diff --git a/images/obfsvpn/README.md b/images/obfsvpn/README.md new file mode 100644 index 0000000..5338513 --- /dev/null +++ b/images/obfsvpn/README.md @@ -0,0 +1,31 @@ +## Dockerized obfs4 and openvpn in a single container + +This is based on the [dockovpn/docker-openvpn](https://github.com/dockovpn/docker-openvpn) repository, it adds the `obfsvpn-server` +binary and the required config files to start an instance of the server targetting the +`openvpn` server running at port 5540 (default) + +A directory can be bind mounted to `/opt/Dockovpn_data` to persist the configurations of the +`openvpn` server and additionally to copy out the `client.ovpn` file created at `/opt/Dockovpn/client/<client-id>/client.ovpn` + +The container recognises the following environment variables and can be used to override the +default values: + +``` +OBFS4_HOST = 0.0.0.0 (default) # This is the OBFS4 server endpoint +OBFS4_PORT = 4430 +HOST_ADDR = localhost # openvpn gateway ip +PORT = 5540 # openvpn GW port +PROTO = tcp # openvpn proto +``` + +### To test locally + +``` +$ make obfsvpn-server-container +``` + +Then run the container using the following command: + +``` +$ docker run -it --rm --privileged -p 4430:4430/tcp leap/obfsvpn:0.1 +``` diff --git a/images/obfsvpn/config/client.ovpn b/images/obfsvpn/config/client.ovpn new file mode 100644 index 0000000..ae5db3a --- /dev/null +++ b/images/obfsvpn/config/client.ovpn @@ -0,0 +1,18 @@ +client +dev tun +proto __PROTO__ +resolv-retry infinite +nobind +persist-key +persist-tun +cipher AES-256-GCM +auth SHA512 +verb 3 +tls-client +tls-version-min 1.2 +key-direction 1 +remote-cert-tls server +;remote localhost 1194 +;ca ca.crt +;cert client.crt +;key client.key diff --git a/images/obfsvpn/config/server.conf b/images/obfsvpn/config/server.conf new file mode 100644 index 0000000..cbafe6c --- /dev/null +++ b/images/obfsvpn/config/server.conf @@ -0,0 +1,26 @@ +port __PORT__ +proto __PROTO__ +dev tun +ca /etc/openvpn/ca.crt +cert /etc/openvpn/MyReq.crt +key /etc/openvpn/MyReq.key +dh /etc/openvpn/dh.pem +server 10.8.0.0 255.255.255.0 +ifconfig-pool-persist ipp.txt +push "redirect-gateway def1 bypass-dhcp" +push "dhcp-option DNS 208.67.222.222" +push "dhcp-option DNS 208.67.220.220" +duplicate-cn +keepalive 10 120 +cipher AES-256-GCM +ncp-ciphers AES-256-GCM:AES-256-CBC +auth SHA512 +user nobody +group nobody +persist-key +persist-tun +status openvpn-status.log +verb 1 +tls-server +tls-version-min 1.2 +tls-auth /etc/openvpn/ta.key 0 diff --git a/images/obfsvpn/scripts/functions.sh b/images/obfsvpn/scripts/functions.sh new file mode 100644 index 0000000..f00ac38 --- /dev/null +++ b/images/obfsvpn/scripts/functions.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +function datef() { + # Output: + # Sat Jun 8 20:29:08 2019 + date "+%a %b %-d %T %Y" +} + +function createConfig() { + cd "$APP_PERSIST_DIR" + CLIENT_ID="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)" + CLIENT_PATH="$APP_PERSIST_DIR/clients/$CLIENT_ID" + + # Redirect stderr to the black hole + /usr/share/easy-rsa/easyrsa build-client-full "$CLIENT_ID" nopass &> /dev/null + # Writing new private key to '/usr/share/easy-rsa/pki/private/client.key + # Client sertificate /usr/share/easy-rsa/pki/issued/client.crt + # CA is by the path /usr/share/easy-rsa/pki/ca.crt + + mkdir -p $CLIENT_PATH + + cp "pki/private/$CLIENT_ID.key" "pki/issued/$CLIENT_ID.crt" pki/ca.crt /etc/openvpn/ta.key $CLIENT_PATH + + # Set default value to HOST_ADDR if it was not set from environment + if [ -z "$HOST_ADDR" ] + then + HOST_ADDR='localhost' + fi + + cd "$APP_INSTALL_PATH" + cp config/client.ovpn $CLIENT_PATH + + echo -e "\nremote $HOST_ADDR $PORT" >> "$CLIENT_PATH/client.ovpn" + + # Embed client authentication files into config file + cat <(echo -e '<ca>') \ + "$CLIENT_PATH/ca.crt" <(echo -e '</ca>\n<cert>') \ + "$CLIENT_PATH/$CLIENT_ID.crt" <(echo -e '</cert>\n<key>') \ + "$CLIENT_PATH/$CLIENT_ID.key" <(echo -e '</key>\n<tls-auth>') \ + "$CLIENT_PATH/ta.key" <(echo -e '</tls-auth>') \ + >> "$CLIENT_PATH/client.ovpn" + + echo $CLIENT_PATH +} + diff --git a/images/obfsvpn/scripts/start.sh b/images/obfsvpn/scripts/start.sh new file mode 100755 index 0000000..3a3bce5 --- /dev/null +++ b/images/obfsvpn/scripts/start.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +source ./functions.sh + +mkdir -p /dev/net + +if ! [ -c /dev/net/tun ]; then + echo "$(datef) Creating tun/tap device." + mknod /dev/net/tun c 10 200 +fi + +# Following firewall configurations will be needed later on +# for a functional deployment of obfsvpn + # Allow UDP traffic on port 1194. + #iptables -A INPUT -i eth0 -p udp -m state --state NEW,ESTABLISHED --dport 1194 -j ACCEPT + #iptables -A OUTPUT -o eth0 -p udp -m state --state ESTABLISHED --sport 1194 -j ACCEPT + + # Allow traffic on the TUN interface. + #iptables -A INPUT -i tun0 -j ACCEPT + #iptables -A FORWARD -i tun0 -j ACCEPT + #iptables -A OUTPUT -o tun0 -j ACCEPT + + # Allow forwarding traffic only from the VPN. + #iptables -A FORWARD -i tun0 -o eth0 -s 10.8.0.0/24 -j ACCEPT + #iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT + + #iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE + +cd "$APP_PERSIST_DIR" + +LOCKFILE=.gen + +# Regenerate certs only on the first start +if ! [ -f $LOCKFILE ]; then + IS_INITIAL="1" + + /usr/share/easy-rsa/easyrsa init-pki + + # DH parameters of size 2048 created at APP_PERSIST_DIR/pki + /usr/share/easy-rsa/easyrsa gen-dh + + /usr/share/easy-rsa/easyrsa build-ca nopass << EOF + +EOF + # CA creation complete and you may now import and sign cert requests. + # Your new CA certificate file for publishing is at: + # /opt/Dockovpn_data/pki/ca.crt + + /usr/share/easy-rsa/easyrsa gen-req MyReq nopass << EOF2 + +EOF2 + # Keypair and certificate request completed. Your files are: + # req: /opt/Dockovpn_data/pki/reqs/MyReq.req + # key: /opt/Dockovpn_data/pki/private/MyReq.key + + /usr/share/easy-rsa/easyrsa sign-req server MyReq << EOF3 +yes +EOF3 + # Certificate created at: /opt/Dockovpn_data/pki/issued/MyReq.crt + + openvpn --genkey secret ta.key << EOF4 +yes +EOF4 + + touch $LOCKFILE +fi + +# Copy server keys, dh file and certificates +cp pki/dh.pem pki/ca.crt pki/issued/MyReq.crt pki/private/MyReq.key ta.key /etc/openvpn + +# Update proto and port in /etc/openvpn/server.conf +sed -i -e "s/__PROTO__/${PROTO}/g" \ + -e "s/__PORT__/${PORT}/g" /etc/openvpn/server.conf + +# Need to feed key password +openvpn --config /etc/openvpn/server.conf & + +# By some strange reason we need to do echo command to get to the next command +echo " " + +# backoff for openvpn to start +sleep 20 + +# Generate client config +if [[ -n $IS_INITIAL ]]; then + CLIENT_PATH="$(createConfig)" + FILE_NAME=client.ovpn + FILE_PATH="$CLIENT_PATH/$FILE_NAME" + sed -i -e "s/__PROTO__/${PROTO}/g" "${FILE_PATH}" + + echo "$(datef) Created ${FILE_PATH}." + # dirty hack: copy client config to root of APP_PERSIST_DIR + # for reusing in the obfsvpn-client container + cp "${FILE_PATH}" "$APP_PERSIST_DIR/" +fi + +cd "${APP_INSTALL_PATH}" +./start_obfs4.sh & + +tail -f /dev/null + diff --git a/images/obfsvpn/scripts/start_obfs4.sh b/images/obfsvpn/scripts/start_obfs4.sh new file mode 100755 index 0000000..c73f604 --- /dev/null +++ b/images/obfsvpn/scripts/start_obfs4.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ -z "$HOST_ADDR" ] +then + HOST_ADDR='localhost' +fi + +cd "${APP_INSTALL_PATH}" +./obfsvpn-server -addr ${OBFS4_HOST}:${OBFS4_PORT} -vpn ${HOST_ADDR}:${PORT} \ + -state ./obfsvpn-server-data -c ./obfsvpn-server-data/obfs4.json -v |