dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.39k stars 4.75k forks source link

Dns.GetHostEntry returns hostnames which aren't valid DNS hostnames #94195

Open mconnew opened 1 year ago

mconnew commented 1 year ago

Description

CoreWCF uses Dns.GetHostEntry(string.Empty).HostName to discover the hostname of the local machine to build a Uri. One of the ultimate purposes of this is to use a Uri in WSDL documents which is valid outside of the current host. The Dns.GetHostEntry method returns an IPHostEntry for the local host if passed the emptry string (see Remarks of documentation).

Per the documentation definition for IPHostEntry.HostName property, it "Gets or sets the DNS name of the host." There is a CoreWCF user that is trying to use CoreWCF on a host which has a NETBIOS name which starts with a leading "-", e.g. "-WIN-1234". Although this is a valid NETBIOS name, it's not a valid DNS name. CoreWCF uses the value from IPHostEntry.HostName with UriBuilder. When creating the resultant Uri, we get a UriFormatException as the hostname we provided is not valid. The constructor of UriBuilder which takes a hostname specifies it accepts "A DNS-style domain name or IP address.", so the result of GetHostEntry(string.Empty).HostName should be valid to use.

Reproduction Steps

On a Windows PC which has a computer name that starts with a hyphen, run the following code:

var hostname = Dns.GetHostEntry(string.Emtpy).HostName;
UriBuilder uriBuilder = new UriBuilder("net.tcp", DnsCache.MachineName);
var uri = uriBuilder.Uri;

Expected behavior

It's unclear what the correct behavior should be. Does Windows generate a valid DNS hostname which should be returned instead? If so, the fix might be to have Dns.GetHostEntry use that other mechanism to get the local hostname. How does Windows handle resolving hostnames when needing to use a FQDN (e.g. cross forest communication so NETBIOS names won't work)? How does Powershell handle things like remote execution which uses HTTP under the hood when non-DNS netbios names are used by the remote machine?  

I believe you can use NETBIOS names in url's in at least some web browsers for accessing intranet websites. Maybe Uri needs to relax the hostname requirements for http/https otherwise you have difficulty making LAN requests using HttpClient for NETBIOS but not DNS valid hostnames.

The "file" scheme accepts netbios names, should Uri accept netbios names for net.tcp too? Net.tcp is primarily targeted at LAN scenarios and is a poor fit for internet communication so lack of internet DNS name resolution isn't a blocker for using net.tcp.

Actual behavior

The not-DNS-valid NETBIOS name is returned in the DNS HostName property. Subsequent use with Uri causes a UriFormatException to be thrown.

Regression?

I don't believe so.

Known Workarounds

None

Configuration

No response

Other information

No response

ghost commented 1 year ago

Tagging subscribers to this area: @dotnet/ncl See info in area-owners.md if you want to be subscribed.

Issue Details
### Description CoreWCF uses `Dns.GetHostEntry(string.Empty).HostName` to discover the hostname of the local machine to build a Uri. One of the ultimate purposes of this is to use a Uri in WSDL documents which is valid outside of the current host. The `Dns.GetHostEntry` method returns an `IPHostEntry` for the local host if passed the emptry string ([see Remarks of documentation](https://learn.microsoft.com/en-us/dotnet/api/system.net.dns.gethostentry?view=net-7.0#system-net-dns-gethostentry(system-string))). Per the documentation definition for `IPHostEntry.HostName` property, it "Gets or sets the DNS name of the host." There is a CoreWCF user that is trying to use CoreWCF on a host which has a NETBIOS name which starts with a leading "-", e.g. "-WIN-1234". Although this is a valid NETBIOS name, it's not a valid DNS name. CoreWCF uses the value from `IPHostEntry.HostName` with UriBuilder. When creating the resultant Uri, we get a `UriFormatException` as the hostname we provided is not valid. The constructor of `UriBuilder` which takes a hostname specifies it accepts "A DNS-style domain name or IP address.", so the result of `GetHostEntry(string.Empty).HostName` should be valid to use. ### Reproduction Steps On a Windows PC which has a computer name that starts with a hyphen, run the following code: ```c# var hostname = Dns.GetHostEntry(string.Emtpy).HostName; UriBuilder uriBuilder = new UriBuilder("net.tcp", DnsCache.MachineName); var uri = uriBuilder.Uri; ``` ### Expected behavior It's unclear what the correct behavior should be. Does Windows generate a valid DNS hostname which should be returned instead? If so, the fix might be to have Dns.GetHostEntry use that other mechanism to get the local hostname. How does Windows handle resolving hostnames when needing to use a FQDN (e.g. cross forest communication so NETBIOS names won't work)? How does Powershell handle things like remote execution which uses HTTP under the hood when non-DNS netbios names are used by the remote machine?   I believe you can use NETBIOS names in url's in at least some web browsers for accessing intranet websites. Maybe Uri needs to relax the hostname requirements for http/https otherwise you have difficulty making LAN requests using HttpClient for NETBIOS but not DNS valid hostnames. The "file" scheme accepts netbios names, should Uri accept netbios names for net.tcp too? Net.tcp is primarily targeted at LAN scenarios and is a poor fit for internet communication so lack of internet DNS name resolution isn't a blocker for using net.tcp. ### Actual behavior The not-DNS-valid NETBIOS name is returned in the DNS HostName property. Subsequent use with Uri causes a UriFormatException to be thrown. ### Regression? I don't believe so. ### Known Workarounds None ### Configuration _No response_ ### Other information _No response_
Author: mconnew
Assignees: -
Labels: `area-System.Net`, `untriaged`
Milestone: -
antonfirsov commented 1 year ago

System.Net.Dns is in fact a multi-protocol name-resolver implemented as a wrapper over getaddrinfo and friends. IMO the type name & our docs are misleading in this aspect. It passes back whatever is returned by getaddrinfo with the AI_CANONNAME hint set, we don't have any control beyond that. Maybe #19443 would open some opportunities if we choose to implement it.

[...] a host which has a NETBIOS name which starts with a leading "-", e.g. "-WIN-1234" [...]

Maybe Uri needs to relax the hostname requirements for http/https otherwise you have difficulty making LAN requests using HttpClient for NETBIOS but not DNS valid hostnames.

@MihaZupan do you think this is possible?

MihaZupan commented 1 year ago

Maybe Uri needs to relax the hostname requirements for http/https otherwise you have difficulty making LAN requests using HttpClient for NETBIOS but not DNS valid hostnames.

Yes, we likely could relax that logic. Similar to #77464, #64707.

@mconnew how important is this scenario for WCF?

mconnew commented 1 year ago

It's not WCF, it's CoreWCF. I'm not sure what the outcome is if this is fixed. At startup we use Dns.GetHostEntry to find the local machine name to place into metadata documents which might be served up. Without having this, we would need to make a change to fallback to "localhost" instead which will make the metadata (currently only WSDL, but will be via a mex endpoint in future serving a SOAP response) have the incorrect hostname.

The flip side of this is if the WSDL now has the hostname available from DNS.GetHostEntry, on the client side we would generate code which uses that Uri when constructing a ChannelFactory. Every code path I can find uses Uri on the client side, at which point it would fail. As this wouldn't be fixed on .NET Framework, it would mean NetFx clients would fail while .NET clients would succeed.

On .NET Framework with a WCF service, we use a different code path where we don't need to use DNS.GetHostEntry. If it's self hosted, then the customer code is providing the hostname into a Uri themselves, so would hit the same issue if they used the real hostname. If it's IIS hosted, then we're getting the hostname from IIS. The customer says it works in WCF, so the only way I can see that working is if they are somehow using localhost (they aren't providing the hostname to WCF so coming from somewhere else?), aren't using WSDL and the client side is specifying a different hostname, maybe the IP address.

I'm going to ask the original reporter of the issue a few clarifying questions to determine the working WCF scenario details better as it looks to me like you need the fix at both sides, but they say it worked with WCF. Once I have more info, I'll be able to judge how important this is.

antonfirsov commented 10 months ago

I'm going to ask the original reporter of the issue a few clarifying questions to determine the working WCF scenario details better as it looks to me like you need the fix at both sides, but they say it worked with WCF. Once I have more info, I'll be able to judge how important this is.

@mconnew did you get a reply? Is this issue still a priority for you?

ghost commented 10 months ago

This issue has been marked needs-author-action and may be missing some important information.

ghost commented 10 months ago

This issue has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.

alex-lapuka commented 9 months ago

That was initially my ticket opened at CoreWCF. In general, I've noticed the unexpected behavior of CoreWCF when the endpoint is running locally, but instead of the loopback address it ties to resolve the host name and use it. Sorry for the long delay, I didn't keep track for the notifications. I'm posting here just to keep the ticket open.

mconnew commented 9 months ago

@antonfirsov, now I understand the customer issue I believe we can find them a solution without the hostname lookup.