mDNS + Tailscale hostname resolution tools for Termux. Fixes .local resolution on Android/Bionic libc.
Go to file
Andres Garcia 0b6642ec84 init: extraer herramientas mDNS de claude-code-termux
Scripts (bin/):
- mdns-resolve: resolver .local por multicast UDP (stdlib Python).
- mdns-publish.py: publicar este dispositivo como movil.local (zeroconf).
- ssh-mdns-proxy: ProxyCommand SSH con orden mDNS -> Tailscale -> cache.
- ssh-fallback: ProxyCommand con fallback Tailscale -> LAN.
- resolve: resolver genérico para cualquier comando (ping, curl, kubectl...).

Config (config/):
- bashrc.snippet: aliases r/pingr/curlr/sshr + auto-arranque publisher.
- ssh_config.example: entradas ProxyCommand para .local y hostnames cortos.

Docs y setup:
- README.md standalone con guía de uso, comportamiento por red y gotchas
  (getent ausente en Bionic, shebang bash-only, mDNS no cruza redes,
  zeroconf no sobrevive tar-backups, no silenciar logs).
- install.sh independiente con --dry-run.

Origen: extraído de andresgarcia0313/claude-code-termux para reutilizarse
sin acoplar a Claude Code.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-19 20:53:44 -05:00
bin init: extraer herramientas mDNS de claude-code-termux 2026-07-19 20:53:44 -05:00
config init: extraer herramientas mDNS de claude-code-termux 2026-07-19 20:53:44 -05:00
.gitignore init: extraer herramientas mDNS de claude-code-termux 2026-07-19 20:53:44 -05:00
LICENSE init: extraer herramientas mDNS de claude-code-termux 2026-07-19 20:53:44 -05:00
README.md init: extraer herramientas mDNS de claude-code-termux 2026-07-19 20:53:44 -05:00
install.sh init: extraer herramientas mDNS de claude-code-termux 2026-07-19 20:53:44 -05:00

README.md

mdns-termux

mDNS + Tailscale hostname resolution for Termux (Android).

Termux runs on Android's Bionic libc, which does not resolve .local names and lacks getent. This repo ships small, dependency-light helpers that fix that — without root, and without a custom system resolver.

Works on any network: LAN via multicast, off-LAN via Tailscale MagicDNS.


What's in here

Script Role
mdns-resolve Resolve <host>.local via raw multicast UDP (pure Python, stdlib only).
mdns-publish.py Publish this device on the LAN as movil.local using zeroconf.
ssh-mdns-proxy SSH ProxyCommand: mDNS → Tailscale DNS → cached IP.
ssh-fallback SSH ProxyCommand: Tailscale → LAN, for flaky Tailscale.
resolve Generic resolver for any command (ping, curl, kubectl, nc…). Same order.

Install

git clone https://devops.ingeniumcodex.com/andresgarcia0313/mdns-termux.git
cd mdns-termux
bash install.sh          # or --dry-run first

Then follow the printed reminders (append bashrc.snippet, set your TAILSCALE_DOMAIN, optionally merge ssh_config.example).

Usage

Generic resolver — works in any command

resolve lenovo                       # -> 100.69.236.16
ping   $(resolve hp62a)
curl   "http://$(resolve dell):8080"
kubectl --server="https://$(resolve master):6443" get nodes

Environment knobs:

  • TAILSCALE_DOMAIN — defaults to tailb0bb74.ts.net. Set to your own tailnet.
  • MDNS_TIMEOUT — seconds waiting for multicast (default 1, keeps off-LAN snappy).

Shell helpers (from config/bashrc.snippet)

alias r='resolve'
pingr <host>              # ping -c 3 to resolved IP
curlr <host> [flags]      # curl http://<resolved-ip>
sshr  <host> [cmd...]     # ssh via resolved IP with correct HostKeyAlias

SSH by hostname (via ProxyCommand)

Drop config/ssh_config.example into ~/.ssh/config. Then:

ssh lenovo                # resolves via mDNS then Tailscale, connects
ssh lenovo.local          # forces mDNS-first path

Publishing this device as movil.local

python ~/.local/bin/mdns-publish.py                                # foreground
nohup python ~/.local/bin/mdns-publish.py >>~/.cache/mdns.log 2>&1 & disown

Behavior by network

Scenario Path Typical latency
On home LAN mDNS multicast (1 s cap) → else Tailscale < 100 ms
Mobile data / away mDNS fails → Tailscale MagicDNS < 200 ms
No Tailscale Both fail → cached last-known IP instant

Gotchas found the hard way

  • getent doesn't exist on Termux. Scripts that shell out to it silently fail. This repo uses python -c "import socket; socket.gethostbyname(...)" as the portable fallback on Bionic.
  • Shebang matters. #!/data/data/com.termux/files/usr/bin/bash is required for declare -A. A stray backslash (#\!) makes the kernel fall through to sh, which rejects bash-only syntax with Syntax error: "(" unexpected.
  • mDNS off-LAN is a no-op. Multicast (224.0.0.251) does not cross networks. Over mobile data, only Tailscale resolves.
  • zeroconf is not pkg-managed. After restoring Termux from a tar backup, re-run pip install zeroconf or mdns-publish.py will silently die with ModuleNotFoundError.
  • Silent failures are the enemy. The .bashrc snippet deliberately logs to ~/.cache/mdns.log instead of /dev/null. Keep it that way.

Tailscale on Termux

Tailscale runs as the Android app, not as a Termux CLI — tailscale up inside a shell won't work. The app provides MagicDNS for *.<your-tailnet>.ts.net, which Bionic-libc resolves fine (it's just a regular DNS lookup).

  • claude-code-termux — Claude Code CLI setup for Termux. Uses this repo for SSH/host resolution.

License

MIT — see LICENSE.