lmagyar / homeassistant-addon-tailscale

Adds some functionality to the Tailscale Home Assistant Community Add-on https://github.com/hassio-addons/addon-tailscale
MIT License
56 stars 7 forks source link

400: Bad Request #53

Closed erapade closed 1 year ago

erapade commented 1 year ago

My HA is throwing "400: Bad Request" when connecting from a none Tailscale equipped device. Connecting from a device with Tailscale works fine using http

Some comments.

Log file below: 2023/08/09 00:38:32 portmapper: UPnP meta changed: {Location:http://192.168.0.150:5000/Public_UPNP_gatedesc.xml Server:Linux/2.6.12, UPnP/1.0, NETGEAR-UPNP/1.0 USN:uuid:c08bed9f-ca63-872c-35eb-849431d8e49a::urn:schemas-upnp-org:device:InternetGatewayDevice:1} s6-rc: info: service init-nginx successfully started s6-rc: info: service nginx: starting 2023/08/09 00:38:32 control: NetInfo: NetInfo{varies=false hairpin=true ipv6=false ipv6os=true udp=true icmpv4=false derp=#4 portmap=active-UM link=""} 2023/08/09 00:38:32 magicsock: endpoints changed: 83.216.118.134:46062 (portmap), 172.30.32.1:46062 (local), 172.30.232.1:46062 (local), 192.168.0.158:46062 (local) 2023/08/09 00:38:32 Switching ipn state NoState -> Starting (WantRunning=true, nm=true) 2023/08/09 00:38:32 magicsock: SetPrivateKey called (init) 2023/08/09 00:38:32 magicsock: private key changed, reconnecting to home derp-4 2023/08/09 00:38:32 wgengine: Reconfig: configuring userspace WireGuard config (with 1/2 peers) 2023/08/09 00:38:32 magicsock: adding connection to derp-4 for home-keep-alive 2023/08/09 00:38:32 magicsock: 1 active derp conns: derp-4=cr0s,wr0s 2023/08/09 00:38:32 wgengine: Reconfig: configuring router 2023/08/09 00:38:32 wgengine: Reconfig: configuring DNS 2023/08/09 00:38:32 dns: Set: {DefaultResolvers:[] Routes:{tailYYYY.ts.net.:[] ts.net.:[199.247.155.53 2620:111:8007::53]}+65arpa SearchDomains:[tailYYYY.ts.net.] Hosts:3} 2023/08/09 00:38:32 derphttp.Client.Connect: connecting to derp-4 (fra) 2023/08/09 00:38:32 peerapi: serving on http://100.111.254.99:43486 2023/08/09 00:38:32 health("dns"): error: getting OS base config is not supported 2023/08/09 00:38:32 health("dns-os"): error: getting OS base config is not supported 2023/08/09 00:38:32 peerapi: serving on http://[fd7a:115c:a1e0:ab12:4843:cd96:626f:fe63]:43486 2023/08/09 00:38:32 Switching ipn state Starting -> Running (WantRunning=true, nm=true) [00:38:32] INFO: Starting NGinx... 2023/08/09 00:38:33 magicsock: derp-4 connected; connGen=1 s6-rc: info: service nginx successfully started 2023/08/09 00:38:34 wgengine: Reconfig: configuring userspace WireGuard config (with 1/10 peers) [00:38:40] DEBUG: Requested API resource: http://supervisor/network/info [00:38:40] DEBUG: Request method: GET [00:38:40] DEBUG: Request data: {} [00:38:40] DEBUG: API HTTP Response code: 200 [00:38:40] DEBUG: API Response: {"result": "ok", "data": {"interfaces": [{"interface": "wlan0", "type": "wireless", "enabled": false, "connected": false, "primary": false, "mac": "B8:27:EB:EF:40:97", "ipv4": {"method": "disabled", "address": [], "nameservers": [], "gateway": null, "ready": false}, "ipv6": {"method": "disabled", "address": [], "nameservers": [], "gateway": null, "ready": false}, "wifi": null, "vlan": null}, {"interface": "eth0", "type": "ethernet", "enabled": true, "connected": true, "primary": true, "mac": "B8:27:EB:BA:15:C2", "ipv4": {"method": "auto", "address": ["192.168.0.158/24"], "nameservers": ["192.168.0.1"], "gateway": "192.168.0.1", "ready": true}, "ipv6": {"method": "disabled", "address": ["fe80::4276:11cb:6a16:4a27/64"], "nameservers": [], "gateway": null, "ready": true}, "wifi": null, "vlan": null}], "docker": {"interface": "hassio", "address": "172.30.32.0/23", "gateway": "172.30.32.1", "dns": "172.30.32.3"}, "host_internet": true, "supervisor_internet": true}} 2023/08/09 00:38:40 wgengine: idle peer [wsJSV] now active, reconfiguring WireGuard 2023/08/09 00:38:40 wgengine: Reconfig: configuring userspace WireGuard config (with 2/10 peers) 2023/08/09 00:38:40 magicsock: disco: node [wsJSV] d:a4f4b648194b869e now using 90.129.214.194:32466 2023/08/09 00:38:40 Accept: TCP{100.79.46.100:53384 > 100.111.254.99:8123} 65 tcp non-syn 2023/08/09 00:38:40 Accept: TCP{100.79.46.100:53409 > 100.111.254.99:8123} 64 tcp ok 2023/08/09 00:38:40 [unexpected] localbackend: got TCP conn without TCP config for port 8123; from 100.79.46.100:53409 2023/08/09 00:38:41 Accept: TCP{100.79.46.100:53409 > 100.111.254.99:8123} 52 tcp non-syn [00:38:41] DEBUG: Requested API resource: http://supervisor/network/interface/wlan0/info [00:38:41] DEBUG: Request method: GET [00:38:41] DEBUG: Request data: {} [00:38:41] DEBUG: API HTTP Response code: 200 [00:38:42] DEBUG: API Response: {"result": "ok", "data": {"interface": "wlan0", "type": "wireless", "enabled": false, "connected": false, "primary": false, "mac": "B8:27:EB:EF:40:97", "ipv4": {"method": "disabled", "address": [], "nameservers": [], "gateway": null, "ready": false}, "ipv6": {"method": "disabled", "address": [], "nameservers": [], "gateway": null, "ready": false}, "wifi": null, "vlan": null}} [00:38:43] DEBUG: Requested API resource: http://supervisor/network/interface/eth0/info [00:38:43] DEBUG: Request method: GET [00:38:43] DEBUG: Request data: {} [00:38:43] DEBUG: API HTTP Response code: 200 [00:38:44] DEBUG: API Response: {"result": "ok", "data": {"interface": "eth0", "type": "ethernet", "enabled": true, "connected": true, "primary": true, "mac": "B8:27:EB:BA:15:C2", "ipv4": {"method": "auto", "address": ["192.168.0.158/24"], "nameservers": ["192.168.0.1"], "gateway": "192.168.0.1", "ready": true}, "ipv6": {"method": "disabled", "address": ["fe80::4276:11cb:6a16:4a27/64"], "nameservers": [], "gateway": null, "ready": true}, "wifi": null, "vlan": null}} [00:38:46] INFO: Tailscale is running [00:38:47] WARNING: Currently the following subnets are both present as local subnets [00:38:47] WARNING: and are also routed within your tailnet to other nodes! [00:38:47] WARNING: Please reconfigure your subnet routing within your tailnet [00:38:47] WARNING: to prevent current or future collisions. [00:38:47] WARNING: 192.168.0.0/24 s6-rc: info: service post-tailscaled successfully started s6-rc: info: service proxy: starting s6-rc: info: service taildrop: starting s6-rc: info: service taildrop successfully started [00:38:49] DEBUG: Requested API resource: http://supervisor/core/info [00:38:49] DEBUG: Request method: GET [00:38:49] DEBUG: Request data: {} [00:38:49] DEBUG: API HTTP Response code: 200 [00:38:49] DEBUG: API Response: {"result": "ok", "data": {"version": "2023.8.1", "version_latest": "2023.8.1", "update_available": false, "machine": "raspberrypi3-64", "ip_address": "172.30.32.1", "arch": "aarch64", "image": "ghcr.io/home-assistant/raspberrypi3-64-homeassistant", "boot": true, "port": 8123, "ssl": false, "watchdog": true, "audio_input": null, "audio_output": null}} 2023/08/09 00:38:50 serve: closing idle connections to http://127.0.0.1:8123 2023/08/09 00:38:50 Hostinfo.WireIngress changed to false 2023/08/09 00:38:51 serve: creating a new proxy handler for http://127.0.0.1:8123 2023/08/09 00:38:51 wgengine: Reconfig: configuring userspace WireGuard config (with 2/2 peers) [00:38:51] INFO: Tailscale Proxy is enabled: [00:38:51] INFO: Your Home Assistant instance is available within your Tailnet VPN at [00:38:51] INFO: https://XXXX.tailYYYY.ts.net s6-rc: info: service proxy successfully started s6-rc: info: service funnel: starting 2023/08/09 00:38:53 Hostinfo.WireIngress changed to true [00:38:53] INFO: Tailscale Funnel is enabled: [00:38:53] INFO: Your Home Assistant instance is publicly available on the internet at [00:38:53] INFO: https://XXXX.tailYYYY.ts.net s6-rc: info: service funnel successfully started s6-rc: info: service legacy-services: starting s6-rc: info: service legacy-services successfully started 2023/08/09 00:38:53 wgengine: Reconfig: configuring userspace WireGuard config (with 2/10 peers) 2023/08/09 00:39:37 Accept: TCP{100.79.46.100:53409 > 100.111.254.99:8123} 52 tcp non-syn 2023/08/09 00:39:37 Accept: TCP{100.79.46.100:53409 > 100.111.254.99:8123} 58 tcp non-syn 2023/08/09 00:39:50 Accept: TCP{100.79.46.100:53409 > 100.111.254.99:8123} 52 tcp non-syn 2023/08/09 00:39:50 Accept: TCP{100.79.46.100:53409 > 100.111.254.99:8123} 66 tcp non-syn 2023/08/09 00:39:56 [unexpected] localbackend: got TCP conn without TCP config for port 8123; from 100.79.46.100:53411 2023/08/09 00:39:56 [unexpected] localbackend: got TCP conn without TCP config for port 8123; from 100.79.46.100:53412 2023/08/09 00:39:56 [unexpected] localbackend: got TCP conn without TCP config for port 8123; from 100.79.46.100:53413 2023/08/09 00:39:58 Accept: TCP{100.79.46.100:53411 > 100.111.254.99:8123} 52 tcp non-syn 2023/08/09 00:40:41 wgengine: idle peer [8EeRI] now active, reconfiguring WireGuard 2023/08/09 00:40:41 wgengine: Reconfig: configuring userspace WireGuard config (with 3/10 peers) 2023/08/09 00:40:41 magicsock: disco: node [8EeRI] d:770110597853e96d now using 185.40.234.37:41651 2023/08/09 00:40:41 Drop: TCP{[fd7a:115c:a1e0:ab12:4843:cd96:6249:ba61]:49386 > [fd7a:115c:a1e0:ab12:4843:cd96:626f:fe63]:43486} 80 no rules matched 2023/08/09 00:40:41 Drop: TCP{[fd7a:115c:a1e0:ab12:4843:cd96:6249:ba61]:49402 > [fd7a:115c:a1e0:ab12:4843:cd96:626f:fe63]:43486} 80 no rules matched 2023/08/09 00:40:41 Accept: TCP{[fd7a:115c:a1e0:ab12:4843:cd96:6249:ba61]:49386 > [fd7a:115c:a1e0:ab12:4843:cd96:626f:fe63]:43486} 72 tcp non-syn 2023/08/09 00:40:41 Accept: TCP{[fd7a:115c:a1e0:ab12:4843:cd96:6249:ba61]:49402 > [fd7a:115c:a1e0:ab12:4843:cd96:626f:fe63]:43486} 72 tcp non-syn 2023/08/09 00:40:41 Accept: TCP{[fd7a:115c:a1e0:ab12:4843:cd96:6249:ba61]:49402 > [fd7a:115c:a1e0:ab12:4843:cd96:626f:fe63]:43486} 315 tcp non-syn 2023/08/09 00:40:41 [RATELIMIT] format("%s: %s %d %s\n%s") 2023/08/09 00:40:57 Accept: TCP{[fd7a:115c:a1e0:ab12:4843:cd96:6249:ba61]:49386 > [fd7a:115c:a1e0:ab12:4843:cd96:626f:fe63]:43486} 72 tcp non-syn

lmagyar commented 1 year ago

Please add 127.0.0.1 to trusted proxies (as noted in the Documentation), because Tailscale is running on the host network, not like NGINX on the docker network.

Note: This is an intentional Tailscale limitation that it uses 127.0.0.1, "Note that only http://127.0.0.1 is currently supported for proxies." https://tailscale.com/kb/1242/tailscale-serve/

  trusted_proxies:
    - 172.30.33.0/24
    - 127.0.0.1

On the Netgear issue: I think Tailscale tries to find any route toward the internet with any means.


Important:

[00:38:47] WARNING: Currently the following subnets are both present as local subnets
[00:38:47] WARNING: and are also routed within your tailnet to other nodes!
[00:38:47] WARNING: Please reconfigure your subnet routing within your tailnet
[00:38:47] WARNING: to prevent current or future collisions.
[00:38:47] WARNING: 192.168.0.0/24

There is a protection in this add-on to prevent this collision, but without this, when you enable the subnet routing on the other site, this site would route all the traffic toward the other site and your local HA would lose ALL network access, would get soft bricked! Yes, it is typical to use 192.168.0.0/24 or 192.168.1.0/24 on multiple LAN-s, but Tailscale assumes they are on the same LAN and this is usually not true, and a simple click (enabling subnet routing on the Tailscale admin page) can mess up your networking completely.

erapade commented 1 year ago

Thanks, now works like a charm.

I tried to understand the "Important:" above but didn't totally grab it. I only have one network that should be known by tailscale and that is 192.168.0.0/24

I did see that there was another issue related to the same "400: Bad Request" with the solution to set 127.0.0.1 as the trusted proxy but as I didn't find it in the documentation I thought it was not relevant. Are you sure this is in the documentation for HA. I looked at the latest documentation where there was some updates for Funnel but I didn't find the information about the trusted proxy but I might have miseed something

I could see that this is on the way to be released in the official repro, that would be great

Thanks for the help and all the work you are doing, this will be a great improvement to HA when finally released. Now my Internet Provider can NAT and hide my router anyway they want, I will still be able to give access to my family members without them to install the Tailscale app and register an account.

Please close, but also re-check the documentation so it's clear in the trusted proxy configuration

lmagyar commented 1 year ago

Ah, I see, this 127.0.0.1 thing is in the proxy documentation, but funnel uses the proxy. I will add a note to the funnel docs to read the proxy docs also. It was trivial for me, but not trivial for a first time reader, thank you for the reply! And I will try to add some detection for this misconfiguration.


On the "Important" thing: there are at least 2 Tailscale devices (add-on or real Tailscale installation) in your tailnet network that uses the same local 192.168.0.0/24 LAN network, and the add-on automatically advertises these as possible subnet routes. Subnet: you can access non-tailscale-installed devices on the advertised subnet through the tailscale-installed device routing the traffic. Advertising doesn't automatically enable the routing, but it seems you have enabled on at least one of the other devices (not this add-on that we are talking about now) this routing (see https://login.tailscale.com/admin/machines), so you can access that subnet's devices from any tailscale-installed device (like this add-on's device) easily with a ping 192.168.0.x. But this add-on's local LAN also uses a 192.168.0.0/24 network, so all the traffic, even your local HA's traffic on 192.168.0.x will go to the other devices LAN, a total mess. Tailscale assumes they are load-balancing or failsafe nodes on the same physical LAN, but they are usually just misconfiguration.

Enter this into a cli (do not copy-paste the output here, just see it):

docker exec -it addon_09716aab_tailscale /bin/bash
/opt/tailscale status --json --peers=true --self=false | jq '.Peer[] | select(has("PrimaryRoutes"))'      

You will get at least one result, a device that is not this add-on's LAN, but has an enabled 192.168.0.0/24 subnet routing.

Enter this:

{ ip -4 rule list; ip -6 rule list; }

There will be lines starting with "5000" like:

5000:   from all to 192.168.0.0/24 lookup main

These lines prevent tailscale to route this add-on's devices's ALL network trafic to the other device's network, making it de facto unreacable.

erapade commented 1 year ago

Thanks. Now I got where you documented the proxy as well. But since it's a pre-req when installing it should also be in this section:

image

lmagyar commented 1 year ago

Yeah, my forked docs contain an extra "check logs again" step, now I made a PR for the official add-on also: https://github.com/hassio-addons/addon-tailscale/pull/242 I don't want to mention proxy explicitly, if somebody is a fresh new Tailscale user, HTTPS won't be set, and if it is already set, there will be warning in the log about the situation. Other services are also starting after the login, so better to be not too specific, core developers don't like that in my experience.

And I made a reference from the funnel docs to the proxy doc also.

And I've tried to add some proxy config check to the scripts, but a simple curl fails on userspace-networking devices, after I figure out this problem, there will be a warning about this trusted proxies issue also.

lmagyar commented 1 year ago

And the proxy config check is released also, closing this issue now.

googanhiem commented 1 year ago

Thanks for this great addon supercharge! Definitely add this to your DOC.md (Something like "Note: 127.0.0.1 must be one of your trusted_proxies in your home assistant config file for https/proxy to work, otherwise you will see a 400:Bad Request error when trying to access home assistant").

Just to understand are their any serious security risks of adding this to the trusted proxy list?

lmagyar commented 1 year ago

OK, I've added more emphasis to it (Important: See also the "Option: proxy" section of this documentation for the necessary configuration changes!)(bbcab4bbe04d062ad57c68122efee6bb8f8a1ce9). Will be part of the next release.

And the add-on's code already checks the accessibility of the HA webserver and writes in the log:

  bashio::log.error "Unable to connect to Home Assistant on http://127.0.0.1:$(bashio::core.port)"
  bashio::log.error "Please check your configuration based on the add-on's Documentation under \"Option: proxy\""
lmagyar commented 1 year ago

Oh, and the security issue: I'm really not an expert, as I understand, this will make accessible the unencrypted plain HTTP web UI of HA for proxies not only on the 172.30.33.0/24 internal docker add-on network (used by eg. the NGINX proxy) but on the localhost also. I think this is at least not much worst than without this extra config line. And this is a Tailscale requirement, so we can't do anything about it. :/

googanhiem commented 1 year ago

That should help. Been using the proxy/https features and they work great.

lmagyar commented 12 months ago

And finally even myself run into this 400: Bad Request error... :D I fixed reverse proxy config detection: diff New release is out.