containers / podman

Podman: A tool for managing OCI containers and pods.
https://podman.io
Apache License 2.0
23.05k stars 2.35k forks source link

Connectivity issue for rootless qbittorrent container using pasta driver #23739

Open psyke83 opened 2 weeks ago

psyke83 commented 2 weeks ago

Issue Description

It seems that qbittorrent running rootless via the default pasta driver (specifically if launched via podman compose or a quadlet) has trouble acquiring an external IP, which breaks DHT connectivity. Reverting to the slirp4netns driver fixes the issue for compose/quadlet invocations, and running qbittorrent via command-line using otherwise identical arguments also seems to work OK.

Steps to reproduce the issue

Steps to reproduce the issue

  1. After starting the qbittorrent container, navigate to web UI, then enable Logs in View menu. Click on Logs tab and check output for any line(s) matching Detected external IP: xxx.xxx.xxx.xxx. Additionally, watch the DHT node count at bottom of the web UI.

  2. For testing the command-line invocation:

    podman run -d \
    --name=qbittorrent \
    -e PUID=1000 \
    -e PGID=1000 \
    -e TZ=Etc/UTC \
    -e WEBUI_PORT=8080 \
    -e TORRENTING_PORT=6881 \
    -p 8080:8080 \
    -p 6881:6881 \
    -p 6881:6881/udp \
    -v ~/docker/qbittorrent/config:/config \
    --restart unless-stopped \
    lscr.io/linuxserver/qbittorrent:latest
  3. Compose definition (same effect if converted to a quadlet):

    services:
    qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
      - WEBUI_PORT=8080
      - TORRENTING_PORT=6881
    volumes:
      - ~/docker/qbittorrent/config:/config
    ports:
      - 8080:8080
      - 6881:6881
      - 6881:6881/udp
    restart: unless-stopped

Describe the results you received

When launched via command-line, external IP is resolved and DHT count will increase as normal. The pasta process will show these arguments:

/usr/bin/pasta --config-net -t 6881-6881:6881-6881 -t 8080-8080:8080-8080 -u 6881-6881:6881-6881 --dns-forward 169.254.0.1 -T none -U none --no-map-gw --quiet --netns /run/user/1000/netns/netns-5f81f8cc-b7b7-c851-af04-c24e80a4fddb

When launched via quadlet or compose with the default pasta driver, the external IP is not resolved in 95% of cases, and DHT count remains at 0. In some rare cases, the external IP is resolved after an extended delay, but the DHT count does not increase at the expected rate. Pasta process will show:

/usr/bin/pasta --config-net --pid /run/user/1000/containers/networks/rootless-netns/rootless-netns-conn.pid --dns-forward 169.254.0.1 -t none -u none -T none -U none --no-map-gw --quiet --netns /run/user/1000/containers/networks/rootless-netns/rootless-netns

When launched via quadlet/compose and default_rootless_network_cmd is set to slirp4netns, external IP resolution and DHT works correctly at all times.

Describe the results you expected

External IP and DHT connectivity should be working in all configurations.

podman info output

$ podman info
host:
  arch: amd64
  buildahVersion: 1.37.2
  cgroupControllers:
  - memory
  - pids
  cgroupManager: systemd
  cgroupVersion: v2
  conmon:
    package: conmon-1:2.1.12-1
    path: /usr/bin/conmon
    version: 'conmon version 2.1.12, commit: e8896631295ccb0bfdda4284f1751be19b483264'
  cpuUtilization:
    idlePercent: 87.55
    systemPercent: 4.06
    userPercent: 8.39
  cpus: 4
  databaseBackend: sqlite
  distribution:
    distribution: arch
    version: unknown
  eventLogger: journald
  freeLocks: 2039
  hostname: hp255g7-arch
  idMappings:
    gidmap:
    - container_id: 0
      host_id: 1000
      size: 1
    - container_id: 1
      host_id: 100000
      size: 65536
    uidmap:
    - container_id: 0
      host_id: 1000
      size: 1
    - container_id: 1
      host_id: 100000
      size: 65536
  kernel: 6.10.6-zen1-1-zen
  linkmode: dynamic
  logDriver: journald
  memFree: 684138496
  memTotal: 7173124096
  networkBackend: netavark
  networkBackendInfo:
    backend: netavark
    dns:
      package: aardvark-dns-1.12.1-1
      path: /usr/lib/podman/aardvark-dns
      version: aardvark-dns 1.12.1
    package: netavark-1.12.2-1
    path: /usr/lib/podman/netavark
    version: netavark 1.12.2
  ociRuntime:
    name: crun
    package: crun-1.16.1-1
    path: /usr/bin/crun
    version: |-
      crun version 1.16.1
      commit: afa829ca0122bd5e1d67f1f38e6cc348027e3c32
      rundir: /run/user/1000/crun
      spec: 1.0.0
      +SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +CRIU +YAJL
  os: linux
  pasta:
    executable: /usr/bin/pasta
    package: passt-2024_08_21.1d6142f-1
    version: |
      pasta 2024_08_21.1d6142f
      Copyright Red Hat
      GNU General Public License, version 2 or later
        <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
      This is free software: you are free to change and redistribute it.
      There is NO WARRANTY, to the extent permitted by law.
  remoteSocket:
    exists: false
    path: /run/user/1000/podman/podman.sock
  rootlessNetworkCmd: pasta
  security:
    apparmorEnabled: false
    capabilities: CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT
    rootless: true
    seccompEnabled: true
    seccompProfilePath: /etc/containers/seccomp.json
    selinuxEnabled: false
  serviceIsRemote: false
  slirp4netns:
    executable: /usr/bin/slirp4netns
    package: slirp4netns-1.3.1-1
    version: |-
      slirp4netns version 1.3.1
      commit: e5e368c4f5db6ae75c2fce786e31eef9da6bf236
      libslirp: 4.8.0
      SLIRP_CONFIG_VERSION_MAX: 5
      libseccomp: 2.5.5
  swapFree: 2815983616
  swapTotal: 3586125824
  uptime: 10h 44m 20.00s (Approximately 0.42 days)
  variant: ""
plugins:
  authorization: null
  log:
  - k8s-file
  - none
  - passthrough
  - journald
  network:
  - bridge
  - macvlan
  - ipvlan
  volume:
  - local
registries: {}
store:
  configFile: /home/conn/.config/containers/storage.conf
  containerStore:
    number: 3
    paused: 0
    running: 1
    stopped: 2
  graphDriverName: overlay
  graphOptions: {}
  graphRoot: /home/conn/.local/share/containers/storage
  graphRootAllocated: 392575868928
  graphRootUsed: 166278561792
  graphStatus:
    Backing Filesystem: extfs
    Native Overlay Diff: "true"
    Supports d_type: "true"
    Supports shifting: "false"
    Supports volatile: "true"
    Using metacopy: "false"
  imageCopyTmpDir: /var/tmp
  imageStore:
    number: 11
  runRoot: /run/user/1000/containers
  transientStore: false
  volumePath: /home/conn/.local/share/containers/storage/volumes
version:
  APIVersion: 5.2.2
  Built: 1724352649
  BuiltTime: Thu Aug 22 19:50:49 2024
  GitCommit: fcee48106a12dd531702d729d17f40f6e152027f
  GoVersion: go1.23.0
  Os: linux
  OsArch: linux/amd64
  Version: 5.2.2


### Podman in a container

No

### Privileged Or Rootless

Rootless

### Upstream Latest Release

Yes

### Additional environment details

Arch Linux x86_64.

### Additional information

I can reproduce the exact same results with the same podman/pasta version on Arch Linux ARM aarch64 running on a Raspberry Pi 4.
sbrivio-rh commented 2 weeks ago

When launched via quadlet or compose with the default pasta driver [...] Pasta process will show:

/usr/bin/pasta --config-net --pid /run/user/1000/containers/networks/rootless-netns/rootless-netns-conn.pid --dns-forward 169.254.0.1 -t none -u none -T none -U none --no-map-gw --quiet --netns /run/user/1000/containers/networks/rootless-netns/rootless-netns

For some reason, ports are not forwarded at all (you get -t 6881-6881:6881-6881 -t 8080-8080:8080-8080 -u 6881-6881:6881-6881 -T none -U none when started by command line).

psyke83 commented 2 weeks ago

When launched via quadlet or compose with the default pasta driver [...] Pasta process will show:

/usr/bin/pasta --config-net --pid /run/user/1000/containers/networks/rootless-netns/rootless-netns-conn.pid --dns-forward 169.254.0.1 -t none -u none -T none -U none --no-map-gw --quiet --netns /run/user/1000/containers/networks/rootless-netns/rootless-netns

For some reason, ports are not forwarded at all (you get -t 6881-6881:6881-6881 -t 8080-8080:8080-8080 -u 6881-6881:6881-6881 -T none -U none when started by command line).

Yes, I noticed this discrepancy, but I'm not certain how pasta is supposed to operate in bridged mode (which seems to be the main networking difference between quadlet/compose vs command line invocation).

I tested the following:

  1. pasta_options = ["-t", "6881-6881:6881-6881", "-t", "8080-8080:8080-8080", "-u", "6881-6881:6881-6881"] This results in the following error:
    Error: rootlessport listen tcp 0.0.0.0:6881: bind: address already in use
    Error: unable to start container "a1dcbf164f52ced90452666254b5d00005ce238e940fc1d228acf5b04034910d": rootlessport listen tcp 0.0.0.0:6881: bind: address already in use
  2. pasta_options = ["-t", "auto", "-u", "auto"] Process spawns with the following arguments, but unfortunately does not improve the issue:
    conn        4716  0.2  0.2  71932 15508 ?        Ss   15:24   0:00 /usr/bin/pasta --config-net -t auto -u auto --pid /run/user/1000/containers/networks/rootless-netns/rootless-netns-conn.pid --dns-forward 169.254.0.1 -T none -U none --no-map-gw --quiet --netns /run/user/1000/containers/networks/rootless-netns/rootless-netns
Luap99 commented 2 weeks ago

The bridge mode is special and never uses pasta for port forwarding, i.e. see https://github.com/containers/podman/discussions/22943#discussioncomment-9795883. But slirp4netns works in the same way so I do not see how this would cause any of this, i.e. port forwarding source ip is wrong (https://github.com/containers/podman/issues/8193).

How does qbittorrent actually try to figure out its external ip address?

psyke83 commented 2 weeks ago

I'm not well-versed on qBittorrent development, but my hunch is that it retrieves the ip address through libtorrent. So it would likely be this function which calls external_address() in libtorrent.

Although my test case doesn't apply (as I didn't set up an IPv6-enabled nework in the compose definition), after further testing I can see that rootless bridge mode has an issue resolving my IPv6 address even with slirp4netns.

In summary: