Kaynağa Gözat

feat(): add openvpn-server, closes #149

Peter Thomassen 5 yıl önce
ebeveyn
işleme
2d96845d6e

+ 10 - 2
README.md

@@ -11,6 +11,7 @@ This is a docker-compose application providing the basic stack for deSEC name se
 - `celery`: A shadow instance of the `api` code for performing asynchronous tasks (email delivery).
 - `rabbitmq`: `celery`'s queue
 - `memcached`: `api`-wide in-memory cache, currently used to keep API throttling state
+- `openvpn-server`: OpenVPN server used to tunnel replication traffic between this stack and frontend DNS slaves.
 
 Requirements
 ------------
@@ -19,9 +20,16 @@ Although most configuration is contained in this repository, some external depen
 
 1.  We run this software with the `--userland-proxy=false` flag of the `dockerd` daemon, and recommend you do the same.
 
-2.  Set up TLS-secured replication of the `nsmaster` database to feed your PowerDNS slaves.
+2.  Set up TLS-secured replication of the `nsmaster` database to feed your PowerDNS slaves. To generate the necessary keys and certificates, follow the instructions at https://dev.mysql.com/doc/refman/5.7/en/creating-ssl-files-using-openssl.html. In the `openssl req -newkey` steps, consider switching to a bigger key size, and add `-subj '/CN=slave.hostname.example'`. (It turned out that StartSSL and Let's Encrypt certificates do not work out of the box.)
 
-    To generate the necessary keys and certificates, follow the instructions at https://dev.mysql.com/doc/refman/5.7/en/creating-ssl-files-using-openssl.html. In the `openssl req -newkey` steps, consider switching to a bigger key size, and add `-subj '/CN=slave.hostname.example'`. (It turned out that StartSSL and Let's Encrypt certificates do not work out of the box.)
+    Also, configure certificates for `openvpn-server`:
+
+    - [Get easy-rsa](https://github.com/OpenVPN/easy-rsa) and follow [this tutorial](https://github.com/OpenVPN/easy-rsa/blob/master/README.quickstart.md).
+    - Then, copy `ca.crt`, `server.crt`, and `server.key` to `openvpn-server/secrets/`.
+    - Create a preshared secret using `openvpn --genkey --secret ta.key` inside `openvpn-server/secrets/`.
+
+    For provisioning a slave, use the same `easy-rsa` PKI and create a new `client.key` and `client.crt` pair. Transfer these securely onto the slave, along with `ca.crt` and `ta.key`.
+    (You can also create the key on the slave and only transfer a certificate signing request and the certificate.) 
 
 3.  Set sensitive information and network topology using environment variables or an `.env` file. You need (you can use the `.env.default` file as a template):
     - global

+ 4 - 0
docker-compose.dev.yml

@@ -73,6 +73,10 @@ services:
     logging:
       driver: "json-file"
 
+  openvpn-server:
+    logging:
+      driver: "json-file"
+
 networks:
   rearwebapp:
     driver: bridge

+ 29 - 0
docker-compose.yml

@@ -152,6 +152,8 @@ services:
     build: nsmaster
     image: desec/dedyn-nsmaster:latest
     init: true
+    cap_add:
+    - NET_ADMIN
     environment:
     - DESECSTACK_IPV4_REAR_PREFIX16
     - DESECSTACK_DBMASTER_PASSWORD_pdns
@@ -164,6 +166,8 @@ services:
       rearapi_ns:
         ipv4_address: ${DESECSTACK_IPV4_REAR_PREFIX16}.1.12
       rearmaster:
+      rearreplication:
+        ipv4_address: ${DESECSTACK_IPV4_REAR_PREFIX16}.7.3
     logging:
       driver: "syslog"
       options:
@@ -247,6 +251,24 @@ services:
         tag: "desec/memcached"
     restart: unless-stopped
 
+  openvpn-server:
+    build: openvpn-server
+    image: desec/openvpn-server:latest
+    init: true
+    cap_add:
+    - NET_ADMIN
+    ports:
+    - "1194:1194/udp"
+    volumes:
+    - ./openvpn-server/secrets:/etc/openvpn/secrets:ro
+    networks:
+      rearreplication:
+        ipv4_address: ${DESECSTACK_IPV4_REAR_PREFIX16}.7.2
+    logging:
+      driver: "syslog"
+      options:
+        tag: "desec/openvpn-server"
+    restart: unless-stopped
 
 volumes:
   dbapi_mysql:
@@ -311,3 +333,10 @@ networks:
       config:
       - subnet: ${DESECSTACK_IPV4_REAR_PREFIX16}.4.0/24
         gateway: ${DESECSTACK_IPV4_REAR_PREFIX16}.4.1
+  rearreplication:
+    driver: bridge
+    ipam:
+      driver: default
+      config:
+      - subnet: ${DESECSTACK_IPV4_REAR_PREFIX16}.7.0/24
+        gateway: ${DESECSTACK_IPV4_REAR_PREFIX16}.7.1

+ 2 - 0
nsmaster/Dockerfile

@@ -21,6 +21,8 @@ RUN set -ex \
 	&& apt-get install -y pdns-server pdns-backend-mysql \
 	# credentials management via envsubst
 	&& apt-get -y install gettext-base \
+	# VPN route
+	&& apt-get -y install iproute2 \
 	&& apt-get clean \
 	&& rm -rf /var/lib/apt/lists/*
 

+ 3 - 0
nsmaster/entrypoint.sh

@@ -1,5 +1,8 @@
 #!/bin/bash
 
+# Route required for communicating with slave NS through VPN
+/sbin/ip route add 10.8.0.0/24 via 172.16.7.2
+
 host=dbmaster; port=3306; n=120; i=0; while ! (echo > /dev/tcp/$host/$port) 2> /dev/null; do [[ $i -eq $n ]] && >&2 echo "$host:$port not up after $n seconds, exiting" && exit 1; echo "waiting for $host:$port to come up"; sleep 1; i=$((i+1)); done
 
 # Manage credentials

+ 1 - 0
openvpn-server/.gitignore

@@ -0,0 +1 @@
+secrets/

+ 12 - 0
openvpn-server/Dockerfile

@@ -0,0 +1,12 @@
+FROM ubuntu:bionic
+
+RUN apt-get update && apt-get install -y \
+		openvpn \
+	--no-install-recommends && apt-get clean && rm -rf /var/lib/apt/lists/*
+
+COPY conf/ /etc/openvpn/
+COPY entrypoint.sh .
+
+VOLUME /etc/openvpn/secrets
+
+CMD ["./entrypoint.sh"]

+ 168 - 0
openvpn-server/conf/server.conf

@@ -0,0 +1,168 @@
+port 1194
+
+proto udp
+
+dev tun
+
+ca /etc/openvpn/secrets/ca.crt
+cert /etc/openvpn/secrets/server.crt
+key /etc/openvpn/secrets/server.key  # This file should be kept secret
+
+tls-version-min 1.3 or-highest
+tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384
+ncp-ciphers AES-256-GCM
+auth SHA256
+dh none
+ecdh-curve secp384r1
+
+remote-cert-tls client
+
+# Network topology
+# Should be subnet (addressing via IP)
+# unless Windows clients v2.0.9 and lower have to
+# be supported (then net30, i.e. a /30 per client)
+# Defaults to net30 (not recommended)
+topology subnet
+
+# Configure server mode and supply a VPN subnet
+# for OpenVPN to draw client addresses from.
+# The server will take 10.8.0.1 for itself,
+# the rest will be made available to clients.
+# Each client will be able to reach the server
+# on 10.8.0.1. Comment this line out if you are
+# ethernet bridging. See the man page for more info.
+server 10.8.0.0 255.255.255.0
+
+# Maintain a record of client <-> virtual IP address
+# associations in this file.  If OpenVPN goes down or
+# is restarted, reconnecting clients can be assigned
+# the same virtual IP address from the pool that was
+# previously assigned.
+ifconfig-pool-persist /var/log/openvpn/ipp.txt
+
+# Configure server mode for ethernet bridging.
+# You must first use your OS's bridging capability
+# to bridge the TAP interface with the ethernet
+# NIC interface.  Then you must manually set the
+# IP/netmask on the bridge interface, here we
+# assume 10.8.0.4/255.255.255.0.  Finally we
+# must set aside an IP range in this subnet
+# (start=10.8.0.50 end=10.8.0.100) to allocate
+# to connecting clients.  Leave this line commented
+# out unless you are ethernet bridging.
+;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100
+
+# Configure server mode for ethernet bridging
+# using a DHCP-proxy, where clients talk
+# to the OpenVPN server-side DHCP server
+# to receive their IP address allocation
+# and DNS server addresses.  You must first use
+# your OS's bridging capability to bridge the TAP
+# interface with the ethernet NIC interface.
+# Note: this mode only works on clients (such as
+# Windows), where the client-side TAP adapter is
+# bound to a DHCP client.
+;server-bridge
+
+# Push routes to the client to allow it
+# to reach other private subnets behind
+# the server.  Remember that these
+# private subnets will also need
+# to know to route the OpenVPN client
+# address pool (10.8.0.0/255.255.255.0)
+# back to the OpenVPN server.
+;push "route 192.168.10.0 255.255.255.0"
+push "route 172.16.7.0 255.255.255.0"
+
+# To assign specific IP addresses to specific
+# clients or if a connecting client has a private
+# subnet behind it that should also have VPN access,
+# use the subdirectory "ccd" for client-specific
+# configuration files (see man page for more info).
+
+# EXAMPLE: Suppose the client
+# having the certificate common name "Thelonious"
+# also has a small subnet behind his connecting
+# machine, such as 192.168.40.128/255.255.255.248.
+# First, uncomment out these lines:
+;client-config-dir ccd
+;route 192.168.40.128 255.255.255.248
+# Then create a file ccd/Thelonious with this line:
+#   iroute 192.168.40.128 255.255.255.248
+# This will allow Thelonious' private subnet to
+# access the VPN.  This example will only work
+# if you are routing, not bridging, i.e. you are
+# using "dev tun" and "server" directives.
+
+# EXAMPLE: Suppose you want to give
+# Thelonious a fixed VPN IP address of 10.9.0.1.
+# First uncomment out these lines:
+;client-config-dir ccd
+;route 10.9.0.0 255.255.255.252
+# Then add this line to ccd/Thelonious:
+#   ifconfig-push 10.9.0.1 10.9.0.2
+
+# Suppose that you want to enable different
+# firewall access policies for different groups
+# of clients.  There are two methods:
+# (1) Run multiple OpenVPN daemons, one for each
+#     group, and firewall the TUN/TAP interface
+#     for each group/daemon appropriately.
+# (2) (Advanced) Create a script to dynamically
+#     modify the firewall in response to access
+#     from different clients.  See man
+#     page for more info on learn-address script.
+;learn-address ./script
+
+# If enabled, this directive will configure
+# all clients to redirect their default
+# network gateway through the VPN, causing
+# all IP traffic such as web browsing and
+# and DNS lookups to go through the VPN
+# (The OpenVPN server machine may need to NAT
+# or bridge the TUN/TAP interface to the internet
+# in order for this to work properly).
+;push "redirect-gateway def1 bypass-dhcp"
+
+# Certain Windows-specific network settings
+# can be pushed to clients, such as DNS
+# or WINS server addresses.  CAVEAT:
+# http://openvpn.net/faq.html#dhcpcaveats
+# The addresses below refer to the public
+# DNS servers provided by opendns.com.
+;push "dhcp-option DNS 208.67.222.222"
+;push "dhcp-option DNS 208.67.220.220"
+
+keepalive 10 120
+
+tls-crypt /etc/openvpn/secrets/ta.key
+
+# The maximum number of concurrently connected
+# clients we want to allow.
+;max-clients 100
+
+user nobody
+group nogroup
+
+# The persist options will try to avoid
+# accessing certain resources on restart
+# that may no longer be accessible because
+# of the privilege downgrade.
+persist-key
+persist-tun
+
+# Output a short status file showing
+# current connections, truncated
+# and rewritten every minute.
+status /var/log/openvpn/openvpn-status.log
+
+verb 3
+
+# Silence repeating messages.  At most 20
+# sequential messages of the same message
+# category will be output to the log.
+;mute 20
+
+# Notify the client that when the server restarts so it
+# can automatically reconnect.
+explicit-exit-notify 1

+ 4 - 0
openvpn-server/entrypoint.sh

@@ -0,0 +1,4 @@
+#!/bin/bash
+mkdir -p /dev/net
+mknod /dev/net/tun c 10 200
+openvpn --config /etc/openvpn/server.conf