diff --git a/05-troubleshooting/index.md b/05-troubleshooting/index.md index 764b5cf..9bd55ef 100644 --- a/05-troubleshooting/index.md +++ b/05-troubleshooting/index.md @@ -1,6 +1,6 @@ --- created: 2026-03-15T06:37 -updated: 2026-04-29T22:45 +updated: 2026-04-29T23:55 --- # 🔧 General Troubleshooting @@ -14,6 +14,7 @@ Practical fixes for common Linux, networking, and application problems. - [Mail Client Stops Receiving: Fail2ban IMAP Self-Ban](networking/fail2ban-imap-self-ban-mail-client.md) - [firewalld: Mail Ports Wiped After Reload](networking/firewalld-mail-ports-reset.md) - [Tailscale SSH: Unexpected Re-Authentication Prompt](networking/tailscale-ssh-reauth-prompt.md) +- [iOS Tailscale Clients Report HostName="localhost" — Breaks /etc/hosts Generators](networking/tailscale-status-json-hostname-localhost-ios.md) - [rsync over Tailscale: Hung in TCP Teardown After Transfer Completes](networking/rsync-tailscale-teardown-stall.md) - [Windows OpenSSH: WSL Default Shell Breaks Remote Commands](networking/windows-openssh-wsl-default-shell-breaks-remote-commands.md) - [Pi-hole AI Blocklist Blocks Claude Desktop (ERR_CONNECTION_REFUSED)](networking/pihole-blocks-claude-desktop.md) diff --git a/05-troubleshooting/networking/tailscale-status-json-hostname-localhost-ios.md b/05-troubleshooting/networking/tailscale-status-json-hostname-localhost-ios.md new file mode 100644 index 0000000..9e0606e --- /dev/null +++ b/05-troubleshooting/networking/tailscale-status-json-hostname-localhost-ios.md @@ -0,0 +1,116 @@ +--- +title: iOS Tailscale Clients Report HostName="localhost" — Breaks /etc/hosts Generators +domain: troubleshooting +category: networking +tags: + - tailscale + - ios + - postfix + - etc-hosts + - jq +status: published +created: 2026-04-29 +updated: 2026-04-29 +--- + +# iOS Tailscale Clients Report HostName="localhost" — Breaks /etc/hosts Generators + +## Problem + +A homegrown script that builds an `/etc/hosts` block from `tailscale status --json` silently corrupted the file the moment any iOS device joined the tailnet. After the next run, services bound to `localhost` started failing. + +On the affected host (`majordiscord`), Postfix refused to start with: + +``` +postfix: fatal: parameter inet_interfaces: no local interface found for 100.127.114.10 +``` + +`/etc/hosts` looked fine at the top — `127.0.0.1 localhost` was still present — but inside the Tailscale-managed block: + +``` +# TAILSCALE_START +100.84.42.102 tttpod +100.110.197.17 majortoot +100.95.55.40 localhost <-- WRONG (this is an iPhone) +100.84.165.52 majormail +... +100.127.114.10 localhost <-- WRONG (this is an iPad) +# TAILSCALE_END +``` + +When Postfix resolved `localhost` (because `inet_interfaces = localhost` in `main.cf`), the **last matching entry** in `/etc/hosts` won — a Tailscale IP that doesn't exist on this host — and the daemon died on bind. + +## Root Cause + +The script used `.HostName` from the Tailscale JSON: + +```bash +tailscale status --json \ + | jq -r '.Peer[] | "\(.TailscaleIPs[0]) \(.HostName)"' \ + >> "$TEMP_HOSTS" +``` + +iOS Tailscale clients (iPhone, iPad) **always report `HostName: "localhost"`** in the JSON. iOS doesn't expose the real device name to apps the way macOS/Linux/Windows do, so the Tailscale client falls back to the literal string `localhost`. + +Inspect it directly: + +```bash +$ tailscale status --json | jq '.Peer[] | select(.OS == "iOS") | {DNSName, HostName, OS}' +{ + "DNSName": "iphone171.tail7f2d9.ts.net.", + "HostName": "localhost", + "OS": "iOS" +} +{ + "DNSName": "ipad166.tail7f2d9.ts.net.", + "HostName": "localhost", + "OS": "iOS" +} +``` + +Every iOS device contributes a line ` localhost` to `/etc/hosts`, hijacking the `localhost` lookup. + +## Fix + +Use `.DNSName` (the unique tailnet DNS name) and take the first dotted component instead of `.HostName`: + +```bash +tailscale status --json \ + | jq -r '.Peer[] | "\(.TailscaleIPs[0]) \(.DNSName | rtrimstr(".") | split(".")[0])"' \ + >> "$TEMP_HOSTS" +``` + +`DNSName` is always set, always unique, and produces clean labels like `iphone171`, `ipad166`, `majorlab`, etc. + +After patching the script and re-running it: + +```bash +$ bash /root/update_tailscale_hosts.sh +$ systemctl restart postfix +$ systemctl is-active postfix +active +``` + +## Why It's Hard to Spot + +- The corruption only triggers when an iOS device is in the tailnet — so the script "worked" for months. +- `/etc/hosts` files are commonly skimmed top-down. The bogus `localhost` line is buried in the Tailscale block, well below the legitimate `127.0.0.1 localhost` line, and looks superficially like a normal Tailscale entry. +- Postfix's error message names the IP, not `localhost`, so the connection to `/etc/hosts` isn't obvious. +- `getent hosts localhost` shows the *first* match (`127.0.0.1`), not the one Postfix's resolver actually picks for `inet_interfaces` lookup. + +## Verification Checklist + +If you suspect this on any host using a similar generator script: + +```bash +# Any non-loopback "localhost" entries are bugs +grep -nE '^[0-9]+\..* localhost\s*$' /etc/hosts + +# Look at iOS peers' HostName field +tailscale status --json | jq '.Peer[] | select(.OS == "iOS") | .HostName' +``` + +## Related + +- [[majordiscord]] — affected host (incident logged 2026-04-29) +- [[Network Overview]] — Tailscale fleet topology diff --git a/SUMMARY.md b/SUMMARY.md index 5096c39..45a8d18 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,6 +1,6 @@ --- created: 2026-04-02T16:03 -updated: 2026-04-29T22:45 +updated: 2026-04-29T23:55 --- * [Home](index.md) * [Linux & Sysadmin](01-linux/index.md) @@ -91,6 +91,7 @@ updated: 2026-04-29T22:45 * [Ollama Drops Off Tailscale When Mac Sleeps](05-troubleshooting/ollama-macos-sleep-tailscale-disconnect.md) * [Ollama: `ollama run` with Piped Stdin Bypasses Chat Template + SYSTEM Prompt](05-troubleshooting/ollama-chat-template-pipe-stdin-bypass.md) * [rsync over Tailscale: Hung in TCP Teardown After Transfer Completes](05-troubleshooting/networking/rsync-tailscale-teardown-stall.md) + * [iOS Tailscale Clients Report HostName="localhost" — Breaks /etc/hosts Generators](05-troubleshooting/networking/tailscale-status-json-hostname-localhost-ios.md) * [macOS: Repeating Alert Tone from Mirrored iPhone Notification](05-troubleshooting/macos-mirrored-notification-alert-loop.md) * [ClamAV CPU Spike: Safe Scheduling with nice/ionice](05-troubleshooting/security/clamscan-cpu-spike-nice-ionice.md) * [Ansible: Vault Password File Not Found](05-troubleshooting/ansible-vault-password-file-missing.md)