Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(portforwarding): Allow running script upon port forwarding success #2399

Merged
merged 3 commits into from
Nov 10, 2024

Conversation

lavalleeale
Copy link
Contributor

@lavalleeale lavalleeale commented Aug 6, 2024

This PR allows an environment variable (VPN_PORT_FORWARDING_STATUS_SCRIPT) to be set that will run a script whenever there is an update to port forwarding status that could be used to sync with other programs that need to know what ports have been forwarded.

EDIT by qdm12:

Copy link
Owner

@qdm12 qdm12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thank you for this PR 👍

We need to notably:

  • change this to a run command (instead of script file)
  • make code ready for a down command (later 🙏, if anyone needs such command)
  • make a PR to the github wiki to document this (probably in the setup/advance/vpn-port-forwarding document) and mention the command is a single command, which doesn't understand shell specific syntax such as &&, and one should use /bin/sh -c "my shell syntax" to do so if they want (bash isn't installed by default, only sh)

Thanks!

@lavalleeale
Copy link
Contributor Author

Ok, I believe that I have resolved all the issues with the initial implementation, I am not a huge fan of comma separating the ports, but that is how the current code works to give maximum compatibility

Copy link
Owner

@qdm12 qdm12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job! 👍
Just 2 renames to do 😉
And once done I'll handle the using-that-command-package-and-plug-lines-to-the-logger. I just worked on it yesterday so it's still fresh in my mind 😉 !

@qdm12 qdm12 added the Status: 🟡 Nearly resolved This might be resolved or is about to be resolved label Aug 17, 2024
@qdm12
Copy link
Owner

qdm12 commented Aug 21, 2024

FYI I'm working on your branch right now, almost done rebasing+fixing the last feedback I left, so please hold 😉 Thanks!!

@qdm12
Copy link
Owner

qdm12 commented Aug 22, 2024

Hi @lavalleeale could you give me (force) push access to your Gluetun branch master? I'm done with the changes, just waiting to force push them there.

@thibautd
Copy link

thibautd commented Sep 2, 2024

Thanks for working on this, can't wait !

@iceteaSA
Copy link

Anything happening here?

@qdm12
Copy link
Owner

qdm12 commented Nov 8, 2024

@lavalleeale I still don't have push access to your fork, can you please allow force push access? Otherwise I'll create another PR with another branch, but would like to give you the credits for it ideally!

@lavalleeale
Copy link
Contributor Author

Done!

@qdm12
Copy link
Owner

qdm12 commented Nov 8, 2024

Thanks @lavalleeale
Just waiting for CI to pass, and I'll re-recheck my own still unresolved comments to make I've done them (has been a while already!).

@qdm12 qdm12 merged commit a035a15 into qdm12:master Nov 10, 2024
5 checks passed
@qdm12
Copy link
Owner

qdm12 commented Nov 12, 2024

Merged, thanks! I've tested it locally, it looks like it's working fine.
I also added VPN_PORT_FORWARDING_DOWN_COMMAND in the next commit, which does what its name says.
And also pushed f9bdb21 to support quoting better i.e. echo "hello" would previously be changed to echo "hello which would fail the parsing step, now it's fixed.

@KSmanis
Copy link

KSmanis commented Nov 12, 2024

@qdm12 Thanks for merging! I've already successfully migrated my setup from polling the control server to this hook, but I'd rather not follow the master branch. Any plans on a new release soon?

@thibautd
Copy link

For those wanting to use this new feature with Transmission, I wrote a simple Python script to automatically update the Peer Port in Transmission. It's written in Python and uses the uv package manager.

docker-compose.yml

services:
  gluetun:
    build: ./gluetun
    container_name: gluetun
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    environment:
      - Your other env vars here...
      - VPN_PORT_FORWARDING_UP_COMMAND=/bin/uv run --script /transmission-sync.py {{PORTS}}
    restart: unless-stopped
    networks:
      - internal
  transmission:
    image: lscr.io/linuxserver/transmission:latest
    container_name: transmission
    network_mode: "service:gluetun"
    volumes:
      - # Your volumes here
    restart: unless-stopped

I had to create a custom Docker image for gluetun to install Python, uv and my script inside:

gluetun/Dockerfile

FROM qmcgaw/gluetun:latest

RUN apk add --no-cache python3

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
COPY transmission-sync.py /

Finally, the Python script wich uses https://pypi.org/project/transmission-rpc/.

gluetun/transmission-sync.py

# /// script
# requires-python = ">=3.12"
# dependencies = [
#     "requests",
#     "transmission-rpc",
# ]
# ///

import sys
import requests
from transmission_rpc import Client

PORTS = [int(p) for p in sys.argv[1].split(",")]

print('Set port: ', PORTS)

CLIENT = Client(host="127.0.0.1", port=9091)
CLIENT.set_session(peer_port=PORTS[0])

print('Done')

I put that here in case it can be useful :-)

@Marsu31
Copy link

Marsu31 commented Dec 26, 2024

Thank you for this great feature !!! :-D
My 50 cents, for qbittorrent container:

VPN_PORT_FORWARDING_UP_COMMAND=wget -qO - --post-data "json={\"listen_port\":{{PORTS}}}" http://127.0.0.1:${QBITTORRENT_UI_PORT}/api/v2/app/setPreferences

Prerequisites:
Whitelist localhost connection in qbittorent options.
Have environment variable QBITTORRENT_UI_PORT set or replace by port.

Have a great holiday :-)

@rsiebertdev
Copy link

rsiebertdev commented Dec 26, 2024

Thanks @Marsu31 for your command. I hope y'all are enjoying your holiday! Here, I managed to simplify it a little 👇

VPN_PORT_FORWARDING_UP_COMMAND=wget -qO- --post-data=json={\"listen_port\":{{PORTS}}} http://127.0.0.1:8080/api/v2/app/setPreferences

If your Gluetun container starts before qBittorrent, the command will fail because there is no service to contact yet. personally have qBittorrent depend on Gluetun, and will not start until it's healthy.

qbittorrent:
    ...
    depends_on:
      gluetun:
        condition: service_healthy

For reliability, consider adding the --retry-connrefused and --tries=6 flags.

  • --retry-connrefused tells wget to retry if the address doesn't resolve (incorrect or likely down). Optionally, you can use the --waitretry flag to specify the time to wait in seconds between retries. By default, --retry-connrefused waits 1 second but doubles with each retry (1s → 2s → 4s → 8s ...).
  • --tries allows you to specify the maximum number of retries. I recommend setting this to 6, because --retry-connrefused doubles its wait between retries (unless specified otherwise) which totals to ~30 seconds worth of retry.

All in all, I'd suggest using this command 👇

VPN_PORT_FORWARDING_UP_COMMAND=wget --retry-connrefused --tries=6 -qO- --post-data=json={\"listen_port\":{{PORTS}}} http://127.0.0.1:8080/api/v2/app/setPreferences

Personally, instead of using the -qO- flag, I prefer to use -nv which gives you a less verbose output so you know what's going on, but Gluetun seems to interpret all outputs from the command as errors so 🤔

ERROR [port forwarding] failed: Connection refused.
ERROR [port forwarding] URL:http://127.0.0.1:8080/api/v2/app/setPreferences [0/0] -> "setPreferences" [4] *👈 not an error*

@redge76
Copy link

redge76 commented Dec 26, 2024

How do you guys handle the gluetun container restart ?
If qbittorrent is connected to the gluetun network, it lose connectivity until it is restarted.
Some background: https://stackoverflow.com/questions/47088261/restarting-an-unhealthy-docker-container-based-on-healthcheck
(the second option does not work with qbittorent ...)

@Marsu31
Copy link

Marsu31 commented Dec 27, 2024

Thank you @ramennbowls for your improvements ! :-)

The lack of logging made me not see the error you pointed out.

To see output not in "ERROR" category I had to surround the command with shell and redirect stderr like this:

VPN_PORT_FORWARDING_UP_COMMAND=/bin/sh -c '/usr/bin/wget -O- --retry-connrefused --post-data "json={\"listen_port\":{{PORTS}}}" http://127.0.0.1:${QBITTORRENT_UI_PORT}/api/v2/app/setPreferences 2>&1'

I don't use -nv nor -q to be sure to see something. It doesn't happen often, also there is no performance problem (for me ;-) ).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature request: Webhook call when forwarded port change
8 participants