From 204a6d1b8c46e524adc4bd8896a2a9c598b498de Mon Sep 17 00:00:00 2001 From: Leonard Jonathan Oh Date: Fri, 30 Jun 2023 08:55:10 +0000 Subject: [PATCH] Feature: Add `2.6.5` variants --- .github/workflows/ci-master-pr.yml | 128 +++++++++++++++++- README.md | 5 +- generate/definitions/VARIANTS.ps1 | 9 ++ variants/v2.6.5-alpine-3.18/Dockerfile | 8 ++ .../v2.6.5-alpine-3.18/docker-compose.yml | 40 ++++++ .../v2.6.5-alpine-3.18/docker-entrypoint.sh | 76 +++++++++++ .../v2.6.5-alpine-3.18/openvpn/client.conf | 23 ++++ .../v2.6.5-alpine-3.18/openvpn/firewall.sh | 13 ++ .../v2.6.5-alpine-3.18/openvpn/server.conf | 25 ++++ 9 files changed, 321 insertions(+), 6 deletions(-) create mode 100644 variants/v2.6.5-alpine-3.18/Dockerfile create mode 100644 variants/v2.6.5-alpine-3.18/docker-compose.yml create mode 100644 variants/v2.6.5-alpine-3.18/docker-entrypoint.sh create mode 100644 variants/v2.6.5-alpine-3.18/openvpn/client.conf create mode 100644 variants/v2.6.5-alpine-3.18/openvpn/firewall.sh create mode 100644 variants/v2.6.5-alpine-3.18/openvpn/server.conf diff --git a/.github/workflows/ci-master-pr.yml b/.github/workflows/ci-master-pr.yml index 4d0f031..69d4e1a 100644 --- a/.github/workflows/ci-master-pr.yml +++ b/.github/workflows/ci-master-pr.yml @@ -32,6 +32,127 @@ jobs: run: | git diff --exit-code + build-v2-6-5-alpine-3-18: + runs-on: ubuntu-latest + env: + VARIANT: v2.6.5-alpine-3.18 + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Display system info (linux) + run: | + set -e + hostname + whoami + cat /etc/*release + lscpu + free + df -h + pwd + docker info + docker version + + # See: https://github.com/docker/build-push-action/blob/v2.6.1/docs/advanced/cache.md#github-cache + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v2 + + - name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ env.VARIANT }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx-${{ env.VARIANT }}- + ${{ runner.os }}-buildx- + + # This step generates the docker tags + - name: Prepare + id: prep + run: | + set -e + + # Get ref, i.e. from refs/heads/, or from refs/tags/. E.g. 'master' or 'v0.0.0' + REF=$( echo "${GITHUB_REF}" | rev | cut -d '/' -f 1 | rev ) + + # Get short commit hash E.g. 'abc0123' + SHA=$( echo "${GITHUB_SHA}" | cut -c1-7 ) + + # Generate docker image tags + # E.g. 'v0.0.0-' and 'v0.0.0-abc0123-' + # E.g. 'master-' and 'master-abc0123-' + REF_VARIANT="${REF}-${VARIANT}" + REF_SHA_VARIANT="${REF}-${SHA}-${VARIANT}" + + # Pass variables to next step + echo "VARIANT_BUILD_DIR=$VARIANT_BUILD_DIR" >> $GITHUB_ENV + echo "VARIANT=$VARIANT" >> $GITHUB_ENV + echo "REF_VARIANT=$REF_VARIANT" >> $GITHUB_ENV + echo "REF_SHA_VARIANT=$REF_SHA_VARIANT" >> $GITHUB_ENV + + - name: Login to Docker Hub registry + # Run on master and tags + if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_REGISTRY_USER }} + password: ${{ secrets.DOCKERHUB_REGISTRY_PASSWORD }} + + - name: Build (PRs) + # Run only on pull requests + if: github.event_name == 'pull_request' + uses: docker/build-push-action@v3 + with: + context: variants/v2.6.5-alpine-3.18 + platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/s390x + push: false + tags: | + ${{ github.repository }}:${{ env.REF_VARIANT }} + ${{ github.repository }}:${{ env.REF_SHA_VARIANT }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + + - name: Build and push (master) + # Run only on master + if: github.ref == 'refs/heads/master' + uses: docker/build-push-action@v3 + with: + context: variants/v2.6.5-alpine-3.18 + platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/s390x + push: true + tags: | + ${{ github.repository }}:${{ env.REF_VARIANT }} + ${{ github.repository }}:${{ env.REF_SHA_VARIANT }} + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + + - name: Build and push (release) + if: startsWith(github.ref, 'refs/tags/') + uses: docker/build-push-action@v3 + with: + context: variants/v2.6.5-alpine-3.18 + platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/s390x + push: true + tags: | + ${{ github.repository }}:${{ env.VARIANT }} + ${{ github.repository }}:${{ env.REF_VARIANT }} + ${{ github.repository }}:${{ env.REF_SHA_VARIANT }} + ${{ github.repository }}:latest + cache-from: type=local,src=/tmp/.buildx-cache + cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max + + # Temp fix + # https://github.com/docker/build-push-action/issues/252 + # https://github.com/moby/buildkit/issues/1896 + - name: Move cache + run: | + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache + build-v2-5-8-alpine-3-17: runs-on: ubuntu-latest env: @@ -141,7 +262,6 @@ jobs: ${{ github.repository }}:${{ env.VARIANT }} ${{ github.repository }}:${{ env.REF_VARIANT }} ${{ github.repository }}:${{ env.REF_SHA_VARIANT }} - ${{ github.repository }}:latest cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max @@ -1354,7 +1474,7 @@ jobs: mv /tmp/.buildx-cache-new /tmp/.buildx-cache update-draft-release: - needs: [build-v2-5-8-alpine-3-17, build-v2-4-12-alpine-3-12, build-v2-4-11-alpine-3-11, build-v2-4-11-alpine-3-10, build-v2-4-6-alpine-3-9, build-v2-4-6-alpine-3-8, build-v2-4-4-alpine-3-7, build-v2-4-4-alpine-3-6, build-v2-3-18-alpine-3-5, build-v2-3-18-alpine-3-4, build-v2-3-18-alpine-3-3] + needs: [build-v2-6-5-alpine-3-18, build-v2-5-8-alpine-3-17, build-v2-4-12-alpine-3-12, build-v2-4-11-alpine-3-11, build-v2-4-11-alpine-3-10, build-v2-4-6-alpine-3-9, build-v2-4-6-alpine-3-8, build-v2-4-4-alpine-3-7, build-v2-4-4-alpine-3-6, build-v2-3-18-alpine-3-5, build-v2-3-18-alpine-3-4, build-v2-3-18-alpine-3-3] if: github.ref == 'refs/heads/master' runs-on: ubuntu-latest steps: @@ -1367,7 +1487,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} publish-draft-release: - needs: [build-v2-5-8-alpine-3-17, build-v2-4-12-alpine-3-12, build-v2-4-11-alpine-3-11, build-v2-4-11-alpine-3-10, build-v2-4-6-alpine-3-9, build-v2-4-6-alpine-3-8, build-v2-4-4-alpine-3-7, build-v2-4-4-alpine-3-6, build-v2-3-18-alpine-3-5, build-v2-3-18-alpine-3-4, build-v2-3-18-alpine-3-3] + needs: [build-v2-6-5-alpine-3-18, build-v2-5-8-alpine-3-17, build-v2-4-12-alpine-3-12, build-v2-4-11-alpine-3-11, build-v2-4-11-alpine-3-10, build-v2-4-6-alpine-3-9, build-v2-4-6-alpine-3-8, build-v2-4-4-alpine-3-7, build-v2-4-4-alpine-3-6, build-v2-3-18-alpine-3-5, build-v2-3-18-alpine-3-4, build-v2-3-18-alpine-3-3] if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest steps: @@ -1382,7 +1502,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} update-dockerhub-description: - needs: [build-v2-5-8-alpine-3-17, build-v2-4-12-alpine-3-12, build-v2-4-11-alpine-3-11, build-v2-4-11-alpine-3-10, build-v2-4-6-alpine-3-9, build-v2-4-6-alpine-3-8, build-v2-4-4-alpine-3-7, build-v2-4-4-alpine-3-6, build-v2-3-18-alpine-3-5, build-v2-3-18-alpine-3-4, build-v2-3-18-alpine-3-3] + needs: [build-v2-6-5-alpine-3-18, build-v2-5-8-alpine-3-17, build-v2-4-12-alpine-3-12, build-v2-4-11-alpine-3-11, build-v2-4-11-alpine-3-10, build-v2-4-6-alpine-3-9, build-v2-4-6-alpine-3-8, build-v2-4-4-alpine-3-7, build-v2-4-4-alpine-3-6, build-v2-3-18-alpine-3-5, build-v2-3-18-alpine-3-4, build-v2-3-18-alpine-3-3] if: github.ref == 'refs/heads/master' runs-on: ubuntu-latest steps: diff --git a/README.md b/README.md index a8ec818..343adb7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,8 @@ Dockerized `openvpn`. | Tag | Dockerfile Build Context | |:-------:|:---------:| -| `:v2.5.8-alpine-3.17`, `:latest` | [View](variants/v2.5.8-alpine-3.17) | +| `:v2.6.5-alpine-3.18`, `:latest` | [View](variants/v2.6.5-alpine-3.18) | +| `:v2.5.8-alpine-3.17` | [View](variants/v2.5.8-alpine-3.17) | | `:v2.4.12-alpine-3.12` | [View](variants/v2.4.12-alpine-3.12) | | `:v2.4.11-alpine-3.11` | [View](variants/v2.4.11-alpine-3.11) | | `:v2.4.11-alpine-3.10` | [View](variants/v2.4.11-alpine-3.10) | @@ -31,7 +32,7 @@ It is assumed that you have knowledge of configuring `openvpn`. To run the image, at the least you should mount a `/etc/openvpn/server.conf`, which may be a unified openvpn profile (see INLINE FILE SUPPORT section in the [openvpn manual](https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage)). ```sh -docker run --rm -it --cap-add NET_ADMIN -v /path/to/server.conf:/etc/openvpn/server.conf theohbrothers/docker-openvpn:v2.5.8-alpine-3.17 +docker run --rm -it --cap-add NET_ADMIN -v /path/to/server.conf:/etc/openvpn/server.conf theohbrothers/docker-openvpn:v2.6.5-alpine-3.18 ``` ## Environment variables diff --git a/generate/definitions/VARIANTS.ps1 b/generate/definitions/VARIANTS.ps1 index ebc532d..e03f3e9 100644 --- a/generate/definitions/VARIANTS.ps1 +++ b/generate/definitions/VARIANTS.ps1 @@ -1,5 +1,14 @@ # Docker image variants' definitions $local:VARIANTS_MATRIX = @( + @{ + package = 'openvpn' + package_version = '2.6.5-r0' + distro = 'alpine' + distro_version = '3.18' + subvariants = @( + @{ components = @() } + ) + } @{ package = 'openvpn' package_version = '2.5.8-r0' diff --git a/variants/v2.6.5-alpine-3.18/Dockerfile b/variants/v2.6.5-alpine-3.18/Dockerfile new file mode 100644 index 0000000..650a190 --- /dev/null +++ b/variants/v2.6.5-alpine-3.18/Dockerfile @@ -0,0 +1,8 @@ +FROM alpine:3.18 + +RUN apk add --no-cache openvpn=2.6.5-r0 iptables + +COPY docker-entrypoint.sh /docker-entrypoint.sh +RUN chmod +x /docker-entrypoint.sh + +ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/variants/v2.6.5-alpine-3.18/docker-compose.yml b/variants/v2.6.5-alpine-3.18/docker-compose.yml new file mode 100644 index 0000000..c13c068 --- /dev/null +++ b/variants/v2.6.5-alpine-3.18/docker-compose.yml @@ -0,0 +1,40 @@ +version: '2.1' +services: + openvpn-server: + image: theohbrothers/docker-openvpn:v2.6.5-alpine-3.18 + environment: + - OPENVPN_CONFIG_FILE=/etc/openvpn/server.conf + # - CUSTOM_FIREWALL_SCRIPT=/etc/openvpn/firewall.sh + volumes: + - ./openvpn/server.conf:/etc/openvpn/server.conf + # - ./openvpn/firewall.sh:/etc/openvpn/firewall.sh + ports: + - "1194:1194/udp" + cap_add: + - NET_ADMIN + # sysctls for the container if it is not set on the host. See: https://docs.docker.com/compose/compose-file/compose-file-v2/#sysctls + sysctls: + - net.ipv4.conf.all.forwarding=1 + # - net.ipv6.conf.all.disable_ipv6=0 + # - net.ipv6.conf.default.forwarding=1 + # - net.ipv6.conf.all.forwarding=1 + restart: unless-stopped + + openvpn-client: + image: theohbrothers/docker-openvpn:v2.6.5-alpine-3.18 + environment: + - OPENVPN_CONFIG_FILE=/etc/openvpn/client.conf + - NAT_MASQUERADE=0 + # - CUSTOM_FIREWALL_SCRIPT=/etc/openvpn/firewall.sh + volumes: + - ./openvpn/client.conf:/etc/openvpn/client.conf + # - ./openvpn/firewall.sh:/etc/openvpn/firewall.sh + cap_add: + - NET_ADMIN + # sysctls for the container if it is not set on the host. See: https://docs.docker.com/compose/compose-file/compose-file-v2/#sysctls + sysctls: + - net.ipv4.conf.all.forwarding=1 + # - net.ipv6.conf.all.disable_ipv6=0 + # - net.ipv6.conf.default.forwarding=1 + # - net.ipv6.conf.all.forwarding=1 + restart: unless-stopped \ No newline at end of file diff --git a/variants/v2.6.5-alpine-3.18/docker-entrypoint.sh b/variants/v2.6.5-alpine-3.18/docker-entrypoint.sh new file mode 100644 index 0000000..20f44fb --- /dev/null +++ b/variants/v2.6.5-alpine-3.18/docker-entrypoint.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +set -eu -o pipefail + +output() { + echo -e "[$( date -u '+%Y-%m-%dT%H:%M:%S%z' )] $1" +} + +error() { + echo -e "[$( date -u '+%Y-%m-%dT%H:%M:%S%z' )] $1" >&2 +} + +# Env vars +OPENVPN_CONFIG_FILE=${OPENVPN_CONFIG_FILE:-/etc/openvpn/server.conf} +OPENVPN_SERVER_CONFIG_FILE=${OPENVPN_SERVER_CONFIG_FILE:-} # Deprecated. For backward compatibility +OPENVPN_ROUTES=${OPENVPN_ROUTES:-} +NAT=${NAT:-1} +NAT_INTERFACE=${NAT_INTERFACE:-eth0} +NAT_MASQUERADE=${NAT_MASQUERADE:-1} +CUSTOM_FIREWALL_SCRIPT=${CUSTOM_FIREWALL_SCRIPT:-/etc/openvpn/firewall.sh} + +# Normalization +if [ -n "$OPENVPN_SERVER_CONFIG_FILE" ]; then + output "Warning: OPENVPN_SERVER_CONFIG_FILE is deprecated. Use OPENVPN_CONFIG_FILE instead." + OPENVPN_CONFIG_FILE="$OPENVPN_SERVER_CONFIG_FILE" +fi + +# Provision +output "Provisioning tun device" +mkdir -p /dev/net +if [ ! -c /dev/net/tun ]; then + mknod /dev/net/tun c 10 200 +fi +if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then + output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" +else + output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" +fi +if [ "$NAT" = 1 ]; then + output "NAT is enabled" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" + if [ "$NAT_MASQUERADE" = 1 ]; then + output "NAT_MASQUERADE is enabled" + iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE > dev/null 2>&1 || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE + if [ -n "$OPENVPN_ROUTES" ]; then + output "Provisioning NAT iptables rules for OPENVPN_ROUTES=$OPENVPN_ROUTES" + for r in $OPENVPN_ROUTES; do + iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE > dev/null 2>&1 || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE + done + else + output "Not provisioning route iptables rules because OPENVPN_ROUTES is empty" + fi + else + output "Not provisioning NAT iptables rules because NAT_MASQUERADE is disabled." + fi +else + output "NAT is disabled." + output "Not adding NAT iptables rules" +fi + +output "Listing iptables rules:" +iptables -L -nv +output "Listing iptables NAT rules:" +iptables -L -nv -t nat + +# Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ +output "Generating command line" +set openvpn --cd /etc/openvpn +set "$@" --config "$OPENVPN_CONFIG_FILE" + +# Exec +ARGS="$@" +output "openvpn command line: $ARGS" +exec "$@" \ No newline at end of file diff --git a/variants/v2.6.5-alpine-3.18/openvpn/client.conf b/variants/v2.6.5-alpine-3.18/openvpn/client.conf new file mode 100644 index 0000000..953eefa --- /dev/null +++ b/variants/v2.6.5-alpine-3.18/openvpn/client.conf @@ -0,0 +1,23 @@ +# See sample config file: https://github.com/OpenVPN/openvpn/blob/v2.4.8/sample/sample-config-files/client.conf +# redirect-gateway def1 bypass-dhcp +client +dev tun +proto udp +remote 10.8.0.1 1194 +resolv-retry infinite +nobind +# user nobody +# group nobody +persist-key +persist-tun +ca pki/ca.crt +cert pki/issued/client.crt +key pki/private/client.key +remote-cert-tls server +tls-auth pki/ta.key 1 +# key-direction 1 +cipher AES-256-CBC +# auth SHA256 +comp-lzo no +verb 3 +# mute 20 diff --git a/variants/v2.6.5-alpine-3.18/openvpn/firewall.sh b/variants/v2.6.5-alpine-3.18/openvpn/firewall.sh new file mode 100644 index 0000000..2741334 --- /dev/null +++ b/variants/v2.6.5-alpine-3.18/openvpn/firewall.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +# This iptables script to controlling traffic in the openvpn tunnel. +# In this example, clients can only perform DNS, HTTP and HTTPS requests to the world. + +set -eu -o pipefail + +# Drop everything by default from tunnel to world +iptables -P FORWARD DROP +# Allow DNS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.6.5-alpine-3.18/openvpn/server.conf b/variants/v2.6.5-alpine-3.18/openvpn/server.conf new file mode 100644 index 0000000..72fef1d --- /dev/null +++ b/variants/v2.6.5-alpine-3.18/openvpn/server.conf @@ -0,0 +1,25 @@ +# See sample config file: https://github.com/OpenVPN/openvpn/blob/v2.4.8/sample/sample-config-files/server.conf +port 1194 +proto udp +dev tun +ca pki/ca.crt +cert pki/issued/server.crt +key pki/private/server.key +dh pki/dh.pem +crl-verify pki/crl.pem +server 10.8.0.0 255.255.255.0 +ifconfig-pool-persist ipp.txt +;client-config-dir ccd +keepalive 10 120 +tls-auth pki/ta.key 0 +cipher AES-256-CBC +max-clients 5 +user nobody +group nogroup +persist-key +persist-tun +status server.status.log +# log-append server.log +verb 3 +mute 20 +explicit-exit-notify 1 \ No newline at end of file