Warlich, Christof
2020-May-19 14:28 UTC
CanonicalHostname and ssh connections through a jumphost
Hi, I have a question w.r.t. OpenSSH that I've posted to Stackoverflow: https://stackoverflow.com/questions/61723825/canonicalhostname-and-ssh-connections-through-a-jumphost Is it appropriate to ask here by posting the link? IMHO, the formatting capabilities there make it easier to read, but just in case, I've amended the question below as well ??. Many thanks for any help, Chris Say I have an internal subdomain named internal.sub.domain.net with hosts like foo.internal.sub.domain.net and bar.internal.sub.domain.net. Furthermore, these hosts are only accessible from the outside world through the jumphost internal.sub.domain.net. Thus, the following ~/.ssh/config allows me to directly connect to either of the internal hosts from outside: Host foo bar HostName %h.internal.sub.domain.net ProxyJump internal.sub.domain.net This is fine for a subdomain with just only a couple of hosts, but it quickly becomes rather unmaintainable if the number of hosts is large and / or changes occasionally. But wildcards may come to the rescue: Host *.internal.sub.domain.net ProxyJump internal.sub.domain.net This avoids the maintenance issue, but forces to always specify the fully qualified hostname to connect, which is rather tedious. From looking at the ssh_config man-page, the CannonicalizeHostname and CannonicalDomains options seems to fix that: CannonicalizeHostname always CannonicalDomains internal.sub.domain.net Host *.internal.sub.domain.net ProxyJump internal.sub.domain.net But this would only work if the name lookup for the host that is to be connected succeeds. But as these hosts are internal by definition, it is no surprise that name resolution fails. A not really helpful but very illustrative hack is to fake successful name resolutions by just adding all the internal hosts as aliases for e.g. 127.0.0.1 to /etc/hosts, i.e. adding the following line to /etc/hosts: 127.0.0.1 foo.internal.sub.domain.net bar.internal.sub.domain.net With that line in place, the last ~/.ssh/config works like a charm. But apart from the fact that this would be quite a hack, it just only shifts the maintenance issue form ~/.ssh/config to /etc/hosts. As the described scenario should not be so uncommon, is there a way to make it work? To phrase it in one sentence again: I want to be able to ssh to all internal hosts that live in the internal.sub.domain.net, i.e. that are only accessible through the internal.sub.domain.net jumphost without having to list each of these hosts somewhere, as they may frequently be added or removed from the internal domain and without being forced to always type their fully qualified hostnames.
Warlich, Christof wrote:> Hi, > > I have a question w.r.t. OpenSSH that I've posted to Stackoverflow: > > https://stackoverflow.com/questions/61723825/canonicalhostname-and-ssh-connections-through-a-jumphost > > Is it appropriate to ask here by posting the link? IMHO, the formatting capabilities there make it easier to read, but just in case, I've amended the question below as well ??. > > Many thanks for any help, > > Chris > > Say I have an internal subdomain named internal.sub.domain.net with hosts like foo.internal.sub.domain.net and bar.internal.sub.domain.net. Furthermore, these hosts are only accessible from the outside world through the jumphost internal.sub.domain.net. Thus, the following ~/.ssh/config allows me to directly connect to either of the internal hosts from outside: > > Host foo bar > HostName %h.internal.sub.domain.net > ProxyJump internal.sub.domain.net > > This is fine for a subdomain with just only a couple of hosts, but it quickly becomes rather unmaintainable if the number of hosts is large and / or changes occasionally. But wildcards may come to the rescue: > > Host *.internal.sub.domain.net > ProxyJump internal.sub.domain.net > > This avoids the maintenance issue, but forces to always specify the fully qualified hostname to connect, which is rather tedious. From looking at the ssh_config man-page, the CannonicalizeHostname and CannonicalDomains options seems to fix that: > > CannonicalizeHostname always > CannonicalDomains internal.sub.domain.net Host *.internal.sub.domain.net > ProxyJump internal.sub.domain.net > > But this would only work if the name lookup for the host that is to be connected succeeds. But as these hosts are internal by definition, it is no surprise that name resolution fails. > > A not really helpful but very illustrative hack is to fake successful name resolutions by just adding all the internal hosts as aliases for e.g. 127.0.0.1 to /etc/hosts, i.e. adding the following line to /etc/hosts: > > 127.0.0.1 foo.internal.sub.domain.net bar.internal.sub.domain.net > > With that line in place, the last ~/.ssh/config works like a charm. But apart from the fact that this would be quite a hack, it just only shifts the maintenance issue form ~/.ssh/config to /etc/hosts. > > As the described scenario should not be so uncommon, is there a way to make it work? To phrase it in one sentence again: > > I want to be able to ssh to all internal hosts that live in the internal.sub.domain.net, i.e. that are only accessible through the internal.sub.domain.net jumphost without having to list each of these hosts somewhere, as they may frequently be added or removed from the internal domain and without being forced to always type their fully qualified hostnames.If you are invoking ssh from a shell, you could define a short variable for the internal domain and append that to the relevant hostnames: e.g. in your ~/.bashrc or similar: i=".internal.sub.domain.net" Then, on the command line: ssh foo$i ssh bar$i At least until a better solution comes along. It's not perfect but it's only 2 extra characters on the command line. cheers, raf
Am Di, 19. Mai 2020, 14:28:04 +0000 schrieb Warlich, Christof:> I want to be able to ssh to all internal hosts that live in the > internal.sub.domain.net, i.e. that are only accessible through the > internal.sub.domain.net jumphost without having to list each of these hosts > somewhere, as they may frequently be added or removed from the internal > domain and without being forced to always type their fully qualified > hostnames.Hi Christof, the question is: how do you want ssh to recognize that you are trying to connect to an internal host? Here are three suggestions (none of which I've tried to there may be syntax errors and the like): If you are fine with considering any unqualified hostname as internal, you can try something like this: | Host !*.* * | HostName %h.internal.sub.domain.net | ProxyJump internal.sub.domain.net (Perhaps add !localhost to the exclusion) If you are fine with specifying explicitly that you are going to ssh to something internal, I'd put the above into ~/.ssh/config.internal and use tha following shell alias (or put the equivalent into a shell script in e.g. ~/bin/): | alias issh='ssh -F ~/.ssh/config.internal' Beware that this will ignore the system-wide configuration file, so you may want to refine that trickery a bit. E.g. you can keep the configuration in the main config file, and use the alias to invoke ssh with a magic environment variable set, and make the configuration dependent on that environment variable using a Match block rather than a Host block. Finally, if a seperate command is not an option for you and you still want to connect to an unbounded set of non-internal unqualified hosts in addition to an unbounded set of internal unqualified hosts, you can try to determine whether a given host is internal like this: | Match host="!*.*,*" exec="ssh internal.sub.domain.net getent hosts %h.internal.sub.domain.net" | HostName %h.internal.sub.domain.net | ProxyJump internal.sub.domain.net Depending on how ssh orders evaluation of its Match conditions, you may need to move the matching of the host pattern into the exec as shell code to avoid infinite recursion. Beware that this may be subject to shell injection if you can't fully trust the hostname ssh is invoked with. Plus you have the overhead of an additional ssh connection for every unqualified host you connect to. Regards, J?. -- -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: not available URL: <http://lists.mindrot.org/pipermail/openssh-unix-dev/attachments/20200520/78e567b3/attachment-0001.asc>