Fix hostname support#864
Conversation
A device will otherwise block the request, when requesting with a hostname instead of the plain IP
| break | ||
|
|
||
| headers = {"content-type": "application/json"} | ||
| # unsetting the host header, as requests with a domain would be blocked otherwise |
There was a problem hiding this comment.
Please better explain what this is intended to fix, I can't reproduce any case where this is blocked myself.
Maybe paste some examples using curl to craft the working and non-working requests?
Are you sure the problem you see is not caused by an issue in your network configuration?
There was a problem hiding this comment.
When requesting the /setup/eureka_info endpoint using a hostname (instead of a plain IP), the request is blocked. I can reproduce this both with an Nvidia Shield and a Google Home Mini. I doubt my network influences this, as the devices are on the same L2 and L3 network and can communicate directly. Here are some simple curl commands for reproduction:
Working
$ curl https://x.x.x.x:8443/setup/eureka_info -k -v
* Trying x.x.x.x:8443...
* Connected to x.x.x.x (x.x.x.x) port 8443
* schannel: disabled automatic use of client certificate
* schannel: using IP address, SNI is not supported by OS.
* ALPN: curl offers http/1.1
* ALPN: server did not agree on a protocol. Uses default.
* using HTTP/1.x
> GET /setup/eureka_info HTTP/1.1
> Host: x.x.x.x:8443
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Access-Control-Allow-Headers:Content-Type
< Cache-Control:no-cache
< Content-Length:1274
< Content-Type:application/json
<
{...json...}* Connection #0 to host x.x.x.x left intact
$ curl -H 'Host:' https://homeminitest:8443/setup/eureka_info -k -v
* Trying x.x.x.x:8443...
* Connected to homeminitest (x.x.x.x) port 8443
* schannel: disabled automatic use of client certificate
* ALPN: curl offers http/1.1
* ALPN: server did not agree on a protocol. Uses default.
* using HTTP/1.x
> GET /setup/eureka_info HTTP/1.1
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Access-Control-Allow-Headers:Content-Type
< Cache-Control:no-cache
< Content-Length:1274
< Content-Type:application/json
<
{...json...}* Connection #0 to host homeminitest left intact
Blocked
$ curl https://homeminitest:8443/setup/eureka_info -k -v
* Trying x.x.x.x:8443...
* Connected to homeminitest (x.x.x.x) port 8443
* schannel: disabled automatic use of client certificate
* ALPN: curl offers http/1.1
* ALPN: server did not agree on a protocol. Uses default.
* using HTTP/1.x
> GET /setup/eureka_info HTTP/1.1
> Host: homeminitest:8443
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Content-Length:0
<
* Connection #0 to host homeminitest left intact
|
I think this might make sense. It is doing ssl authentication. So you setting a host header might trigger the device to try to use some different https certificate. These device are not using publically signed SSL certs, so that likely causes weird behaviour. |
|
|
||
| headers = {"content-type": "application/json"} | ||
| # unsetting the host header, as requests with a domain would be blocked otherwise | ||
| headers = {"host": "", "content-type": "application/json"} |
There was a problem hiding this comment.
I think this end up setting it to an empty string. I am not sure that is such a good idea.
"A Host header field must be sent in all HTTP/1.1 request messages. A 400 Bad Request status code may be sent to any HTTP/1.1 request message that lacks or contains more than one Host header field."
So it likely need to be set to the IP address of the request.
There was a problem hiding this comment.
I would still like an example showing where this is a problem and how this PR fixes it.
There was a problem hiding this comment.
I suspect just setting a manual dns (ie not mdns) hostname for a chromecast instead of an IP would cause it.
There was a problem hiding this comment.
Just realized that it might only be possible with the changes for ipv6 that was posted that does a getaddrinfo lookup.
There was a problem hiding this comment.
My usecase is indeed to have a custom DNS name for a cast device, as I can't use mDNS in my setup, since the cast devices are in a different L2/L3 network than Home Assistant.
I do agree with setting the Host header to the resolved IP, that's a cleaner way to solve this.
There was a problem hiding this comment.
As mentioned here: home-assistant/core#135024 (comment)
Adding the IP of the chromecast in the host header fixes the issue
There was a problem hiding this comment.
I changed the PR to do something inbetween; if the HTTP get fails with FORBIDDEN, we retry with an empty host header.
The reason I suggest this simplified approach is to avoid doing the name resolution via socket.getaddrinfo, and then iterating over the returned list.
elupus
left a comment
There was a problem hiding this comment.
While i think the need might be real, i think the solution need to be adjusted.
@elupus This is not related to TLS (my curl examples all ignore invalid certificates through |
elupus
left a comment
There was a problem hiding this comment.
I would have done as in the suggestion. But this is fine!
A device will otherwise block the request, when requesting with a hostname instead of the plain IP.