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).
[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.
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.
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).
[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.
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.
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).
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).
/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:
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.ip rule ... pref 9000.192.168.0.XXX:555510.66.0.3:5555Nota 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.
Por ese mismo túnel anda scrcpy (Android 5+): espejo de pantalla + control remoto completo del teléfono desde la notebook.