# 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 `.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 ```bash 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 ```bash 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`) ```bash alias r='resolve' pingr # ping -c 3 to resolved IP curlr [flags] # curl http:// sshr [cmd...] # ssh via resolved IP with correct HostKeyAlias ``` ### SSH by hostname (via `ProxyCommand`) Drop `config/ssh_config.example` into `~/.ssh/config`. Then: ```bash ssh lenovo # resolves via mDNS then Tailscale, connects ssh lenovo.local # forces mDNS-first path ``` ### Publishing this device as `movil.local` ```bash 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 `*..ts.net`, which Bionic-libc resolves fine (it's just a regular DNS lookup). ## Related - [claude-code-termux](https://devops.ingeniumcodex.com/andresgarcia0313/claude-code-termux) — Claude Code CLI setup for Termux. Uses this repo for SSH/host resolution. ## License MIT — see `LICENSE`.