在〜/ .ssh / config中动态生成SSH主机条目


9

我必须通过ssh管理一大堆主机。但是,我只能通过某个网关ssh服务器访问它们。

我的内容如下~/.ssh/config

Host mygateway-www
Hostname www
IdentityFile ~/.ssh/id_rsa
ProxyCommand ssh mygateway nc %h 22

但是,我必须连接许多这样的机器。不用在我的中放置数十个条目,反而~/.ssh/config我可以拥有这样的东西:

Host mygateway-*
Hostname ???WHAT GOES HERE????
IdentityFile ~/.ssh/id_rsa
ProxyCommand ssh mygateway nc %h 22

我知道您可以%hHostname参数中使用,但这将是主机名。我真正需要的是某种字符串替换,例如bash的${VAR%thingie}。这可能吗?

Answers:


24

可以使用以下SSH配置文件完成此操作:

Host *
  ServerAliveInterval 120

Host gateway.somewhere.com
  User jdoe

Host gateway+*
  User jdoe
  ProxyCommand ssh -T -a $(echo %h |cut -d+ -f1).somewhere.com nc $(echo %h |cut -d+ -f2) %p 2>/dev/null
  ControlMaster auto
  ControlPath ~/.ssh/ssh-control_%r@%h:%p

然后,您可以像这样访问内部主机:

ssh gateway+internalhost01.somewhere.com
ssh gateway+internalhost02.somewhere.com

您为右半部分选择的名称应可由跳转主机解析。

如果需要手动映射到不同类别的主机上的不同用户,则指定User参数。指定ControlMaster和ControlPath以允许重新使用SSH连接。


6

您不需要手动指定HostName,因为它将来自命令行。

只需尝试:

Host *.domain  
  IdentityFile ~/.ssh/id_rsa  
  ProxyCommand ssh mygateway /usr/bin/nc %h 22

这种方法的问题在于主机名是通用名称(例如db1,www,mail2),而我也希望它们也带有项目前缀,因为我可能需要将SSH切换到另一台名为“ db2”的机器。因此,主机中的前缀
Rory

2
因此,您实际上要重新配置DNS。最简单(但最麻烦的解决方案)是修改您的主机文件。另一方面,您可以始终将具有.invalid域的本地DNS服务器添加到您的工作站,并使用您喜欢的主机名。
Martin M.

+1前一个。为每个项目创建一个子域。DNS可以使您的生活更轻松;)
Dan Carley

1

似乎没有任何方法可以执行此操作。


1

我遇到了类似的问题,最终写了一个脚本,为我生成了所有样板文件。我不再更改〜/ ssh / config,而是更改〜/ ssh / config.in并重新运行脚本。


1
想分享您的脚本吗?我已经考虑过这样做,但是似乎一个健壮且通用的解决方案可能需要大量工作才能正确完成。即使您的解决方案还不是这样,了解您认为正确的方法以及重新完成操作也会有不同的用途。
iconoclast

我的想法是.ssh/config.d每个模板都有一个文件,其中每个模板将在final中生成一个或多个条目~/.ssh/config。也将有一个带有通用变量的文件,但是每个模板可以有其自己的变量,这些变量将优先于全局变量(在顶部列出)。该~/.ssh/config文件可能根据需要或问题,只要你从来没有直接编辑它,你想保存生成的时间表,它不会。
iconoclast

我的脚本是完全没有文档的,如果没有文档或示例,我认为我没有时间来创建它,那么我认为它是无法理解的。
Michael Hoffman

可以理解的 对于我概述的方法的任何反馈将不胜感激,特别是如果我忽略了一些重要的需求或用例,或者是一些大(或小)障碍时。
iconoclast

1
我认为这是一种很好的方法,可能比我使用的方法少一些混乱。我将许多主机声明读入内存,然后读取了许多非主机声明。非主机声明将应用于当前组中的每个主机,直到有另一个主机为止。我还允许在文件中多次声明Host,包括使用globbing。最后,我写出我在内存中构建的所有内容。
Michael Hoffman

1

忽略直接通过Hostname声明指定覆盖主机名,而是在运行时确定它。为此,请将其作为的一部分进行评估ProxyCommand%h并在命令中引用它(也可使用%p代替22的硬编码端口),即

Host mygateway-*
   #Hostname ???WHAT GOES HERE????
   IdentityFile ~/.ssh/id_rsa
   ProxyCommand ssh mygateway nc $(echo %h|sed 's/^mygateway-//') %p

一个人甚至可以拥有一个更通用的节,通过该节,您可以指定任何不带主机的主机,而-只需按原样或按照其他匹配的节来对待,但可以采用一种通用的-方法来指定任何主机<gateway>-<target>

Host *-*
   # Assume LHS of "-" is GW and RHS of "-" is target host
   IdentityFile ~/.ssh/id_rsa
   ProxyCommand ssh $(echo %h|cut -d - -f1) nc $(echo %h|cut -d - -f2-) %p

此外,较新版本的SSH客户端支持[-W host:port]直接与nc(netcat)执行相同功能的选项。因此,我们可以使用修改后的代码:

Host *-*
   # Assume LHS of "-" is GW and RHS of "-" is target host
   IdentityFile ~/.ssh/id_rsa
   ProxyCommand ssh -W $(echo %h|cut -d - -f2-):%p $(echo %h|cut -d - -f1)

当然,如果确实有有限的主机列表,则可以始终这样做:

Host host1 host2 host3 hostN
   IdentityFile ~/.ssh/id_rsa
   ProxyCommand ssh mygateway nc %h %p

希望这可以帮助!


0

我有一个具有相同设置的客户端,并且使用DSSH解决了我的问题。
DSSH除其他功能外,还允许您通过网关主机透明地登录到远程主机。

用例

  • 从需要“ ena”登录的Cisco路由器收集配置参数
  • 登录到具有PermitRootLogin的服务器,该服务器直接以root用户身份(通过自动输入su-和密码)被禁用,同时保留退出状态
  • 添加自定义逻辑,例如高级日志记录
  • 通过多个连接建立隧道以到达目标服务器

5
我宁愿不开始使用一些使用java的随机第三方ssh客户端,因为我可以在〜/ .ssh / config中做这些事情。
罗里

链接已消失
iconoclast

该软件源可以在Github上找到:github.com/digmia/dssh
Guest,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.