Tengo un Moto G3 con LineageOS 14.1 que controlo por ADB WiFi desde la PC. El problema: eso solo funciona estando en la misma red. Acá dejo armado el esquema para controlarlo desde cualquier parte del mundo sin instalar nada raro en el teléfono (no hay Tailscale para Android 7).

La idea

[notebook en el mundo] --túnel WG--> [PC Linux en casa] --adb wifi--> [G3]

La PC de casa hace de gateway: mantiene el ADB del teléfono y expone WireGuard. El celular no necesita ninguna app nueva.

1. Servidor WireGuard en la PC (Arch)

sudo pacman -S wireguard-tools
cd /etc/wireguard
wg genkey | tee server.key | wg pubkey > server.pub
wg genkey | tee notebook.key | wg pubkey > notebook.pub

/etc/wireguard/wg0.conf:

[Interface]
Address = 10.66.0.1/24
ListenPort = 51820
PrivateKey = <contenido de server.key>
PostUp   = sysctl -w net.ipv4.ip_forward=1 >/dev/null
PostUp   = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT
PostUp   = iptables -t nat -A POSTROUTING -s 10.66.0.0/24 -o wlp1s0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -s 10.66.0.0/24 -o wlp1s0 -j MASQUERADE

[Peer]
# notebook
PublicKey = <notebook.pub>
AllowedIPs = 10.66.0.2/32
sudo systemctl enable --now wg-quick@wg0

Ojo: si levantás el túnel a mano antes, systemctl start falla porque el puerto ya existe. sudo wg-quick down wg0 primero.

Abrir el puerto en el router

Si el router tiene UPnP:

upnpc -m wlp1s0 -r 51820 udp   # dura 24h

Los routers caseros limitan el lease a 24hs, así que lo renuevo con un timer de systemd (/etc/systemd/system/wg-upnp.timer, cada 12hs):

[Unit]
Description=Renueva UPnP cada 12 horas
[Timer]
OnBootSec=3min
OnUnitActiveSec=12h
[Install]
WantedBy=timers.target

con un service oneshot que ejecuta upnpc -m wlp1s0 -r 51820 udp. Si el ISP te da IP dinámica, sumarle DDNS (duckdns o similar).

2. Cliente notebook

[Interface]
PrivateKey = <notebook.key>
Address = 10.66.0.2/24

[Peer]
PublicKey = <server.pub>
Endpoint = TU_IP_PUBLICA:51820
AllowedIPs = 10.66.0.0/24, 192.168.0.0/24
PersistentKeepalive = 25

Y desde cualquier bar del mundo:

ssh -N -L 5555:192.168.0.129:5555 usuario@10.66.0.1 &
adb connect 127.0.0.1:5555

Todo lo que hacía en casa, igual.

3. El Android viejo (la parte divertida)

No hay WireGuard para Android 7 ya (min SDK subió a 26), pero con root se puede correr wireguard-go como binario CLI horneado en /system. Esto es mejor que una app: sobrevive a formateos.

Compilar wireguard-go para ARM

En la PC con Go:

git clone https://github.com/WireGuard/wireguard-go && cd wireguard-go
GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=0 \
  go build -trimpath -ldflags="-s -w" -o wireguard-go-arm .

Truco: GOOS=android exige cgo/NDK, pero un binario estático linux/arm corre joya en Android con root (el kernel de Android ES Linux). El daemon crea su socket en /var/run/wireguard, que en Android es read-only; se resuelve montando un tmpfs en /var/run al arrancar.

El wg CLI sale del paquete Termux wireguard-tools (packages.termux.dev/apt/termux-main/pool/main/w/wireguard-tools/), se extrae del .deb y corre directo (está linkeado contra bionic).

Instalar en el teléfono

Con adb root: pushear wireguard-go y wg a /system/xbin/ (chmod 755) y la config a /system/etc/wireguard/g3.conf (chmod 600):

[Interface]
PrivateKey = <clave del peer celular>

[Peer]
PublicKey = <server.pub>
Endpoint = TU_IP_PUBLICA:51820
AllowedIPs = 10.66.0.0/24
PersistentKeepalive = 25

Además agregar al /system/build.prop:

persist.adb.tcp.port=5555

para que adbd escuche en red después de cada reinicio (y de un formateo).

Script de arranque

/system/etc/init.d/99wireguard:

#!/system/bin/sh
mkdir -p /dev/net
[ -e /dev/net/tun ] || mknod /dev/net/tun c 10 200
chmod 660 /dev/net/tun

grep -q ' /var/run ' /proc/mounts || { mount -o remount,rw / >/dev/null 2>&1
mkdir -p /var/run; mount -t tmpfs tmpfs /var/run >/dev/null 2>&1
mount -o remount,ro / >/dev/null 2>&1; }
mkdir -p /var/run/wireguard

setsid /system/xbin/wireguard-go wg0 >> /data/local/tmp/wgboot.log 2>&1 < /dev/null &
sleep 4
/system/xbin/wg setconf wg0 /system/etc/wireguard/g3.conf
ip addr add 10.66.0.3/24 dev wg0
ip link set wg0 mtu 1420 up
ip rule add to 10.66.0.0/24 lookup main pref 9000

Detalles que me hicieron perder un rato:

  • El servicio sysinit de CM corre los init.d en post-fs-data, pero mata los hijos al terminar: usar setsid para que el daemon quede huérfano.
  • Sin tmpfs en /var/run el daemon muere con “read-only file system”.
  • Falta la regla de ruteo: Android usa tablas por-red con fwmark y pisa la tabla main. Por eso el ip rule ... pref 9000.

4. Cómo queda funcionando

  • Teléfono en casa → ADB directo 192.168.0.XXX:5555
  • Teléfono afuera → keepalive conecta el túnel solo → ADB por 10.66.0.3:5555
  • Reinicio del teléfono → vuelve solo (build.prop + init.d)
  • Formateo del teléfono → adb en red vuelve solo (build.prop está en /system); re-instalar wireguard-go/wg/config (están en /system, sobreviven) y aceptar la huella RSA una vez con el teléfono en la mano.

Nota sobre hairpin NAT: estando en la misma LAN el túnel contra la IP pública no completa handshake (el router no hace loopback). No importa: en casa el acceso directo por LAN ya funciona.

Bonus

Por ese mismo túnel anda scrcpy (Android 5+): espejo de pantalla + control remoto completo del teléfono desde la notebook.