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> |
||
|---|---|---|
| bin | ||
| config | ||
| .gitignore | ||
| LICENSE | ||
| README.md | ||
| install.sh | ||
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 totailb0bb74.ts.net. Set to your own tailnet.MDNS_TIMEOUT— seconds waiting for multicast (default1, 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
getentdoesn't exist on Termux. Scripts that shell out to it silently fail. This repo usespython -c "import socket; socket.gethostbyname(...)"as the portable fallback on Bionic.- Shebang matters.
#!/data/data/com.termux/files/usr/bin/bashis required fordeclare -A. A stray backslash (#\!) makes the kernel fall through tosh, which rejects bash-only syntax withSyntax error: "(" unexpected. - mDNS off-LAN is a no-op. Multicast (224.0.0.251) does not cross networks. Over mobile data, only Tailscale resolves.
zeroconfis notpkg-managed. After restoring Termux from atarbackup, re-runpip install zeroconformdns-publish.pywill silently die withModuleNotFoundError.- Silent failures are the enemy. The
.bashrcsnippet deliberately logs to~/.cache/mdns.loginstead 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).
Related
- claude-code-termux — Claude Code CLI setup for Termux. Uses this repo for SSH/host resolution.
License
MIT — see LICENSE.