From 0598d2ecaa8ea88656338e8cf52e730ebc081aa3 Mon Sep 17 00:00:00 2001 From: Miklos Bagi Date: Sun, 26 Jan 2025 18:22:08 +0100 Subject: [PATCH 1/7] Add control server authentication support #59, address grep: bad regex bug in #61 --- entrypoint.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 99cfbd5..12bbd5d 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -12,6 +12,7 @@ # Mandatory env vars, please set these: # GLUETUN_CONTROL_ENDPOINT # GLUETUN_HEALTH_ENDPOINT +# GLUETUN_CONTROL_API_KEY # TRANSMISSION_ENDPOINT # TRANSMISSION_USER # TRANSMISSION_PASS @@ -36,6 +37,7 @@ transmission_port_fail_count=0 required_vars=( GLUETUN_CONTROL_ENDPOINT + GLUETUN_CONTROL_API_KEY TRANSMISSION_ENDPOINT TRANSMISSION_USER TRANSMISSION_PASS @@ -101,7 +103,7 @@ get_transmission_port() { # get peer port from vpn via gluetun control server get_gluetun_port() { - gluetun_response=$(curl -s "$GLUETUN_CONTROL_ENDPOINT/v1/openvpn/portforwarded") + gluetun_response=$(curl -s -H "X-API-Key: $GLUETUN_CONTROL_API_KEY" "$GLUETUN_CONTROL_ENDPOINT/v1/openvpn/portforwarded") if [ "$gluetun_response" == "" ] || [ "$gluetun_response" == '{"port":0}' ]; then log "gluetun returned $gluetun_response, retrying ($gluetun_port_fail_count / $GLUETUN_PICK_NEW_SERVER_AFTER)..." return 1 @@ -124,11 +126,11 @@ check_transmission_port_open() { # pick a new gluetun server pick_new_gluetun_server() { log "asking gluetun to disconnect from $country_details", "s#$country_details#* OMITTED *#" - gluetun_server_response=$(curl -s -X PUT -d '{"status":"stopped"}' "$GLUETUN_CONTROL_ENDPOINT/v1/openvpn/status") || log "error instructing gluetun to pick new server ($gluetun_server_response)." - if echo "$gluetun_server_response" | grep -qE '{"outcome":"(stopping|stopped)"}'; then + gluetun_server_response=$(curl -s -H "X-API-Key: $GLUETUN_CONTROL_API_KEY" -X PUT -d '{"status":"stopped"}' "$GLUETUN_CONTROL_ENDPOINT/v1/openvpn/status") || log "error instructing gluetun to pick new server ($gluetun_server_response)." + if echo "$gluetun_server_response" | grep -qE '\{"outcome":"(stopping|stopped)"\}'; then log "bleh, gluetun server response is weird, expected {\"outcome\":\"stopping\"}, got $gluetun_server_response" return 1 - fi + fi # this is fixed as ~ around this time it takes for gluetun to reconnect, this avoids some nag in logs sleep 15 # just in case this takes longer than expected From 9e4f79e1fef56ea4315f7f6fc9586646649722cc Mon Sep 17 00:00:00 2001 From: Miklos Bagi Date: Sun, 26 Jan 2025 18:23:42 +0100 Subject: [PATCH 2/7] Add control server auth config #59 --- test/gluetun-config/config.toml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 test/gluetun-config/config.toml diff --git a/test/gluetun-config/config.toml b/test/gluetun-config/config.toml new file mode 100644 index 0000000..6731705 --- /dev/null +++ b/test/gluetun-config/config.toml @@ -0,0 +1,5 @@ +[[roles]] +name = "gluetrans" +routes = ["GET /v1/openvpn/portforwarded", "GET /v1/openvpn/status", "PUT /v1/openvpn/status"] +auth = "apikey" +apikey = "secret-apikey-for-gluetrans" \ No newline at end of file From a931b23b9367db66d70dd2f43a21664adc5c1ca8 Mon Sep 17 00:00:00 2001 From: Miklos Bagi Date: Sun, 26 Jan 2025 18:24:23 +0100 Subject: [PATCH 3/7] Bind control server auth config for gluetun and set api key for gluetrans #59 --- test/docker-compose-build.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/docker-compose-build.yaml b/test/docker-compose-build.yaml index 6f31716..232571a 100644 --- a/test/docker-compose-build.yaml +++ b/test/docker-compose-build.yaml @@ -13,6 +13,8 @@ services: SERVER_COUNTRIES: ${TEST_P_SVCS} VPN_PORT_FORWARDING: "on" VPN_PORT_FORWARDING_PROVIDER: protonvpn + volumes: + - ./gluetun-config/config.toml:/gluetun/auth/config.toml restart: unless-stopped devices: - /dev/net/tun:/dev/net/tun @@ -33,6 +35,7 @@ services: context: ../ environment: GLUETUN_CONTROL_ENDPOINT: http://localhost:8000 + GLUETUN_CONTROL_API_KEY: "secret-apikey-for-gluetrans" # must match the one in config.toml GLUETUN_HEALTH_ENDPOINT: http://localhost:9999 GLUETUN_PICK_NEW_SERVER_AFTER: 10 PEERPORT_CHECK_INTERVAL: 30 From 57480fe5a7fe30b90936c1e34e2d6ea64bea6a76 Mon Sep 17 00:00:00 2001 From: Miklos Bagi Date: Sun, 26 Jan 2025 18:52:26 +0100 Subject: [PATCH 4/7] Polish a little more on #61 --- entrypoint.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 12bbd5d..d0b56f6 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -127,8 +127,8 @@ check_transmission_port_open() { pick_new_gluetun_server() { log "asking gluetun to disconnect from $country_details", "s#$country_details#* OMITTED *#" gluetun_server_response=$(curl -s -H "X-API-Key: $GLUETUN_CONTROL_API_KEY" -X PUT -d '{"status":"stopped"}' "$GLUETUN_CONTROL_ENDPOINT/v1/openvpn/status") || log "error instructing gluetun to pick new server ($gluetun_server_response)." - if echo "$gluetun_server_response" | grep -qE '\{"outcome":"(stopping|stopped)"\}'; then - log "bleh, gluetun server response is weird, expected {\"outcome\":\"stopping\"}, got $gluetun_server_response" + if ! echo "$gluetun_server_response" | grep -qE '\{"outcome":"(stopping|stopped)"\}'; then + log "bleh, gluetun server response is weird, expected one of {\"outcome\":\"stopping\"} or {\"outcome\":\"stopped\"}, got $gluetun_server_response" return 1 fi # this is fixed as ~ around this time it takes for gluetun to reconnect, this avoids some nag in logs From ac3705e87b6f33ec4b49f3f8284c4807372f96fb Mon Sep 17 00:00:00 2001 From: Miklos Bagi Date: Sun, 26 Jan 2025 18:58:51 +0100 Subject: [PATCH 5/7] Update examples with control server auth, and set warning for breaking change --- README.md | 63 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 7758fcf..ae73f25 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,18 @@ Supported providers: - Private Internet Access - ProtonVPN -Supported gluetun versions: all between v3.35 and v3.39 (incl minor versions), see tests passing/failing above for latest. +Supported gluetun versions: all between v3.35 and v3.40 (incl minor versions), see tests passing/failing above for latest. (please note that there's no CI test for v3.35 as that version did not support protonvpn peer port back that time, but was tested and working with PIA). +> [!WARNING] +> Breaking change ahead: starting from gluetun 3.40.0+ versions, control server requires authentication. You can read more about this in [gluetun control server documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication).
+> Gluetrans, from version 0.3.5 and above provides support for this change, but an API key must be provided. Please [consult compose the examples](#docker-compose-examples) and [config.toml example](#gluetun-config.toml) below.

+> In short: +> 1. Set `GLUETUN_CONTROL_API_KEY` in your environment variables. +> 1. Create a role in gluetun's `config.toml` with the same API key. +> 1. Map `config.toml` to gluetun container. +> 1. Set the same API key in gluetrans' environment variables. + ## What does it do? 1. Waits for gluetun to report healthy 1. Checks gluetun's VPN Peer Port (via control server), and keep trying until it gets a valid port @@ -24,6 +33,7 @@ It keeps trying until you have a valid peer port. ## Environment variables Mandatory: - `GLUETUN_CONTROL_ENDPOINT`: Full Control Server URL with port, e.g.: `http://gluetun:8000`. +- `GLUETUN_CONTROL_API_KEY`: API key for the control server. This is requried from gluetun versions newer than v3.40.0. - `GLUETUN_HEALTH_ENDPOINT`: Full Health URL with port, `http://gluetun:9999` by default. - `TRANSMISSION_ENDPOINT` : Full Transmission RPC URL with port, service path, e.g.: `http://transmission:9091/transmission/rpc`. - `TRANSMISSION_USER`: Username for transmission RPC auth. @@ -39,6 +49,7 @@ Optional: Export the necessary variables, for example: ``` export GLUETUN_CONTROL_ENDPOINT=http://gluetun:8000 +export GLUETUN_CONTROL_API_KEY=your-secret-api-key export GLUETUN_HEALTH_ENDPOINT=http://gluetun:8080 export TRANSMISSION_ENDPOINT=http://transmission:9091/transmission/rpc export TRANSMISSION_USER=transmission @@ -56,6 +67,7 @@ Script logs to stdout, you can redirect it to a file if you want to with `./entr ``` docker run \ -e GLUETUN_CONTROL_ENDPOINT=http://gluetun:8000 \ +-e GLUETUN_CONTROL_API_KEY=your-secret-api-key \ -e GLUETUN_HEALTH_ENDPOINT=http://gluetun:8080 \ -e TRANSMISSION_ENDPOINT=http://transmission:9091/transmission/rpc \ -e TRANSMISSION_USER=transmission \ @@ -72,13 +84,15 @@ miklosbagi/gluetrans:latest docker run \ -e GLUETUN_CONTROL_ENDPOINT=http://gluetun:8000 \ -e GLUETUN_HEALTH_ENDPOINT=http://gluetun:8080 \ +-e GLUETUN_CONTROL_API_KEY=your-secret-api-key \ -e TRANSMISSION_ENDPOINT=http://transmission:9091/transmission/rpc \ -e TRANSMISSION_USER=transmission \ -e TRANSMISSION_PASS=transmission \ gluetrans:local ``` -## Docker-compose example with gluetun + transmission + piavpn +## Docker-compose examples +### PiaVPN (gluetun + transmission + piavpn) Please note that `data` directory will be created if this gets executed as is. Also, please note that we test against versions, not :latest, as that's like a weather report. @@ -100,6 +114,9 @@ services: SERVER_REGIONS: "FI Helsinki,France,Norway,SE Stockholm,Serbia" VPN_PORT_FORWARDING: on VPN_PORT_FORWARDING_PROVIDER: "private internet access" + # from gluetun v3.40.0+ control server auth, mapping config.toml with api key is required + volumes: + - ./gluetun-config/config.toml:/gluetun/auth/config.toml restart: unless-stopped # for ubuntu-latest, you may need: devices: @@ -124,6 +141,8 @@ services: environment: GLUETUN_CONTROL_ENDPOINT: http://localhost:8000 GLUETUN_HEALTH_ENDPOINT: http://localhost:9999 + # from gluetun v3.40.0+ control server auth key must be passed + GLUETUN_CONTROL_API_KEY: "secret-apikey-for-gluetrans" # must match the one in config.toml TRANSMISSION_ENDPOINT: http://localhost:9091/transmission/rpc TRANSMISSION_USER: My Transmission Username TRANSMISSION_PASS: My Transmission Password @@ -135,7 +154,7 @@ services: - gluetun ``` -## Gluetun configuration for protonvpn example (for gluetun v3.36 and later please) +### ProtonVPN (gluetun + transmission + protonvpn) (gluetun v3.36 and above only) Please note that `data` directory will be created if this gets executed as is. Also, please note that we test against versions, not :latest, as that's like a weather report. @@ -157,6 +176,9 @@ services: SERVER_COUNTRIES: "Romania,Poland,Netherlands,Moldova" VPN_PORT_FORWARDING: on VPN_PORT_FORWARDING_PROVIDER: "protonvpn" + # from gluetun v3.40.0+ control server auth, mapping config.toml with api key is required + volumes: + - ./gluetun-config/config.toml:/gluetun/auth/config.toml restart: unless-stopped # for ubuntu-latest, you may need: devices: @@ -168,23 +190,36 @@ services: Please note that the above is example for piavpn. Nightly tests are running against protonvpn provider, feel free to take a look into the compose file in test for a working example. +### Gluetun config.toml +For control server authentication, `config.toml` will be required to allow gluetrans to send authenticated requests to gluetun. +``` +[[roles]] +name = "gluetrans" +routes = ["GET /v1/openvpn/portforwarded", "PUT /v1/openvpn/status"] +auth = "apikey" +apikey = "secret-apikey-for-gluetrans" +``` + ## Debug `docker logs -f gluetrans` should reveal what's happening. ### Ideal scenario ``` GlueTrans starting... -Oct 10 10:10:11 [gt] waiting for gluetun to become active... -Oct 10 10:10:17 [gt] gluetun is active, country details: "123.123.1.12,UK,Belgrade,CODE Test DataCenterHost Inc." -Oct 10 10:10:17 [gt] monitoring... -Oct 10 10:10:47 [gt] gluetun returned {"port":0}, retrying (1 / 15)... -Oct 10 10:11:17 [gt] tramsmission returned '', retrying (1/15)... -Oct 10 10:11:47 [gt] tramsmission returned '', retrying (2/15)... -Oct 10 10:12:18 [gt] tramsmission returned '', retrying (3/15)... -Oct 10 10:12:48 [gt] port change detected: gluetun is 12345, transmission is 0, updating... -Oct 10 10:12:54 [gt] success: transmission port updated successfully. -Oct 10 10:13:23 [gt] country jump timer: 14 minutes left on this server. -Oct 10 10:13:24 [gt] heartbeat: gluetun & transmission ports match (12345), Port is open: Yes +Jan 26 17:43:11 [gt] waiting for gluetun to establish connection... +Jan 26 17:43:16 [gt] waiting for gluetun to establish connection... +Jan 26 17:43:21 [gt] gluetun is active, country details: Europe/Berlin, +Jan 26 17:43:21 [gt] monitoring... +Jan 26 17:45:43 [gt] country jump timer: 0 minute(s) left on this server. +Jan 26 17:45:43 [gt] port change detected: gluetun is 49198, transmission is 56864, Port is open: Yes updating... +Jan 26 17:45:48 [gt] success: transmission port updated successfully. +Jan 26 17:46:18 [gt] country jump timer: 0 minute(s) left on this server. +Jan 26 17:46:19 [gt] heartbeat: gluetun & transmission ports match (49198), Port is open: Yes +Jan 26 17:46:49 [gt] country jump timer: 0 minute(s) left on this server. +Jan 26 17:46:49 [gt] countryjump: forcing gluetun to pick a new server after 1 minute(s). +Jan 26 17:46:49 [gt] asking gluetun to disconnect from Europe/Berlin, +Jan 26 17:47:04 [gt] gluetun is active, country details: Europe/Paris, +... ``` Please note that this data is sanitized. From 2464c09930c3a4e9fefa9653fcdd88738e76dda7 Mon Sep 17 00:00:00 2001 From: Miklos Bagi Date: Sun, 26 Jan 2025 19:01:21 +0100 Subject: [PATCH 6/7] Fix config.toml anchor link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae73f25..fd94d96 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Supported gluetun versions: all between v3.35 and v3.40 (incl minor versions), s > [!WARNING] > Breaking change ahead: starting from gluetun 3.40.0+ versions, control server requires authentication. You can read more about this in [gluetun control server documentation](https://github.com/qdm12/gluetun-wiki/blob/main/setup/advanced/control-server.md#authentication).
-> Gluetrans, from version 0.3.5 and above provides support for this change, but an API key must be provided. Please [consult compose the examples](#docker-compose-examples) and [config.toml example](#gluetun-config.toml) below.

+> Gluetrans, from version 0.3.5 and above provides support for this change, but an API key must be provided. Please [consult compose the examples](#docker-compose-examples) and [config.toml example](#gluetun-configtoml) below.

> In short: > 1. Set `GLUETUN_CONTROL_API_KEY` in your environment variables. > 1. Create a role in gluetun's `config.toml` with the same API key. From 9b7151316c557ffe103aaf5983d5b504869fc764 Mon Sep 17 00:00:00 2001 From: Miklos Bagi Date: Sun, 26 Jan 2025 19:15:05 +0100 Subject: [PATCH 7/7] Remove v3.70 and v3.70.1 from autotests to fit into VPN funding limits --- .github/workflows/pr-check.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 872af69..2c7e123 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -39,20 +39,6 @@ jobs: - uses: actions/checkout@v3 - uses: ludeeus/action-shellcheck@2.0.0 - pr-check-against-3-37: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Test against Gluetun v3.37 - run: make GLUETUN_VERSION=v3.37 pr-test - - pr-check-against-3-37-1: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Test against Gluetun v3.37.1 - run: make GLUETUN_VERSION=v3.37.1 pr-test - pr-check-against-3-38: runs-on: ubuntu-latest steps: