Image rewrite

This commit is contained in:
Wyatt Gill 2022-10-16 07:52:46 -05:00
parent ac8a5ba3d4
commit b5489ea7ce
18 changed files with 122 additions and 458 deletions

View file

@ -1,2 +0,0 @@
*
!data/

View file

@ -1,24 +1,15 @@
name: Publish
name: Build
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
env:
IMAGE_NAME: openvpn-client
jobs:
publish:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: cat build-variables >> $GITHUB_ENV
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
- uses: docker/login-action@v2
@ -30,7 +21,7 @@ jobs:
- id: tags
uses: docker/metadata-action@v4
with:
images: ${{ env.IMAGE_NAME }}
images: ghcr.io/wfg/openvpn-client
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
@ -46,9 +37,10 @@ jobs:
- uses: docker/build-push-action@v3
with:
context: "{{defaultContext}}:build"
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6
tags: ${{ steps.tags.outputs.tags }}
build-args: |
BUILD_DATE=${{ steps.build-args.outputs.date }}
IMAGE_VERSION=${{ steps.build-args.outputs.version }}
tags: ${{ steps.tags.outputs.tags }}
push: true

3
.gitignore vendored
View file

@ -1 +1,2 @@
.local/
# Anything used during development should be put in local/ to prevent accidental committing.
local/

View file

@ -1,28 +0,0 @@
# Changelog
## Version 3.1.0 - 2022-06-30
### Changed
- `KILL_SWITCH` now requires `iptables` or `nftables` to be enabled. It defaults to `iptables`. See documentation for more information.
### Added
- Modified OpenVPN configuration file cleanup function.
## Version 3.0.0 - 2022-06-14
### Changed
- Refactored scripts
- Renamed a lot of variables ([PLEASE see docs](README.md#environment-variables))
- Updated logic used to select the OpenVPN configuration file
- Switched to `nftables`
- Updated to Alpine 3.16
- Fixed outdated proxy configuration files
## Version 2.1.0 - 2022-03-06
### Added
- `VPN_CONFIG_PATTERN` environment variable.
## Version 2.0.0 - 2022-01-02
### Changed
- `OPENVPN_AUTH_SECRET` changed to `VPN_AUTH_SECRET` for consistency.
### Fixed
- Commented remotes are no longer processed.

View file

@ -1,29 +0,0 @@
FROM alpine:3.16
RUN apk add --no-cache \
bash \
bind-tools \
dante-server \
iptables \
openvpn \
nftables \
shadow \
tinyproxy
COPY data/ /data/
ENV KILL_SWITCH=iptables
ENV USE_VPN_DNS=on
ENV VPN_LOG_LEVEL=3
ARG BUILD_DATE
ARG IMAGE_VERSION
LABEL build-date=$BUILD_DATE
LABEL image-version=$IMAGE_VERSION
HEALTHCHECK CMD ping -c 3 1.1.1.1 || exit 1
WORKDIR /data
ENTRYPOINT [ "scripts/entry.sh" ]

View file

@ -61,24 +61,9 @@ services:
#### Environment variables
| Variable | Default (blank is unset) | Description |
| --- | --- | --- |
| `USE_VPN_DNS` | `on` | Whether or not to use the DNS servers pushed from the VPN server. It's best to leave this enabled unless you have a good reason to disable it. |
| `VPN_CONFIG_FILE` | | The OpenVPN configuration file to use. If unset, the `VPN_CONFIG_PATTERN` is used. |
| `VPN_CONFIG_PATTERN` | | The search pattern to use when looking for an OpenVPN configuration file. If unset, the search will include `*.conf` and `*.ovpn`. |
| `VPN_AUTH_SECRET` | | Docker secret that contain the credentials for accessing the VPN. |
| `VPN_LOG_LEVEL` | `3` | OpenVPN logging verbosity (`1`-`11`) |
| `SUBNETS` | | A list of one or more comma-separated subnets (e.g. `192.168.0.0/24,192.168.1.0/24`) to allow outside of the VPN tunnel. |
| `KILL_SWITCH` | `iptables` | Which packet filterer to use for the kill switch. This value likely depends on your underlying host. Recommended to leave default unless you have problems. Acceptable values are `iptables` and `nftables`. To disable the kill switch, set to any other value. |
| `HTTP_PROXY` | | Whether or not to enable the built-in HTTP proxy server. To enable, set to any "truthy" value (see below the table). Any other value (including unset) will cause the proxy server to not run. It listens on port 8080. |
| `HTTP_PROXY_USERNAME` | | Credentials for accessing the HTTP proxy. If `HTTP_PROXY_USERNAME` is specified, you should also specify `HTTP_PROXY_PASSWORD`. |
| `HTTP_PROXY_PASSWORD` | | Credentials for accessing the HTTP proxy. If `HTTP_PROXY_PASSWORD` is specified, you should also specify `HTTP_PROXY_USERNAME`. |
| `HTTP_PROXY_USERNAME_SECRET` | | Docker secrets that contain the credentials for accessing the HTTP proxy. If `HTTP_PROXY_USERNAME_SECRET` is specified, you should also specify `HTTP_PROXY_PASSWORD_SECRET`. |
| `HTTP_PROXY_PASSWORD_SECRET` | | Docker secrets that contain the credentials for accessing the HTTP proxy. If `HTTP_PROXY_PASSWORD_SECRET` is specified, you should also specify `HTTP_PROXY_USERNAME_SECRET`. |
| `SOCKS_PROXY` | | Whether or not to enable the built-in SOCKS proxy server. To enable, set to any "truthy" value (see below the table). Any other value (including unset) will cause the proxy server to not run. It listens on port 1080. |
| `SOCKS_LISTEN_ON` | | Address the proxies will be listening on. Set to `0.0.0.0` to listen on all IP addresses. |
| `SOCKS_PROXY_USERNAME` | | Credentials for accessing the proxies. If `SOCKS_PROXY_USERNAME` is specified, you should also specify `SOCKS_PROXY_PASSWORD`. |
| `SOCKS_PROXY_PASSWORD` | | Credentials for accessing the proxies. If `SOCKS_PROXY_PASSWORD` is specified, you should also specify `SOCKS_PROXY_USERNAME`. |
| `SOCKS_PROXY_USERNAME_SECRET` | | Docker secrets that contain the credentials for accessing the proxies. If `SOCKS_PROXY_USERNAME_SECRET` is specified, you should also specify `SOCKS_PROXY_PASSWORD_SECRET`. |
| `SOCKS_PROXY_PASSWORD_SECRET` | | Docker secrets that contain the credentials for accessing the proxies. If `SOCKS_PROXY_PASSWORD_SECRET` is specified, you should also specify `SOCKS_PROXY_USERNAME_SECRET`. |
| `ALLOWED_SUBNETS` | | A list of one or more comma-separated subnets (e.g. `192.168.0.0/24,192.168.1.0/24`) to allow outside of the VPN tunnel. |
| `AUTH_SECRET` | | Docker secret that contains the credentials for accessing the VPN. |
| `CONFIG_FILE` | | The OpenVPN configuration file or search pattern. If unset, a random `.conf` or `.ovpn` file will be selected. |
"Truthy" values are the following: `true`, `t`, `yes`, `y`, `1`, `on`, `enable`, or `enabled`.
##### Environment variable considerations

View file

@ -1 +0,0 @@
IMAGE_NAME=ghcr.io/wfg/openvpn-client

View file

@ -6,15 +6,15 @@ import subprocess
parser = argparse.ArgumentParser()
parser.add_argument('image_version', type=str)
parser.add_argument('image_version')
args = parser.parse_args()
docker_build_cmd = [
'docker', 'build',
'--build-arg', f'BUILD_DATE={str(datetime.datetime.now())}',
'--build-arg', f'BUILD_DATE={str(datetime.datetime.utcnow())}',
'--build-arg', f'IMAGE_VERSION={args.image_version}',
'--tag', f'ghcr.io/wfg/openvpn-client:{args.image_version}',
'--tag', 'ghcr.io/wfg/openvpn-client:latest',
'.',
'./build',
]
subprocess.run(docker_build_cmd)

1
build/.dockerignore Normal file
View file

@ -0,0 +1 @@
Dockerfile

12
build/Dockerfile Normal file
View file

@ -0,0 +1,12 @@
FROM alpine:3.16
RUN apk add --no-cache \
bash \
bind-tools \
iptables \
ip6tables \
openvpn
COPY . /usr/local/bin
ENTRYPOINT [ "entry.sh" ]

48
build/entry.sh Executable file
View file

@ -0,0 +1,48 @@
#!/usr/bin/env bash
set -e
cleanup() {
kill TERM "$openvpn_pid"
exit 0
}
is_enabled() {
[[ ${1,,} =~ ^(true|t|yes|y|1|on|enable|enabled)$ ]]
}
# Either a specific file name or a pattern.
if [[ $CONFIG_FILE ]]; then
config_file=$(find /config -name "$CONFIG_FILE" 2> /dev/null | sort | shuf -n 1)
else
config_file=$(find /config -name '*.conf' -o -name '*.ovpn' 2> /dev/null | sort | shuf -n 1)
fi
if [[ -z $config_file ]]; then
>&2 echo 'no openvpn configuration file found'
exit 1
fi
echo "using openvpn configuration file: $config_file"
openvpn_args=(
"--config" "$config_file"
"--cd" "/config"
)
if is_enabled "$KILL_SWITCH"; then
openvpn_args+=("--route-up" "/usr/local/bin/killswitch.sh $ALLOWED_SUBNETS")
fi
# Docker secret that contains the credentials for accessing the VPN.
if [[ $AUTH_SECRET ]]; then
openvpn_args+=("--auth-user-pass" "/run/secrets/$AUTH_SECRET")
fi
openvpn "${openvpn_args[@]}" &
openvpn_pid=$!
trap cleanup TERM
wait $openvpn_pid

42
build/killswitch.sh Executable file
View file

@ -0,0 +1,42 @@
#!/usr/bin/env bash
set -e
iptables --insert OUTPUT \
! --out-interface tun0 \
--match addrtype ! --dst-type LOCAL \
! --destination "$(ip -4 -oneline addr show dev eth0 | awk 'NR == 1 { print $4 }')" \
--jump REJECT
# Create static routes for any ALLOWED_SUBNETS and punch holes in the firewall
# (ALLOWED_SUBNETS is passed as $1 from entry.sh)
default_gateway=$(ip -4 route | awk '$1 == "default" { print $3 }')
for subnet in ${1//,/ }; do
ip route add "$subnet" via "$default_gateway"
iptables --insert OUTPUT --destination "$subnet" --jump ACCEPT
done
# Punch holes in the firewall for the OpenVPN server addresses
# $config is set by OpenVPN:
# "Name of first --config file. Set on program initiation and reset on SIGHUP."
global_port=$(awk '$1 == "port" { print $2 }' "${config:?}")
global_protocol=$(awk '$1 == "proto" { print $2 }' "${config:?}")
remotes=$(awk '$1 == "remote" { print $2, $3, $4 }' "${config:?}")
ip_regex='^(([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\.){3}([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))$'
while IFS= read -r line; do
# Read a comment-stripped version of the line
# Fixes #84
IFS=' ' read -ra remote <<< "${line%%\#*}"
address=${remote[0]}
port=${remote[1]:-${global_port:-1194}}
protocol=${remote[2]:-${global_protocol:-udp}}
if [[ $address =~ $ip_regex ]]; then
iptables --insert OUTPUT --destination "$address" --protocol "$protocol" --destination-port "$port" --jump ACCEPT
else
for ip in $(dig -4 +short "$address"); do
iptables --insert OUTPUT --destination "$ip" --protocol "$protocol" --destination-port "$port" --jump ACCEPT
echo "$ip $address" >> /etc/hosts
done
fi
done <<< "$remotes"

View file

@ -1,14 +0,0 @@
User tinyproxy
Group tinyproxy
Port 8080
Listen
Bind
Timeout 600
LogLevel Info
LogFile "/var/log/tinyproxy/tinyproxy.log"
DefaultErrorFile "/usr/share/tinyproxy/default.html"
StatFile "/usr/share/tinyproxy/stats.html"
DisableViaHeader yes

View file

@ -1,26 +0,0 @@
logoutput: /var/log/dante.log
errorlog: stderr
internal: eth0 port = 1080
external: tun0
socksmethod: none
user.unprivileged: sockd
client pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
log: error connect disconnect
}
socks pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
command: bind connect udpassociate
log: error connect disconnect
}
socks pass {
from: 0.0.0.0/0 to: 0.0.0.0/0
command: bindreply udpreply
log: error connect disconnect
}

View file

@ -1,242 +0,0 @@
#!/usr/bin/env bash
set -e
cleanup() {
if [[ $openvpn_child ]]; then
kill SIGTERM "$openvpn_child"
fi
sleep 0.5
rm -f "$modified_config_file"
echo "info: exiting"
exit 0
}
is_enabled() {
[[ ${1,,} =~ ^(true|t|yes|y|1|on|enable|enabled)$ ]]
}
mkdir -p /data/{config,scripts,vpn}
echo "
--- Running with the following variables ---"
if [[ $VPN_CONFIG_FILE ]]; then
echo "VPN configuration file: $VPN_CONFIG_FILE"
fi
if [[ $VPN_CONFIG_PATTERN ]]; then
echo "VPN configuration file name pattern: $VPN_CONFIG_PATTERN"
fi
echo "Use default resolv.conf: ${USE_VPN_DNS:-off}
Allowing subnets: ${SUBNETS:-none}
Kill switch: $KILL_SWITCH
Using OpenVPN log level: $VPN_LOG_LEVEL"
if is_enabled "$HTTP_PROXY"; then
echo "HTTP proxy: $HTTP_PROXY"
if is_enabled "$HTTP_PROXY_USERNAME"; then
echo "HTTP proxy username: $HTTP_PROXY_USERNAME"
elif is_enabled "$HTTP_PROXY_USERNAME_SECRET"; then
echo "HTTP proxy username secret: $HTTP_PROXY_USERNAME_SECRET"
fi
fi
if is_enabled "$SOCKS_PROXY"; then
echo "SOCKS proxy: $SOCKS_PROXY"
if [[ $SOCKS_LISTEN_ON ]]; then
echo "Listening on: $SOCKS_LISTEN_ON"
fi
if is_enabled "$SOCKS_PROXY_USERNAME"; then
echo "SOCKS proxy username: $SOCKS_PROXY_USERNAME"
elif is_enabled "$SOCKS_PROXY_USERNAME_SECRET"; then
echo "SOCKS proxy username secret: $SOCKS_PROXY_USERNAME_SECRET"
fi
fi
echo "---
"
if [[ $VPN_CONFIG_FILE ]]; then
original_config_file=vpn/$VPN_CONFIG_FILE
elif [[ $VPN_CONFIG_PATTERN ]]; then
original_config_file=$(find vpn -name "$VPN_CONFIG_PATTERN" 2> /dev/null | sort | shuf -n 1)
else
original_config_file=$(find vpn -name '*.conf' -o -name '*.ovpn' 2> /dev/null | sort | shuf -n 1)
fi
if [[ -z $original_config_file ]]; then
>&2 echo 'erro: no vpn configuration file found'
exit 1
fi
echo "info: original configuration file: $original_config_file"
# Create a new configuration file to modify so the original is left untouched.
modified_config_file=vpn/openvpn.$(tr -dc A-Za-z0-9 </dev/urandom | head -c8).conf
trap cleanup SIGTERM
echo "info: modified configuration file: $modified_config_file"
grep -Ev '(^up\s|^down\s)' "$original_config_file" > "$modified_config_file"
# Remove carriage returns (\r) from the config file
sed -i 's/\r$//g' "$modified_config_file"
default_gateway=$(ip -4 route | grep 'default via' | awk '{print $3}')
case "$KILL_SWITCH" in
'iptables')
echo "info: kill switch is using iptables"
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
local_subnet=$(ip -4 route | grep 'scope link' | awk '{print $1}')
iptables -A INPUT -s "$local_subnet" -j ACCEPT
iptables -A OUTPUT -d "$local_subnet" -j ACCEPT
if [[ $SUBNETS ]]; then
for subnet in ${SUBNETS//,/ }; do
ip route add "$subnet" via "$default_gateway" dev eth0
iptables -A INPUT -s "$subnet" -j ACCEPT
iptables -A OUTPUT -d "$subnet" -j ACCEPT
done
fi
global_port=$(grep "^port " "$modified_config_file" | awk '{print $2}')
global_protocol=$(grep "^proto " "$modified_config_file" | awk '{print $2}') # {$2 = substr($2, 1, 3)} 2
remotes=$(grep "^remote " "$modified_config_file" | awk '{print $2, $3, $4}')
ip_regex='^(([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\.){3}([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))$'
while IFS= read -r line; do
IFS=' ' read -ra remote <<< "$line"
address=${remote[0]}
port=${remote[1]:-${global_port:-1194}}
protocol=${remote[2]:-${global_protocol:-udp}}
if [[ $address =~ $ip_regex ]]; then
iptables -A OUTPUT -o eth0 -d "$address" -p "$protocol" --dport "$port" -j ACCEPT
else
for ip in $(dig -4 +short "$address"); do
iptables -A OUTPUT -o eth0 -d "$ip" -p "$protocol" --dport "$port" -j ACCEPT
printf "%s %s\n" "$ip" "$address" >> /etc/hosts
done
fi
done <<< "$remotes"
iptables -A INPUT -i tun0 -j ACCEPT
iptables -A OUTPUT -o tun0 -j ACCEPT
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables-save > config/iptables.conf
;;
'nftables')
echo "info: kill switch is using nftables"
nftables_config_file=config/nftables.conf
printf '%s\n' \
'#!/usr/bin/nft' '' \
'flush ruleset' '' \
'# base ruleset' \
'add table inet killswitch' '' \
'add chain inet killswitch incoming { type filter hook input priority 0; policy drop; }' \
'add rule inet killswitch incoming ct state established,related accept' \
'add rule inet killswitch incoming iifname lo accept' '' \
'add chain inet killswitch outgoing { type filter hook output priority 0; policy drop; }' \
'add rule inet killswitch outgoing ct state established,related accept' \
'add rule inet killswitch outgoing oifname lo accept' '' > $nftables_config_file
local_subnet=$(ip -4 route | grep 'scope link' | awk '{print $1}')
printf '%s\n' \
'# allow traffic to/from the Docker subnet' \
"add rule inet killswitch incoming ip saddr $local_subnet accept" \
"add rule inet killswitch outgoing ip daddr $local_subnet accept" '' >> $nftables_config_file
if [[ $SUBNETS ]]; then
printf '# allow traffic to/from the specified subnets\n' >> $nftables_config_file
for subnet in ${SUBNETS//,/ }; do
ip route add "$subnet" via "$default_gateway" dev eth0
printf '%s\n' \
"add rule inet killswitch incoming ip saddr $subnet accept" \
"add rule inet killswitch outgoing ip daddr $subnet accept" '' >> $nftables_config_file
done
fi
global_port=$(grep "^port " "$modified_config_file" | awk '{print $2}')
global_protocol=$(grep "^proto " "$modified_config_file" | awk '{print $2}') # {$2 = substr($2, 1, 3)} 2
remotes=$(grep "^remote " "$modified_config_file" | awk '{print $2, $3, $4}')
printf '# allow traffic to the VPN server(s)\n' >> $nftables_config_file
ip_regex='^(([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\.){3}([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))$'
while IFS= read -r line; do
IFS=' ' read -ra remote <<< "$line"
address=${remote[0]}
port=${remote[1]:-${global_port:-1194}}
protocol=${remote[2]:-${global_protocol:-udp}}
if [[ $address =~ $ip_regex ]]; then
printf '%s\n' \
"add rule inet killswitch outgoing oifname eth0 ip daddr $address $protocol dport $port accept" >> $nftables_config_file
else
for ip in $(dig -4 +short "$address"); do
printf '%s\n' \
"add rule inet killswitch outgoing oifname eth0 ip daddr $ip $protocol dport $port accept" >> $nftables_config_file
printf "%s %s\n" "$ip" "$address" >> /etc/hosts
done
fi
done <<< "$remotes"
printf '%s\n' \
'' '# allow traffic over the VPN interface' \
"add rule inet killswitch incoming iifname tun0 accept" \
"add rule inet killswitch outgoing oifname tun0 accept" >> $nftables_config_file
nft -f $nftables_config_file
;;
*)
echo "info: kill switch is off"
for subnet in ${SUBNETS//,/ }; do
ip route add "$subnet" via "$default_gateway" dev eth0
done
;;
esac
if is_enabled "$HTTP_PROXY" ; then
scripts/run-http-proxy.sh &
fi
if is_enabled "$SOCKS_PROXY" ; then
scripts/run-socks-proxy.sh &
fi
openvpn_args=(
"--config" "$modified_config_file"
"--auth-nocache"
"--cd" "vpn"
"--pull-filter" "ignore" "ifconfig-ipv6 "
"--pull-filter" "ignore" "route-ipv6 "
"--script-security" "2"
"--up-restart"
"--verb" "$VPN_LOG_LEVEL"
)
if is_enabled "$USE_VPN_DNS" ; then
openvpn_args+=(
"--up" "/etc/openvpn/up.sh"
"--down" "/etc/openvpn/down.sh"
)
fi
if [[ $VPN_AUTH_SECRET ]]; then
openvpn_args+=("--auth-user-pass" "/run/secrets/$VPN_AUTH_SECRET")
fi
openvpn "${openvpn_args[@]}" &
openvpn_child=$!
wait $openvpn_child

View file

@ -1,30 +0,0 @@
#!/usr/bin/env bash
set -e
until ip link show tun0 2>&1 | grep -qv "does not exist"; do
sleep 1
done
proxy_config_file=config/http-proxy.conf
addr_eth0=$(ip address show eth0 | grep 'inet ' | awk '{split($2, inet, "/"); print inet[1]}')
addr_tun0=$(ip address show tun0 | grep 'inet ' | awk '{split($2, inet, "/"); print inet[1]}')
sed -i \
-e "/Listen/c Listen $addr_eth0" \
-e "/Bind/c Bind $addr_tun0" \
$proxy_config_file
if [[ $HTTP_PROXY_USERNAME && $HTTP_PROXY_PASSWORD ]]; then
echo 'info: starting http proxy with credentials'
printf 'BasicAuth %s %s\n' "$HTTP_PROXY_USERNAME" "$HTTP_PROXY_PASSWORD" >> $proxy_config_file
elif [[ -f "/run/secrets/$HTTP_PROXY_USERNAME_SECRET" && -f "/run/secrets/$HTTP_PROXY_PASSWORD_SECRET" ]]; then
echo 'info: starting http proxy with credentials'
printf 'BasicAuth %s %s\n' \
"$(cat /run/secrets/"$HTTP_PROXY_USERNAME_SECRET")" \
"$(cat /run/secrets/"$HTTP_PROXY_PASSWORD_SECRET")" >> $proxy_config_file
else
echo 'info: starting http proxy without credentials'
fi
exec tinyproxy -d -c $proxy_config_file

View file

@ -1,26 +0,0 @@
#!/usr/bin/env bash
set -e
until ip link show tun0 2>&1 | grep -qv "does not exist"; do
sleep 1
done
proxy_config_file=config/socks-proxy.conf
if [[ $SOCKS_LISTEN_ON ]]; then
sed -i "/internal: /c internal: $SOCKS_LISTEN_ON port = 1080" $proxy_config_file
fi
if [[ $SOCKS_PROXY_USERNAME && $SOCKS_PROXY_PASSWORD ]]; then
printf 'info: starting socks proxy with credentials\n'
id "$SOCKS_PROXY_USERNAME" &> /dev/null || useradd "$SOCKS_PROXY_USERNAME" -s /bin/false -M -p "$(mkpasswd "$SOCKS_PROXY_PASSWORD")"
sed -i "/method: /c method: username" $proxy_config_file
elif [[ -f "/run/secrets/$SOCKS_PROXY_USERNAME_SECRET" && -f "/run/secrets/$SOCKS_PROXY_PASSWORD_SECRET" ]]; then
printf 'info: starting socks proxy with credentials\n'
id "$(cat /run/secrets/"$SOCKS_PROXY_USERNAME_SECRET")" &> /dev/null || useradd "$(cat /run/secrets/"$SOCKS_PROXY_USERNAME_SECRET")" -s /bin/false -M -p "$(mkpasswd "$(cat /run/secrets/"$SOCKS_PROXY_PASSWORD_SECRET")")"
sed -i "/method: /c method: username" $proxy_config_file
else
printf 'info: starting socks proxy without credentials\n'
fi
exec sockd -f $proxy_config_file

View file

@ -1,32 +1,13 @@
# Use this file as an example if you need help writing your Compose files.
# The commented-out parts may or may not be relevant to your setup.
services:
vpn:
image: ghcr.io/wfg/openvpn-client
# build: .
openvpn-client:
image: ghcr.io/wfg/openvpn-client:latest
container_name: openvpn-client
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
environment:
# - SUBNETS=192.168.10.0/24
- HTTP_PROXY=on
- SOCKS_PROXY=on
# - PROXY_USERNAME_SECRET=username # <-- If used, these must match the name of a
# - PROXY_PASSWORD_SECRET=password # <-- secret (NOT the file used by the secret)
# volumes:
# - ~/local/vpn:/data/vpn
ports:
- 1080:1080
- 8088:8080
# secrets:
# - username
# - password
# secrets:
# username:
# file: ~/local/secrets/username
# password:
# file: ~/local/secrets/password
- ALLOWED_SUBNETS=192.168.10.0/24
volumes:
- ./local:/config
restart: unless-stopped