Jan Schermer
2025-Sep-05 08:45 UTC
How to specify chost (client hostname) used for hostbased authentication?
Hi, I have a question about hostbased authentication. It looks like the client does a reverse DNS lookup on the IP it is connecting from and uses that hostname as chost - which fails if it?s a dynamic IP (though wildcards in some places seem to work). The solution is to put this IP in /etc/hosts so that it picks the hostname the authenticating server has in ssh_known_hosts and hosts.equiv, but that?s not practical. Is there a way to just configure it for a client or system in a config file? It?s apparently not a security measure (at least with HostbasedUsesNameFromPacketOnly=yes)? The only workaround I found is to use ?ssh -o BindAddress=10.1.2.3? which is my second loopback address that?s actually used for my FQDN in /etc/hosts. Also I wonder if the server could/should just check forward DNS against the connecting IP as a better alternative to HostbasedUsesNameFromPacketOnly=yes, this would make it work with DynDNS services. Thanks Jan
Brian Candler
2025-Sep-05 09:30 UTC
How to specify chost (client hostname) used for hostbased authentication?
On 05/09/2025 09:45, Jan Schermer wrote:> I have a question about hostbased authentication. It looks like the client does a reverse DNS lookup on the IP it is connecting from and uses that hostname as chost - which fails if it?s a dynamic IP (though wildcards in some places seem to work).For reference: https://www.rfc-editor.org/rfc/rfc4252.html#section-9 The point under consideration is: how does the openssh client select the chost value to put in the auth exchange for "hostbased" authentication? From the source: ? ? ? ? /* figure out a name for the client host */ ? ? ? ? lname = get_local_name(ssh_packet_get_connection_in(ssh)); ? ? ? ? if (lname == NULL) { ? ? ? ? ? ? ? ? error_f("cannot get local ipaddr/name"); ? ? ? ? ? ? ? ? goto out; ? ? ? ? } ? ? ? ? /* XXX sshbuf_put_stringf? */ ? ? ? ? xasprintf(&chost, "%s.", lname); ? ? ? ? debug2_f("chost %s", chost); ... char * get_local_name(int fd) { ? ? ? ? char *host, myname[NI_MAXHOST]; ? ? ? ? /* Assume we were passed a socket */ ? ? ? ? if ((host = get_socket_address(fd, 0, NI_NAMEREQD)) != NULL) ? ? ? ? ? ? ? ? return host; ? ? ? ? /* Handle the case where we were passed a pipe */ ? ? ? ? if (gethostname(myname, sizeof(myname)) == -1) { ? ? ? ? ? ? ? ? verbose_f("gethostname: %s", strerror(errno)); ? ? ? ? ? ? ? ? host = xstrdup("UNKNOWN"); ? ? ? ? } else { ? ? ? ? ? ? ? ? host = xstrdup(myname); ? ? ? ? } ? ? ? ? return host; } ... and in turn, get_socket_address() uses getpeername() or getsockname() and getnameinfo() to resolve. So in short: I believe you're right, the chost that the client sends is chosen via reverse DNS of the client-side bound socket. It does seem to me that it would be reasonable to have a client option to select an arbitrary chost string for host-based authentication (and/or to use the value of gethostname() only), but as far as I can see, no such option currently exists.> Also I wonder if the server could/should just check forward DNS against the connecting IP as a better alternative to HostbasedUsesNameFromPacketOnly=yes, this would make it work with DynDNS services.Whatever hostname the client claims to have via chosts, it has to back that up by proving possession of the corresponding private key, so any DNS checks are arguably unnecesary. Having said that, the RFC does say: Whenever possible, it is RECOMMENDED that the server perform additional checks to verify that the network address obtained from the (untrusted) network matches the given client host name. This makes exploiting compromised host keys more difficult. Note that this may require special handling for connections coming through a firewall. Regards, Brian.
Damien Miller
2025-Sep-07 01:21 UTC
How to specify chost (client hostname) used for hostbased authentication?
On Fri, 5 Sep 2025, Jan Schermer wrote:> Hi, I have a question about hostbased authentication. It looks like > the client does a reverse DNS lookup on the IP it is connecting from > and uses that hostname as chost - which fails if it?s a dynamic > IP (though wildcards in some places seem to work). The solution > is to put this IP in /etc/hosts so that it picks the hostname the > authenticating server has in ssh_known_hosts and hosts.equiv, but > that?s not practical. > > Is there a way to just configure it for a client or system in a > config file? It?s apparently not a security measure (at least with > HostbasedUsesNameFromPacketOnly=yes)? The only workaround I found > is to use ?ssh -o BindAddress=10.1.2.3? which is my second loopback > address that?s actually used for my FQDN in /etc/hosts. > > Also I wonder if the server could/should just check forward > DNS against the connecting IP as a better alternative to > HostbasedUsesNameFromPacketOnly=yes, this would make it work with > DynDNS services.There's intentionally no way for the user to specify the name that is sent in the hostbased authentication message. Others have already pointed to the code, but tldr it's the hostname that getnameinfo() returns for the outbound address of the connection or gethostname() if that fails. I say intentionally, as offering the user the ability to specify the name in the packet would create a signing oracle in ssh-keysign that would allow the hostkeys to be used to sign arbitrary hostbased auth requests. If you want to effectively configure the name in the packet, then you need to ensure that /etc/hosts has the name you want to use associated with the outbound connection address, and that the system is configured to use /etc/hosts. You can also do this via DNS, or other NSS lookup mechanisms, but /etc/hosts is the easiest generally. There might be other valid ways to do this, e.g. new knobs that can only be set via the system /etc/ssh/ssh_config (ssh-keysign already trusts this file). -d