diff --git a/.dockerignore b/.dockerignore index 66f2881..19f07ef 100644 --- a/.dockerignore +++ b/.dockerignore @@ -20,7 +20,6 @@ openvpn-admin ovpn-admin docker-compose.yaml -docker-compose-slave.yaml img dashboard .helm diff --git a/.gitignore b/.gitignore index 3894d1c..5dbe4c6 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ packrd/ *.njsproj *.sln .env +nginx/default.conf diff --git a/docker-compose-slave.yaml b/docker-compose-slave.yaml deleted file mode 100644 index a7e253b..0000000 --- a/docker-compose-slave.yaml +++ /dev/null @@ -1,30 +0,0 @@ -version: '3' - -services: - openvpn: - build: - context: . - dockerfile: Dockerfile.openvpn - image: openvpn:local - command: /etc/openvpn/setup/configure.sh - environment: - - OVPN_ROLE=slave - cap_add: - - NET_ADMIN - ports: - - 7778:1194 # for openvpn - - 8081:8080 # for ovpn-admin because of network_mode - volumes: - - ./easyrsa_slave:/etc/openvpn/easyrsa - - ./ccd_slave:/etc/openvpn/ccd - ovpn-admin: - build: - context: . - image: ovpn-admin:local - command: /app/ovpn-admin --debug --ovpn.network="172.16.100.0/22" --master.sync-token="TOKEN" --master.host="http://172.20.0.1:8080" --role="slave" --ovpn.server="127.0.0.1:7777:tcp" --ovpn.server="127.0.0.1:7778:tcp" --easyrsa.path="/mnt/easyrsa" --easyrsa.index-path="/mnt/easyrsa/pki/index.txt" - environment: - - OVPN_SLAVE=1 - network_mode: service:openvpn - volumes: - - ./easyrsa_slave:/mnt/easyrsa - - ./ccd_slave:/mnt/ccd diff --git a/docker-compose.yaml b/docker-compose.yaml index dc9fd70..db93ef2 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -8,17 +8,20 @@ services: image: openvpn:local command: /etc/openvpn/setup/configure.sh environment: - OVPN_SERVER_NET: "192.168.100.0" - OVPN_SERVER_MASK: "255.255.255.0" - OVPN_PASSWD_AUTH: "true" + OVPN_SERVER_NET: ${OVPN_SERVER_NET} + OVPN_SERVER_MASK: ${OVPN_SERVER_MASK} + OVPN_PASSWD_AUTH: "false" cap_add: - NET_ADMIN ports: - - 7777:1194 # for openvpn - - 8080:8080 # for ovpn-admin because of network_mode + - ${OVPN_PORT}:1194/${OVPN_PROTOCOL} volumes: - ./easyrsa_master:/etc/openvpn/easyrsa - ./ccd_master:/etc/openvpn/ccd + - ./ovpn_config:/etc/openvpn/config + networks: + ovpn-net: + ipv4_address: ${OVPN_SERVER_IP} ovpn-admin: build: context: . @@ -27,16 +30,35 @@ services: environment: OVPN_DEBUG: "true" OVPN_VERBOSE: "true" - OVPN_NETWORK: "192.168.100.0/24" + OVPN_NETWORK: ${OVPN_ADMIN_OVPN_NETWORK} OVPN_CCD: "true" OVPN_CCD_PATH: "/mnt/ccd" EASYRSA_PATH: "/mnt/easyrsa" - OVPN_SERVER: "127.0.0.1:7777:tcp" + OVPN_SERVER: ${OVPN_PUBLIC_IP}:${OVPN_PORT}:${OVPN_PROTOCOL} OVPN_INDEX_PATH: "/mnt/easyrsa/pki/index.txt" - OVPN_AUTH: "true" + OVPN_AUTH: "false" OVPN_AUTH_DB_PATH: "/mnt/easyrsa/pki/users.db" - LOG_LEVEL: "debug" - network_mode: service:openvpn + LOG_LEVEL: "warn" + networks: + ovpn-net: + ipv4_address: ${OVPN_ADMIN_IP} volumes: - ./easyrsa_master:/mnt/easyrsa - ./ccd_master:/mnt/ccd + ovpn-nginx: + image: nginx:latest + container_name: nginx + networks: + ovpn-net: + ipv4_address: ${OVPN_NGINX_IP} + ports: + - ${OVPN_NGINX_PORT}:8088 + volumes: + - ./nginx/.htpasswd:/etc/nginx/.htpasswd:ro + - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro +networks: + ovpn-net: + ipam: + driver: default + config: + - subnet: ${OVPN_NET_SUBNET} diff --git a/nginx/default.conf.tpl b/nginx/default.conf.tpl new file mode 100644 index 0000000..49a53ca --- /dev/null +++ b/nginx/default.conf.tpl @@ -0,0 +1,16 @@ +server { +listen 8088; +server_name 127.0.0.1; + + location / { + auth_basic "Pass"; + auth_basic_user_file /etc/nginx/.htpasswd; + proxy_pass http://${OVPN_ADMIN_IP}:8080; + + # Disable caching of credentials + add_header Cache-Control "no-store, private, no-cache, must-revalidate, max-age=0"; + add_header Pragma "no-cache"; + add_header Expires "Thu, 01 Jan 1970 00:00:00 GMT"; + + } +} diff --git a/ovpn_config/openvpn.conf b/ovpn_config/openvpn.conf new file mode 100644 index 0000000..5ff5470 --- /dev/null +++ b/ovpn_config/openvpn.conf @@ -0,0 +1,29 @@ +verb 3 +tls-server +ca /etc/openvpn/easyrsa/pki/ca.crt +key /etc/openvpn/easyrsa/pki/private/server.key +cert /etc/openvpn/easyrsa/pki/issued/server.crt +dh /etc/openvpn/easyrsa/pki/dh.pem +crl-verify /etc/openvpn/easyrsa/pki/crl.pem +tls-auth /etc/openvpn/easyrsa/pki/ta.key +key-direction 0 +cipher AES-128-CBC +management 127.0.0.1 8989 +keepalive 10 60 +persist-key +persist-tun +topology subnet +#duplicate-cn +proto udp +port 1194 +dev tun0 +status /tmp/openvpn-status.log +user nobody +group nogroup +push "topology subnet" +push "route-metric 9999" +push "dhcp-option DNS ${OVPN_DNS_SERVER_IP}" +push "tun-mtu ${OPVN_VPN_MTU}" +tun-mtu ${OPVN_VPN_MTU} +push "redirect-gateway def1" +push "route ${OVPN_VPN_IGNORE_ROUTE_IP} ${OVPN_VPN_IGNORE_ROUTE_MASK} net_gateway" diff --git a/reconfigure.sh b/reconfigure.sh new file mode 100755 index 0000000..1e0d848 --- /dev/null +++ b/reconfigure.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +if [ ! -f .env ]; then + echo "Please create a .env file" + exit 1 +fi + +source .env + + +envsubst < ./nginx/default.conf.tpl > ./nginx/default.conf diff --git a/setup/configure.sh b/setup/configure.sh index a9299a5..8faaffb 100644 --- a/setup/configure.sh +++ b/setup/configure.sh @@ -39,7 +39,13 @@ if [ ! -c /dev/net/tun ]; then mknod /dev/net/tun c 10 200 fi -cp -f /etc/openvpn/setup/openvpn.conf /etc/openvpn/openvpn.conf +if [ -f "/etc/openvpn/config/openvpn.conf" ]; then + target_config="/etc/openvpn/config/openvpn.conf" +else + target_config="/etc/openvpn/setup/openvpn.conf" +fi + +cp -f "$target_config" /etc/openvpn/openvpn.conf if [ ${OVPN_PASSWD_AUTH} = "true" ]; then mkdir -p /etc/openvpn/scripts/ @@ -56,4 +62,4 @@ fi mkdir -p /etc/openvpn/ccd -openvpn --config /etc/openvpn/openvpn.conf --client-config-dir /etc/openvpn/ccd --port 1194 --proto tcp --management 127.0.0.1 8989 --dev tun0 --server ${OVPN_SRV_NET} ${OVPN_SRV_MASK} +openvpn --config /etc/openvpn/openvpn.conf --client-config-dir /etc/openvpn/ccd --server ${OVPN_SRV_NET} ${OVPN_SRV_MASK} diff --git a/start-with-slave.sh b/start-with-slave.sh deleted file mode 100755 index 683eb67..0000000 --- a/start-with-slave.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash - -./start.sh -docker-compose -p openvpn-slave -f docker-compose-slave.yaml up -d diff --git a/start.d/internal_dns.sh b/start.d/internal_dns.sh new file mode 100644 index 0000000..aa40667 --- /dev/null +++ b/start.d/internal_dns.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -ex + +dns_container_id="$(docker ps | grep "$OVPN_DNS_CONTAINER_NAME_PATTERN" | awk '{ print $1 }' 2> /dev/null)" +if [ "$dns_container_id" != "" ]; then + echo "Connecting network 'vpnet' to $dns_container_id" + docker network connect vpnet "$dns_container_id" +fi diff --git a/start.d/secondary_ip_route.sh b/start.d/secondary_ip_route.sh new file mode 100644 index 0000000..3ea1d74 --- /dev/null +++ b/start.d/secondary_ip_route.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -ex + +default_iface=$(ip route | grep default | awk '{print $5}') +iptables -t nat -I POSTROUTING -s "$OVPN_NET_SUBNET" -o "$default_iface" -j SNAT --to-source "$OVPN_PUBLIC_IP" diff --git a/start.sh b/start.sh index 4715df8..fbcced9 100755 --- a/start.sh +++ b/start.sh @@ -1,3 +1,16 @@ #!/usr/bin/env bash -docker compose -p openvpn-master up -d --build +if [ ! -f .env ]; then + echo "Please create a .env file" + exit 1 +fi + +source .env + +for script_file in ./start.d/*.sh +do + echo "Sourcing ${script_file}" + source "${script_file}" +done + +docker compose -p "$OVPN_COMPOSE_NAME" up -d --force-recreate --always-recreate-deps "$@" diff --git a/stop.d/internal_dns.sh b/stop.d/internal_dns.sh new file mode 100644 index 0000000..5dce0e7 --- /dev/null +++ b/stop.d/internal_dns.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -ex + +dns_container_id="$(docker ps | grep "$OVPN_DNS_CONTAINER_NAME_PATTERN" | awk '{ print $1 }' 2> /dev/null)" +if [ "$dns_container_id" != "" ]; then + echo "Disconnecting network 'vpnet' from $dns_container_id" + docker network disconnect vpnet "$dns_container_id" +fi diff --git a/stop.d/secondary_ip_route.sh b/stop.d/secondary_ip_route.sh new file mode 100644 index 0000000..3ea1d74 --- /dev/null +++ b/stop.d/secondary_ip_route.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -ex + +default_iface=$(ip route | grep default | awk '{print $5}') +iptables -t nat -I POSTROUTING -s "$OVPN_NET_SUBNET" -o "$default_iface" -j SNAT --to-source "$OVPN_PUBLIC_IP" diff --git a/stop.sh b/stop.sh new file mode 100755 index 0000000..e439a84 --- /dev/null +++ b/stop.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +if [ ! -f .env ]; then + echo "Please create a .env file" + exit 1 +fi + +source .env + +docker compose -p "$OVPN_COMPOSE_NAME" down "$@" + +for script_file in ./start.d/*.sh +do + echo "Sourcing ${script_file}" + source "${script_file}" +done