openssh
openssh

一、从需求说起

现网所有的服务器连接都要通过一台堡垒机进行用户名密码认证,根据安全合规要求,默认不允许root直接登陆。而某业务模板要实现容灾自动切换功能,其又需要配置某两台切换平台管理机和该业务平台主机的ssh互信(root免密码登陆)。这里就涉及到一个安全需求和业务需求的一个冲突。哪有没有一种配置方法可以只针对个别主机开启root直接登陆或秘钥登陆,而对其他主机还是之前的安全配置策略?答案肯定是有的,而且不止一种。先梳理下能想到的和ssh安全需求相关的信息(本文只涉及Linux系统自带工具,不涉及动态码,二次验证等):

1# ssh参数部分
2PermitRootLogin
3Allowuser相关
4Match
5# 外部工具
6tcp_wrappers
7pam_access
8iptables

二、PermitRootLogin参数

该选项默认有四个值可用:“yes”, “without-password”, “forced-commands-only”, or “no”,默认是yes 。这四个选项里,yes/no两个不用解释,平时用的最多,就是是否允许root直接登陆。

  • without-password :这个从字面意思上也很好理解,即不使用密码,可以使用key认证。即如果使用root的密码登陆,即使是对的也会登陆不上(使用普通用户登陆后,su不受此影响),使用key的话,可以直接 ssh用root登陆。
  • forced-commands-only:看man里的解释:If this option is set to “forced-commands-only”, root login with public key authentication will be allowed, but only if the command option has been specified (which may be useful for taking remote backups even if root login is normally not allowed). ,可能会看的比较郁闷,又说允许key认证,但需要在特殊情况下。什么叫特殊情况,比如:rsync备份可以走ssh协议,这里的ssh就是特殊的参数选项啊。就个时候是可以正常用key认证的。但如果想通过ssh root@IP这样的方式登陆,不好意思不通过,不会给你分配shell使用。

forced-commands-only参数使用时,是需要在公钥中增加对应的command配置的,不然还是不行的。这个是想当于把ssh后可以执行的命令进行了最小限制,这里来个示例截图:

forced-commands-only
forced-commands-only

所以从上面的理解并配合测试结果来看,without-password参数算凑合满足上面的需求,但还不够严谨。

三、Allowuser相关参数

AllowUsers相关的参数有四个,这个参数对应的顺序是:The allow/deny directives are processed in the following order: DenyUsers, AllowUsers, DenyGroups, and finally AllowGroups. 。其用法如下:

1Allowusers root@10.212.52.253
2Allowusers zabbix,nginx

如果不在Allow选项的,登陆后,会在日志中有如下记录:User root from 10.212.52.14 not allowed because not listed in AllowUsers 。如果上面的示例中,如果只有一条Allowusers root@10.212.52.253规则,猜猜使用test用户ssh登陆会发生什么?

答案是会发生灾难,在启用Allowusers策略后,默认有一条看见的策略是Deny ALL ,这点和tcp_wrappers很像—-除非明确允许的,其他的都是禁止的。使用上面的一条策略后,本机会只允许来自10.212.52.253的主机使用root用户登陆本机。其他任何主机,任何用户登陆过来都是not allow,52.253主机使用nginx过来能不能过来?不能,虽然52.253在允许的IP,但其有前缀root,这是有条件的登陆。

Allowuser参数符不符合上面的需求?仅从技术角度来说简直太符合了,而且安全性很强。但是业务新增一个用户,想从其他主机登陆过来,就要在策略里增加该用户,不然只能通过允许的用户su过去。这点容易和业务逻辑茅盾。

注:另外三个参数可以参照Allowuser,用法是一样的。

四、Match参数

Match参数是个有意思的参数,其在全局不变的情况下,允许个别符合的例外。这点用两个社会词概况最恰当不过—-“走后门”,“开小灶” 。可能很多人在用这个参数时表示不生效,请注意两点:一点是man里的提示:until either another Match line or the end of the file.(需要写在sshd_config的最后或者实完后在下面加一行Match all),另一点是Match规则匹配后,后面的参数项在别起一行时是不顶格写的。

例1:只允许192.168.2.5主机进行root登陆

1PermitRootLogin no
2Match Address 192.168.2.5
3PermitRootLogin yes

例2:多个主机或IP段

1PasswordAuthentication no
2Match Address 192.168.184.8,202.54.1.1,192.168.1.0/24
3PermitRootLogin yes

例3:用户加IP多匹配

1PasswordAuthentication no
2Match User zabbix Address 192.168.1.0/24
3PasswordAuthentication yes

例4:通配符匹配

 1## Match 192.168.1.1 to 192.168.1.9 ##
 2Match Address 192.168.1.?
 3    PermitRootLogin yes
 4
 5## Match 192.168.1.{2,3....}  ##
 6Match Address 192.168.2.*
 7    X11Forwarding no
 8
 9## Allow any host in the ".home.lan" set of domains ##
10Match Host *.home.lan
11X11Forwarding yes
12
13## Allow everyone except foo user ##
14Match User *,!foo
15      X11Forwarding yes
16      PermitTunnel yes
17      PermitTTY no

Match适用的参数很多,基本sshd里大部分参数都是适用的。而且从上面的示例上也可以看出,Match完全符合上面的需求。

ssh参数和本需求相关的部分就介绍到这里,在测试的时候还需要注意一点,每次ssh的配置变更,都需要重启ssh服务器才能生效的,重启上也可以使用sshd -T和sshd -t测试配置。

五、外部工具

这里提到的外部工具是指ssh之外,但还都是系统自带工具。

1、iptables

先说iptables,因为iptables不满足上在的需求,其能做的只是基于IP和ssh 端口的匹配,允许哪个IP,不允许哪个IP。但是对于用户,其匹配不到。

2、tcp_wrappers

tcp_wrappers和pam_access我在很早之前的一篇博文《RH442之/etc/security/access.conf与tcp_wrappers》中有提到。TCP_wrppers和iptables类似,都可以看成防火墙类。其同样只能针对服务和来源IP、域名的匹配。无法针对用户这种级别做策略,也无法满足上面的需求。

3、pam_access

从名称也可以看出,pam_access是一个模块,其在使用的时候,需要在对应的pam下的服务配置里增加相应的调用才行。这里就对应上面的需求ssh服务,先增加该模块的调用:

1account    required   pam_access.so

接着配置其对应的默认配置文件/etc/security/access.conf ,这里先增加一行配置,如下:

1+ : root : 10.212.52.14

可以猜想下如果从10.212.52.253 ssh用root用户登陆本机能不能登陆上?

绝对可以,这点又和上面的Allowusers和tcp_wrppers不同。其是未明确不允许的,都是默认允许。上面的配置虽然通过+号表示允许52.14主机连接,但其也没有表示其他主机不能连接。如果其再增加一行:

1- : root : ALL

这样两行配合,就可以完全满足上面提到的需求。

六、linux思维

算是一点小总结吧,从上在的简单需求,再次印证了在linux平台的人性化,实现同一问题,方法不止一种。尽力发掘你能想到的方法。