Kubuntu 26.04, aMule 3.xxx más Proton VPN y sus ports forwarding y Claude

ACTUALIZADO: El script tiene un fallo y es que no actualiza el puerto UDP que usa Kad. Os dejo los dos por si alguien quiere estudiarlo.

Como dice el título del hilo uso el nuevo aMule 3 con Proton VPN que posibilita asignar un puerto aleatorio (el que Proton VPN te de) para que el P2P como el de aMule funcione bien. El caso es que aunque configurase los puertos en aMule cada vez que estos cambian en Proton VPN siempre me daba ID baja así que me dio por preguntarle a Claude y la solución que me ha dado es abrir los puertos en ufw, pero claro, hacer esto cada vez que Proton VPN te reasigne un puerto nuevo es engorroso y Claude me ha propuesto crear varios scripts para automatizar la apertura de los puertos que asigne Proton VPN en ufw y actualizar automáticamente aMule. Os paso todo el proceso por si os interesa y de paso por si podéis o queréis aportar algo a los scripts

AQUÍ HAY UN FALLO: amule-port-sync.service no actualiza el puerto UDP de aMule

# Solución: ID baja en aMule con Proton VPN (Linux)

## Contexto del problema

aMule daba **ID baja** (y Kad en estado "tras cortafuegos") a pesar de tener el
puerto de aMule configurado con el mismo número que el puerto activo de port
forwarding de Proton VPN.

## Diagnóstico

1. **Puerto TCP configurado en aMule** coincidía con el puerto forwardeado por Proton — correcto.
2. **`ss -tlnp | grep <puerto>`** confirmó que aMule escuchaba en `0.0.0.0:<puerto>` (todas las interfaces) — correcto.
3. **Causa real encontrada:** `ufw` (firewall local de Ubuntu) tenía política por defecto
`deny (entrantes)`, y bloqueaba el tráfico entrante en la interfaz de la VPN
(`proton0`) antes de que llegara a aMule. Proton reenviaba el puerto
perfectamente en su lado, pero el propio firewall del equipo lo descartaba.

### Nota sobre los puertos UDP de aMule

Proton VPN abre **un único número de puerto**, válido tanto para TCP como para UDP.
En Preferencias → Conexión de aMule aparecen tres campos:

| Campo | Ejemplo | ¿Forwardeado por Proton? |
|---|---|---|
| Puerto TCP estándar | 58463 | Sí |
| Puerto UDP servidor (TCP+3) | 58466 | **No** (no se necesita) |
| Puerto UDP Kad / búsqueda global | 58463 | Sí (coincide con el TCP) |

Solo hace falta abrir en el firewall el puerto TCP y su mismo número en UDP —
el puerto "TCP+3" es un cálculo interno de aMule/eMule que no llega a usarse
realmente a través de Proton.

## Solución aplicada

### 1. Regla de firewall (una vez, manual, para desatascar el problema)

```bash
sudo ufw allow in on proton0 to any port <PUERTO> proto tcp
sudo ufw allow in on proton0 to any port <PUERTO> proto udp
```

Con esto se restablecía el ID alto tras reconectar el servidor eD2K y Kad en aMule.

### 2. Automatización — el puerto de Proton cambia en cada reconexión

Proton reasigna el puerto forwardeado cada vez que se reconecta la VPN, así que
hubo que automatizar dos cosas:

- Mantener las reglas de `ufw` sincronizadas con el puerto activo.
- Mantener `amule.conf` actualizado y reiniciar aMule cuando cambia el puerto.

Se crearon **dos servicios systemd independientes**:

#### A) `proton-ufw-sync` (servicio de sistema, root)

Vigila el archivo que Proton escribe con el puerto activo y actualiza `ufw`
en consecuencia. Es **idempotente y autorreparable**: en cada ciclo (15s) vuelve
a pedir a `ufw` que permita el puerto actual, sin depender de recordar si ya lo
hizo antes — así se recupera solo si las reglas se pierden por cualquier motivo
(por ejemplo, tras un reinicio del sistema).

- Script: `/usr/local/bin/proton-ufw-sync.sh`
- Servicio: `/etc/systemd/system/proton-ufw-sync.service`

**Crear el script:**

```bash
sudo nano /usr/local/bin/proton-ufw-sync.sh
```

Pega el siguiente contenido, guarda (`Ctrl+O`, `Enter`) y sal (`Ctrl+X`):

```bash
#!/usr/bin/env bash
set -euo pipefail

TARGET_USER="tu_usuario"
USER_UID=$(id -u "$TARGET_USER")
PORT_FILE="/run/user/$USER_UID/Proton/VPN/forwarded_port"
IFACE="proton0"
STATE_FILE="/var/lib/proton-ufw-sync/last_port"

mkdir -p "$(dirname "$STATE_FILE")"

apply_port() {
local new_port="$1"
local old_port=""
[[ -f "$STATE_FILE" ]] && old_port=$(cat "$STATE_FILE")

# Si el puerto cambió, borra la regla vieja
if [[ -n "$old_port" && "$old_port" != "$new_port" ]]; then
ufw delete allow in on "$IFACE" to any port "$old_port" proto tcp >/dev/null 2>&1 || true
ufw delete allow in on "$IFACE" to any port "$old_port" proto udp >/dev/null 2>&1 || true
logger -t proton-ufw-sync "Puerto cambiado: ${old_port} -> ${new_port}"
fi

# ufw es idempotente: si la regla ya existe la ignora, si falta la crea.
# Así nos autorreparamos ante cualquier pérdida de reglas (reinicio, etc.)
# sin necesidad de comprobar nada nosotros mismos.
ufw allow in on "$IFACE" to any port "$new_port" proto tcp >/dev/null 2>&1
ufw allow in on "$IFACE" to any port "$new_port" proto udp >/dev/null 2>&1

if [[ "$old_port" != "$new_port" ]]; then
logger -t proton-ufw-sync "Puerto ${new_port} asegurado en ufw"
fi

echo "$new_port" > "$STATE_FILE"
}

while true; do
if [[ -f "$PORT_FILE" ]]; then
apply_port "$(cat "$PORT_FILE")"
fi
sleep 15
done
```

**Crear el servicio:**

```bash
sudo nano /etc/systemd/system/proton-ufw-sync.service
```

Pega el siguiente contenido, guarda (`Ctrl+O`, `Enter`) y sal (`Ctrl+X`):

```ini
[Unit]
Description=Sincroniza reglas de ufw con el puerto forwardeado de Proton VPN
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/proton-ufw-sync.sh
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

Instalación:

```bash
sudo chmod +x /usr/local/bin/proton-ufw-sync.sh
sudo systemctl daemon-reload
sudo systemctl enable --now proton-ufw-sync.service
```

#### B) `amule-port-sync` (servicio de usuario, sin root)

Vigila el mismo archivo de puerto de Proton y, cuando cambia, actualiza
`~/.aMule/amule.conf` (claves `Port` y `UDPPort`) y reinicia aMule para que
tome el nuevo valor.

- Script: `/home/tu_usuario/bin/amule-port-sync.sh`
- Servicio: `/home/tu_usuario/.config/systemd/user/amule-port-sync.service`

**Crear el script:**

```bash
mkdir -p ~/bin
nano ~/bin/amule-port-sync.sh
```

Pega el siguiente contenido, guarda (`Ctrl+O`, `Enter`) y sal (`Ctrl+X`):

```bash
#!/usr/bin/env bash
set -euo pipefail

PORT_FILE="/run/user/$(id -u)/Proton/VPN/forwarded_port"
AMULE_CONF="$HOME/.aMule/amule.conf"
STATE_FILE="$HOME/.cache/amule-port-sync-last"

mkdir -p "$(dirname "$STATE_FILE")"

restart_amule() {
if pgrep -x amule >/dev/null; then
pkill -TERM -x amule
for i in $(seq 1 20); do
pgrep -x amule >/dev/null || break
sleep 1
done
fi
setsid amule >/dev/null 2>&1 &
disown
}

apply_port() {
local new_port="$1"
sed -i "s/^Port=.*/Port=${new_port}/" "$AMULE_CONF"
sed -i "s/^UDPPort=.*/UDPPort=$((new_port + 3))/" "$AMULE_CONF"
echo "$new_port" > "$STATE_FILE"
logger -t amule-port-sync "Puerto actualizado a ${new_port}, reiniciando aMule"
restart_amule
}

while true; do
if [[ -f "$PORT_FILE" ]]; then
current=$(cat "$PORT_FILE")
last=""
[[ -f "$STATE_FILE" ]] && last=$(cat "$STATE_FILE")
if [[ "$current" != "$last" ]]; then
apply_port "$current"
fi
fi
sleep 15
done
```

**Crear el servicio:**

```bash
mkdir -p ~/.config/systemd/user
nano ~/.config/systemd/user/amule-port-sync.service
```

Pega el siguiente contenido, guarda (`Ctrl+O`, `Enter`) y sal (`Ctrl+X`):

```ini
[Unit]
Description=Sincroniza el puerto de aMule con el forwarding de Proton VPN
After=graphical-session.target

[Service]
Type=simple
ExecStart=%h/bin/amule-port-sync.sh
Restart=always
RestartSec=5

[Install]
WantedBy=default.target
```

Instalación:

```bash
mkdir -p ~/bin ~/.config/systemd/user
chmod +x ~/bin/amule-port-sync.sh
systemctl --user daemon-reload
systemctl --user enable --now amule-port-sync.service
```

## Resultado final

- Proton VPN asigna un puerto (cambia en cada reconexión).
- `proton-ufw-sync` (root) sincroniza `ufw` automáticamente, autorreparándose si
las reglas se pierden por cualquier motivo.
- `amule-port-sync` (usuario) actualiza `amule.conf` y reinicia aMule con el
puerto correcto.
- Ya no hace falta tocar `ufw` ni la configuración de aMule manualmente.

## Comandos de diagnóstico útiles (para el futuro)

```bash
# Puerto activo según Proton ahora mismo
cat /run/user/$(id -u)/Proton/VPN/forwarded_port

# ¿aMule escucha en todas las interfaces con ese puerto?
ss -tlnp | grep <PUERTO>

# Estado y reglas actuales de ufw
sudo ufw status verbose

# Logs de los dos servicios
sudo journalctl -t proton-ufw-sync --no-pager -n 20
journalctl --user -u amule-port-sync --no-pager -n 20

# Estado de los servicios
sudo systemctl status proton-ufw-sync.service
systemctl --user status amule-port-sync.service
```

## Qué revisar tras una actualización de aMule

```bash
# Confirma que el binario sigue llamándose igual (lo usan pgrep/pkill)
which amule

# Confirma que la config sigue en la misma ruta con las mismas claves
grep -nE "^(Port|UDPPort)=" ~/.aMule/amule.conf
```


Resumen del fallo, en corto:

El campo de la GUI "Puerto UDP adicional (Kad/búsqueda global)" se guarda en amule.conf bajo la clave UDPPort= — la misma clave que, por su nombre y posición en el menú, parecía corresponder al "puerto UDP para peticiones del servidor (TCP+3)" (que en realidad no se persiste nunca, es solo informativo).

El script original asumía esa relación incorrecta y hacía:

bash
UDPPort=$((new_port + 3))


cuando en realidad UDPPort debe ser idéntico al puerto TCP, porque Proton reenvía un único número de puerto válido para ambos protocolos. Al escribir sistemáticamente TCP+3 en ese campo, quedaba fuera del rango que Proton realmente tenía abierto.

Lo confirmamos de forma empírica (cambiando el campo desde la GUI a un valor distintivo y viendo en qué clave del archivo aparecía), y lo corregimos quitando el +3.

AQUí amule-port-sync.service funciona correctamente

# Solución: ID baja en aMule con Proton VPN (Linux)

## Contexto del problema

aMule daba **ID baja** (y Kad en estado "tras cortafuegos") a pesar de tener el
puerto de aMule configurado con el mismo número que el puerto activo de port
forwarding de Proton VPN.

## Diagnóstico

1. **Puerto TCP configurado en aMule** coincidía con el puerto forwardeado por Proton — correcto.
2. **`ss -tlnp | grep <puerto>`** confirmó que aMule escuchaba en `0.0.0.0:<puerto>` (todas las interfaces) — correcto.
3. **Causa real encontrada:** `ufw` (firewall local de Ubuntu) tenía política por defecto
`deny (entrantes)`, y bloqueaba el tráfico entrante en la interfaz de la VPN
(`proton0`) antes de que llegara a aMule. Proton reenviaba el puerto
perfectamente en su lado, pero el propio firewall del equipo lo descartaba.

### Nota sobre los puertos UDP de aMule

Proton VPN abre **un único número de puerto**, válido tanto para TCP como para UDP.
En Preferencias → Conexión de aMule aparecen tres campos:

| Campo | Ejemplo | ¿Forwardeado por Proton? | ¿Se guarda en `amule.conf`? |
|---|---|---|---|
| Puerto TCP estándar | 58463 | Sí | `Port=` |
| Puerto UDP servidor (TCP+3) | 58466 | No (no se necesita) | No — es puramente informativo, aMule lo calcula en tiempo real y nunca lo persiste |
| Puerto UDP adicional (Kad/búsqueda global) | 58463 | Sí (debe coincidir con el TCP) | **`UDPPort=`** |

**Importante:** el campo "Puerto UDP adicional (Kad/búsqueda global)" de la
interfaz corresponde a la clave `UDPPort=` en `amule.conf` — no al "TCP+3"
como podría parecer por su posición en el menú. Este dato se confirmó
empíricamente: al escribir un valor distintivo en ese campo desde la GUI y
cerrar aMule, ese mismo valor apareció en la clave `UDPPort=` del archivo.

Como Proton reenvía el **mismo número** para TCP y UDP, `UDPPort` debe fijarse
siempre **igual** al puerto TCP — nunca a TCP+3. Un primer intento del script
de automatización calculaba mal este valor (`TCP+3` en vez de `TCP`), lo que
producía una desincronización silenciosa del lado UDP aunque el TCP
funcionara correctamente. La versión corregida más abajo ya lo fija al valor
correcto.

## Solución aplicada

### 1. Regla de firewall (una vez, manual, para desatascar el problema)

```bash
sudo ufw allow in on proton0 to any port <PUERTO> proto tcp
sudo ufw allow in on proton0 to any port <PUERTO> proto udp
```

Con esto se restablecía el ID alto tras reconectar el servidor eD2K y Kad en aMule.

### 2. Automatización — el puerto de Proton cambia en cada reconexión

Proton reasigna el puerto forwardeado cada vez que se reconecta la VPN, así que
hubo que automatizar dos cosas:

- Mantener las reglas de `ufw` sincronizadas con el puerto activo.
- Mantener `amule.conf` actualizado y reiniciar aMule cuando cambia el puerto.

Se crearon **dos servicios systemd independientes**:

#### A) `proton-ufw-sync` (servicio de sistema, root)

Vigila el archivo que Proton escribe con el puerto activo y actualiza `ufw`
en consecuencia. Es **idempotente y autorreparable**: en cada ciclo (15s) vuelve
a pedir a `ufw` que permita el puerto actual, sin depender de recordar si ya lo
hizo antes — así se recupera solo si las reglas se pierden por cualquier motivo
(por ejemplo, tras un reinicio del sistema).

- Script: `/usr/local/bin/proton-ufw-sync.sh`
- Servicio: `/etc/systemd/system/proton-ufw-sync.service`

**Crear el script:**

```bash
sudo nano /usr/local/bin/proton-ufw-sync.sh
```

Pega el siguiente contenido, guarda (`Ctrl+O`, `Enter`) y sal (`Ctrl+X`):

```bash
#!/usr/bin/env bash
set -euo pipefail

TARGET_USER="tu_usuario"
USER_UID=$(id -u "$TARGET_USER")
PORT_FILE="/run/user/$USER_UID/Proton/VPN/forwarded_port"
IFACE="proton0"
STATE_FILE="/var/lib/proton-ufw-sync/last_port"

mkdir -p "$(dirname "$STATE_FILE")"

apply_port() {
local new_port="$1"
local old_port=""
[[ -f "$STATE_FILE" ]] && old_port=$(cat "$STATE_FILE")

# Si el puerto cambió, borra la regla vieja
if [[ -n "$old_port" && "$old_port" != "$new_port" ]]; then
ufw delete allow in on "$IFACE" to any port "$old_port" proto tcp >/dev/null 2>&1 || true
ufw delete allow in on "$IFACE" to any port "$old_port" proto udp >/dev/null 2>&1 || true
logger -t proton-ufw-sync "Puerto cambiado: ${old_port} -> ${new_port}"
fi

# ufw es idempotente: si la regla ya existe la ignora, si falta la crea.
# Así nos autorreparamos ante cualquier pérdida de reglas (reinicio, etc.)
# sin necesidad de comprobar nada nosotros mismos.
ufw allow in on "$IFACE" to any port "$new_port" proto tcp >/dev/null 2>&1
ufw allow in on "$IFACE" to any port "$new_port" proto udp >/dev/null 2>&1

if [[ "$old_port" != "$new_port" ]]; then
logger -t proton-ufw-sync "Puerto ${new_port} asegurado en ufw"
fi

echo "$new_port" > "$STATE_FILE"
}

while true; do
if [[ -f "$PORT_FILE" ]]; then
apply_port "$(cat "$PORT_FILE")"
fi
sleep 15
done
```

**Crear el servicio:**

```bash
sudo nano /etc/systemd/system/proton-ufw-sync.service
```

Pega el siguiente contenido, guarda (`Ctrl+O`, `Enter`) y sal (`Ctrl+X`):

```ini
[Unit]
Description=Sincroniza reglas de ufw con el puerto forwardeado de Proton VPN
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/proton-ufw-sync.sh
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

Instalación:

```bash
sudo chmod +x /usr/local/bin/proton-ufw-sync.sh
sudo systemctl daemon-reload
sudo systemctl enable --now proton-ufw-sync.service
```

#### B) `amule-port-sync` (servicio de usuario, sin root)

Vigila el mismo archivo de puerto de Proton y, cuando cambia, actualiza
`~/.aMule/amule.conf` (claves `Port` y `UDPPort`) y reinicia aMule para que
tome el nuevo valor.

- Script: `/home/tu_usuario/bin/amule-port-sync.sh`
- Servicio: `/home/tu_usuario/.config/systemd/user/amule-port-sync.service`

**Crear el script:**

```bash
mkdir -p ~/bin
nano ~/bin/amule-port-sync.sh
```

Pega el siguiente contenido, guarda (`Ctrl+O`, `Enter`) y sal (`Ctrl+X`):

```bash
#!/usr/bin/env bash
set -euo pipefail

PORT_FILE="/run/user/$(id -u)/Proton/VPN/forwarded_port"
AMULE_CONF="$HOME/.aMule/amule.conf"
STATE_FILE="$HOME/.cache/amule-port-sync-last"

mkdir -p "$(dirname "$STATE_FILE")"

restart_amule() {
if pgrep -x amule >/dev/null; then
pkill -TERM -x amule
for i in $(seq 1 20); do
pgrep -x amule >/dev/null || break
sleep 1
done
fi
setsid amule >/dev/null 2>&1 &
disown
}

apply_port() {
local new_port="$1"
# UDPPort = campo "Puerto UDP adicional (Kad/búsqueda global)" en la GUI.
# Debe coincidir EXACTAMENTE con el puerto TCP (Proton reenvía el mismo
# número para TCP y UDP). No sumar nada aquí.
sed -i "s/^Port=.*/Port=${new_port}/" "$AMULE_CONF"
sed -i "s/^UDPPort=.*/UDPPort=${new_port}/" "$AMULE_CONF"
echo "$new_port" > "$STATE_FILE"
logger -t amule-port-sync "Puerto actualizado a ${new_port}, reiniciando aMule"
restart_amule
}

while true; do
if [[ -f "$PORT_FILE" ]]; then
current=$(cat "$PORT_FILE")
last=""
[[ -f "$STATE_FILE" ]] && last=$(cat "$STATE_FILE")
if [[ "$current" != "$last" ]]; then
apply_port "$current"
fi
fi
sleep 15
done
```

**Crear el servicio:**

```bash
mkdir -p ~/.config/systemd/user
nano ~/.config/systemd/user/amule-port-sync.service
```

Pega el siguiente contenido, guarda (`Ctrl+O`, `Enter`) y sal (`Ctrl+X`):

```ini
[Unit]
Description=Sincroniza el puerto de aMule con el forwarding de Proton VPN
After=graphical-session.target

[Service]
Type=simple
ExecStart=%h/bin/amule-port-sync.sh
Restart=always
RestartSec=5

[Install]
WantedBy=default.target
```

Instalación:

```bash
mkdir -p ~/bin ~/.config/systemd/user
chmod +x ~/bin/amule-port-sync.sh
systemctl --user daemon-reload
systemctl --user enable --now amule-port-sync.service
```

## Resultado final

- Proton VPN asigna un puerto (cambia en cada reconexión).
- `proton-ufw-sync` (root) sincroniza `ufw` automáticamente, autorreparándose si
las reglas se pierden por cualquier motivo.
- `amule-port-sync` (usuario) actualiza `amule.conf` y reinicia aMule con el
puerto correcto.
- Ya no hace falta tocar `ufw` ni la configuración de aMule manualmente.

## Comandos de diagnóstico útiles (para el futuro)

```bash
# Puerto activo según Proton ahora mismo
cat /run/user/$(id -u)/Proton/VPN/forwarded_port

# ¿aMule escucha en todas las interfaces con ese puerto?
ss -tlnp | grep <PUERTO>

# Estado y reglas actuales de ufw
sudo ufw status verbose

# Logs de los dos servicios
sudo journalctl -t proton-ufw-sync --no-pager -n 20
journalctl --user -u amule-port-sync --no-pager -n 20

# Estado de los servicios
sudo systemctl status proton-ufw-sync.service
systemctl --user status amule-port-sync.service
```

## Qué revisar tras una actualización de aMule

```bash
# Confirma que el binario sigue llamándose igual (lo usan pgrep/pkill)
which amule

# Confirma que la config sigue en la misma ruta con las mismas claves
grep -nE "^(Port|UDPPort)=" ~/.aMule/amule.conf
```

Si ambos comandos devuelven lo esperado, no hay que tocar nada. Si la ruta del
config o el nombre de las claves cambiara en una actualización mayor, habría
que ajustar `AMULE_CONF` y las líneas `sed` en `amule-port-sync.sh` en consecuencia.


Si ambos comandos devuelven lo esperado, no hay que tocar nada. Si la ruta del
config o el nombre de las claves cambiara en una actualización mayor, habría
que ajustar `AMULE_CONF` y las líneas `sed` en `amule-port-sync.sh` en consecuencia.[/spoiler]
Solo decir que, de momento, funciona bien.
¿Cómo lo veis? ¿Algo que añadir y/o mejorar?

Lo he editado añadiendo los comandos nano para la creación de los scripts
Aunque el emule lo uso para cosas muy muy muy especificas -peliculas o series en catalan incontrables y cosas asi- se agradace tu aportación. Seguro que a alguien le resulta útil.
1 respuesta