home-assistant / iOS

:iphone: Home Assistant for Apple platforms
https://companion.home-assistant.io
Other
1.55k stars 302 forks source link

Add secondary URL address, NAT LOOPBACK #41

Closed odyslam closed 6 years ago

odyslam commented 7 years ago

I guess that many people like me will have routers that do not support NAT loopback. What it means basically is that we can't use the global url to acess the interface from inside the LAN, we need to use the local address.

I would be really usefull to add a backup Url in a "if not ==> then" basis. If the app can't connect from the main URL, try the backup. It seems pretty rudimentary, but I have no swift knowledge whatsoever.

Cheers

mnoorenberghe commented 6 years ago

The usual way to do this would be to run a local DNS server offered by your DHCP server. Hass.io now has add-ons to help with this. See also https://home-assistant.io/docs/ecosystem/certificates/tls_domain_certificate/#make-mydomaincom-point-to-your-home-assistant-instance

sendorm commented 6 years ago

The problem is, if you have SSL enabled, even when running a local DNS server, you have to include the port address for this to work. So you still have two different url addresses to access home assistant. One with port included for home wifi, one with no port to access elsewhere.

cmsimike commented 6 years ago

Is installing custom firmware onto the router an option for those without nat loopback?

sendorm commented 6 years ago

For some it is a solution, for some it is not. My router does not support custom firmwares, so I am out of luck.

cmsimike commented 6 years ago

Another idea: let's presume your hass domain is something like hass.example.com. Externally, hass.example.com resolves to your public ip:443 (which your router then forwards to the machine running hass) and internally hass.example.com resolves to the machine directly (also on 443).

sendorm commented 6 years ago

Actually you have to also have port forwarding on the router from 443 to 8123. The ssl directly tries to connect to 443 and the router succesfully forwards it to 8123, when out of wifi.

But there is a problem while on wifi. You can not bypass the ssl with ios device. Apple does not let you. So you can't just connect to 192.168.1.x:8123. You have to have dns entries as described. But you need to include the port number while on same network. If by any chance I can use the same address both internally and externally that's the solution. If not, two different configurations for two casez are needed.

Currently: Internally: https://xxxx.ddns.net:8123

Externally: https://xxxx.ddns.net

cmsimike commented 6 years ago

@sendorm run nginx (or some other proxying software) on the same computer as hass. proxy from nginx 44 (so ssl is on the same machine) to hass 8123. that way you can connect externally and internally the exact same way.

you still need the ability to modify dns internally to point directly at the computer (vs external dns which points to your public ip on your router, which then forwards to your hass instance)

sendorm commented 6 years ago

@cmsimike, thank you for a way of a solution. But having two shortcuts on the homepage currently seems the easier way for now. But I'll look into it. Having a double configuration option on the ios app itself is a much easier solution, and much more welcome though :)

Bart274 commented 6 years ago

@sendorm I solved that issue for me by having a friend run a dns server on his device. I use his dns server at home and that dns server translates my external ip address to my internal ip address

robbiet480 commented 6 years ago

I do a similar thing as @Bart274 but run my own DNS internally and use Cloudflare externally.

Adding a fallback address adds a lot of complexities (what's the retry attempts for example) and added delays (especially in extremely time sensitive spots like background fetch location updates where we only have very little time to do our work) to the app which is why I continue to hesitate.

Bart274 commented 6 years ago

Yeah I would prefer running my own dns server locally as well, but I have to use the modem/router from my isp and the dns port is blocked on it, both for external and internal usage 😞

sendorm commented 6 years ago

I already have a dns server running. The problem is if you have ssl enabled too, you have to add the port address for internal access.

robbiet480 commented 6 years ago

@sendorm shouldn't need to. Just always use https and it'll automatically use 443

sendorm commented 6 years ago

Normally with a nat forwarding router you just write: Https://xxx.ddns.net the ssl request from 443 is forwarded to 8123 (you also have to have a port forwarding rule) With a non nat loopback router you have to write: Https://192.168.1.xxx:8123 You get the ssl warning and just ignore it. But with ios you can't ignore that warning. As mentioned you have to enter a custom dns entry. The entry changes the ip number into the xxxx.ddns.net name. But you still have to enter the 8123. Otherwise it won't work.

robbiet480 commented 6 years ago

Ah, do you mean you have a DDNS or DynDNS server running? If so, those are different from a DNS server. If not, I misunderstood.

Here's how I'm setup:

I own a custom domain name, let's say it's mydomain.home

That domain's nameservers are pointed to CloudFlare for external DNS

Requesting homeassistant.mydomain.home while away from home returns 4.4.4.4 (for example) via CloudFlare

When on my local network all devices use our internal DNS resolver which has records for homeassistant.mydomain.home

Requesting homeassistant.mydomain.home while at home returns 192.168.1.2 via internal resolver

NGINX runs in front of Home Assistant, such that I always connect via 443 and NGINX proxies to 8123.

192.168.1.2 has a LetsEncrypt SSL certificate which renews via the dns-01 challenge.

CloudFlare provides its own certificate.

I don't use pinning or anything so whether outside or inside the network the connection uses SSL even with two different certificates for the same hostname.

This setup allows me to always access homeassistant.mydomain.home no matter where I am and without having to use two addresses.

sendorm commented 6 years ago

Dynamic dns ia running on the router and using no-ip to map outside xxx.ddns.net to outside ip. Yeah but I also have a local dns resolver running on raspberry pi. Which just maps xxx.ddns.net to 192.168.1.x.

The holy grail in your setup is nginx I assume. I don't want to go there of possible.

cmsimike commented 6 years ago

@sendorm Why don't you want to use nginx? The alternative you're proposing is asking someone else to introduce complex code so you don't have to deal with nginx?

The fact of the matter is that this nat problem seems solved without needing the additional url in the app. Nginx is such a common deployment that I can't imagine an environment that allows customization without it.

sendorm commented 6 years ago

I'll look into it. When I first started home assistant, the recommended security measure was to have an ssl. It was said to be the easiest to setup. Everything besides the two url thing works perfectly. I just have two shortcuts on home page. But yeah I'll look into nginx and make a gains vs work needed assesment.

Roemer commented 6 years ago

NAT loopback does not work in double NAT scenarios (which some ISPs use) so the fallback address would be great.

joergsti commented 6 years ago

any news on that?

cmsimike commented 6 years ago

@Roemer can you explain the situation in a bit more detail?

Roemer commented 6 years ago

Sure I can: I have a cablemodem and a router and in order to use my routers feature (port forwarding etc.) I needed to connect via static ip to the internet (a setup many ISPs use as far as I know). The problem now is, that I am now in a double NAT and many routers don't handle that scenario very well. That means from external, I can access my network with "my-network.somendomain.com" but when I am in my LAN, resolving the domain "my-network.somendomain.com" does not work because of the double NAT. So this means from internal, I need to use the LAN-IP or add a DNS entry to all computers and therefore I would always need to switch the address of homeassistant if I am local or remote. I actually solved the problem now another way: I have created my own DNS server (in a Synology NAS) which is the primary DNS for devices connected to my router. In the DNS I have various entries, for example: nas.mydomain.com, octoprint.mydomain.com, camera1.mydomain.com and so one, basically one for each service. They all point to the LAN address of the service. Then I have a domain (mydomain.com in this example) where I added CNAME dns entries which forward to my no-ip service so that they all get the same external IP. This way, I can use the same name from external and internal. The only limitation is that each service needs to be on a different port (even if it is on different hosts). So for me, this is not an issue anymore but as the setup is a bit complex, it might help others to implement that (openHAB has this afaik).

Edit: Hmm quite some wall of text. Here's a short summary of my workaround: