简介
如果需要远程访问计算机并启用了 Secure Shell (SSH) 连接,黑客就会尝试突破您的防线并控制您的计算机,您必须接受这个事实。尽管不能保证计算机不会被 “黑客” 占领,但是一些简单的解决方案有助于保护 SSH,可以让攻击困难一些。本文讨论三种技术:
要想应用这些技术,需要能够访问根账户。另外,可能必须安装一些包,需要配置防火墙和路由器(如果有路由器的话),打开和关闭特定的端口并把数据包转发到您的计算机。
加强保护
“隐匿产生安全” 这个概念尽人皆知而且受到大家的嘲笑,因为采用隐匿的方式,希望没人了解您的方法,这只是一厢情愿的想法。但是,在某些场景中,隐匿一点儿会有帮助。尽管简单的措施无法阻止下定决心的黑客,但是至少能够挡住那些 “脚本小子”,他们的脚本往往水平很一般。
人人都知道 SSH 连接的标准端口是 22。因此,为了让计算机更安全,应该采取的第一个措施是把端口改为另一个不常用的非标准端口号,比如 22960。1024 以上的号码通常都可以使用,但是应该查阅参考资料以避免导致问题。这一修改对您的影响仅仅是必须使用下面的命令连接计算机:
ssh -p 22960 your.machine.url
为了实现这个小措施,只需在 /etc/ssh/sshd_config 文件中做简单的修改。编辑此文件(必须作为根用户),寻找 Port 22 行,把端口号改为您选择的号码(如果这一行以镑符 [#] 开头,表示它被注释掉了,那么应该取消注释标志)。保存文件,用/etc/init.d/sshd restart 命令重新启动 SSH。应该在防火墙上打开您选择的端口并关闭端口 22。
但是,还可以更进一步。编辑配置文件,在其中包含 清单 1 所示的行。注意,其中一些行可能已经存在,但是可以把它们注释掉。
清单 1. 通过修改 SSH 配置文件简便地增强安全性
Port 22960
LoginGraceTime 30
MaxAuthTries 3
Protocol 2
PermitRootLogin no
LoginGraceTime 允许一次登录花费 30 秒;如果用户花费的时间超过 30 秒,就不允许他访问,必须重新登录。MaxAuthTries 把错误尝试的次数限制为 3 次,3 次之后拒绝登录尝试。上面的 Protocol 2 行禁止使用比较弱的协议。最后一行不允许任何人作为根用户登录,这会让黑客攻击更困难。还可以使用 DenyUsers、AllowUsers、DenyGroups 和 AllowGroups 选项实现其他限制。这些修改不会显著增强计算机的安全性,但是只尝试强力攻击标准端口 22 的一般脚本会失败,不会造成损害。无论如何,这是向正确的方向迈出了第一步。在本文后面,我们将使用更安全的方法,不仅修改端口号,而且完全隐藏它。
谁可以进入?
对于大多数人,PAM 是一种罐装的烹调油。但是作为 Linux® 安全术语,PAM 代表可插入身份验证模块(Pluggable Authentication Modules)。这些模块提供额外的身份验证规则,保护对计算机的访问。
首先讨论一个基本问题:究竟为什么要使用 PAM?如果每个程序不得不定义自己的身份验证逻辑,就会很混乱。如何确定所有应用程序都实现了相同的测试和检查?如果需要额外的控制手段,那么怎么办?难道要重新编写所有程序吗?在计算机科学领域,有时候可以用额外的一层解决所有问题,至少在安全方面是这样。如果一个程序需要验证用户的身份,它可以调用 PAM API。这个 API 负责执行在 PAM 配置文件中指定的所有检查。这种方法还允许方便地修改身份验证规则,所有感知 PAM 的程序都会自动地应用新规则,不需要修改它们的代码。如果希望使用某种生物学检查(比如虹膜扫描器或指纹采集器),而且生产商提供了 PAM,就可以方便地设置它。在配置文件中包含模块调用,所有应用程序就可以使用这个设备了。
配置 PAM
PAM 提供四个安全领域的特性,但是应用程序不太可能同时需要所有这些方面。例如,passwd 命令只需要下面列表中的第三组:
在 /etc/pam.d 目录中为将使用 PAM 的每个应用程序创建一个配置文件,文件名与应用程序名相同。例如,login 命令的配置文件是 /etc/pam.d/login。
必须定义将应用哪些模块,创建一个动作 “堆”。PAM 运行堆中的所有模块,根据它们的结果允许或拒绝用户的请求。还必须定义检查是否是必需的。最后,other 文件为没有特殊规则的所有应用程序提供默认规则。
配置文件的结构很简单。可以包含注释,注释以散列符 (#) 开头;通过在换行处加上反斜杠 (/),可以把长的行分为多行。行有三个字段:领域 (account、auth、password 或 session)、控制标志(optional、required、requisite 或 sufficient)、将运行的模块的路径和参数。注意,第二个字段可以更复杂;更多信息见 参考资料。另外,可以使用 include 规则以包含其他文件中的规则,比如auth include common-account。
特殊的 /etc/pam.d/other 文件是 “默认的” 配置文件(见 清单 2),其中的规则自动地应用于没有自己的配置文件的所有应用程序。为了确保安全,应该快速检查 /etc/pam.d 目录,把您不使用的所有配置文件改为其他名称(这样就会使用 other 配置)。如果认为确实需要某个应用程序,那么只需把配置文件改回原来的名称。默认配置通常拒绝所有请求(通过使用 pam_deny.so 模块)并警告管理员(通过 pam_warn.so 模块),让管理员解决问题。
标准的 “other” 配置文件为没有自己的配置文件的所有应用程序提供安全的默认规则(拒绝所有请求)。
清单 2. 标准的 “other” 配置文件
account required pam_deny.so
auth required pam_deny.so
auth required pam_warn.so
password required pam_deny.so
password required pam_warn.so
session required pam_deny.so
如果把 pam_deny.so 替换为 pam_unix.so,就应用标准的身份验证方法(输入用户名和密码)。如果您不关心安全性,那么使用pam_permit.so,这会允许任何请求!
一些可用方法
尽管没有标准的模块列表,但是所有发行版都包含以下模块中的大多数。请检查驻留模块的 /lib/security 或 /usr/lib/security 目录。对于 64 位操作系统,用 lib64 替换 lib。如果需要更多信息,可以尝试执行 man the.name.of.the.module,而不要直接执行它;PAM 不是可执行的二进制代码。
关于其他模块和编写自己的模块的信息,请查阅 参考资料。现在,使用 PAM 决定谁可以登录您的计算机。
用 PAM 限制访问
现在,我们来使用 PAM 限制谁可以连接您的服务器。必须编辑 /etc/pam.d/sshd 文件,让它像清单 3 这样。
清单 3. 在 sshd PAM 文件中添加 pam_access.so
#%PAM-1.0
account include common-account
account required pam_access.so
auth include common-auth
auth required pam_nologin.so
password include common-password
session include common-session
在 sshd PAM 文件中添加 pam_access.so,就可以轻松地定义谁可以使用 SSH 连接您的计算机。pam_access.so 模块实现基于 /etc/security/access.conf 文件的安全控制,见清单 4。
清单 4. 通过使用 pam_access.so,定义谁可以或不可以使用 SSH
+ : ALL : 192.168.1.
+ : jack : ALL
+ : jill : ALL
- : ALL : ALL
第一行允许任何用户 (ALL) 从内部网络登录。后两行允许用户 jack 和 jill 从任何地方访问服务器。最后一行拒绝其他任何用户从其他任何地方访问。允许多个用户访问的另一种方法是使用 pam_listfile.so,这需要创建一个允许访问的用户列表(例如 /etc/ssh_users)。在 /etc/pam.d/sshd 文件中添加以下行:
auth required pam_listfile.so item=user sense=allow
file=/etc/ssh_users onerr=fail
这还没有完。必须修改 /etc/ssh/sshd_config 文件,让它使用 PAM。在此文件中添加 UsePAM yes 行,重新启动 sshd 守护进程,这样就行了!
究竟是否有门?
即使应用了前两节中的方法,无论您怎么预防,黑客仍然会尝试穿越您系统中任何开放的门户。改变 SSH 端口号对于经验丰富的黑客只能造成小小的麻烦。限制允许访问的用户会有帮助,但前提是没有用户落入黑客或社会工程攻击的圈套而泄露密码。无论如何,只要您的系统中有门,就会吸引黑客。
增强计算机安全性的最后一种方案是最激进的:关闭打开的端口,这会让任何攻击都无法攻破您的计算机。只向能够提供 “秘密敲门暗号” 的用户开放所需的端口,让用户能够输入密码并访问计算机。
这种技术称为端口敲门,适用于需要访问不向公众开放的服务器的用户。服务器可以关闭所有端口,直到用户提供一个秘密的敲门序列 (序列很容易实现,而且需要的资源不多)。
打开秘密端口之后,应用常用的安全机制(比如密码或证书)。只需在防火墙级上提供一个额外的安全层,需要秘密端口的所有服务就会正常工作。
这种方法的要点在于关闭所有端口并监视外部连接尝试。当识别出预定义的尝试序列(称为敲门序列 )时,可以执行打开端口等操作,让外部的用户能够进来。敲门序列的复杂程度由您决定,从简单的列表(比如依次尝试 TCP 端口 7000、UDP 端口 7100 和 TCP 端口 7200)到一次性序列集合都可以。(按密码学术语来说,一次性序列与 “一次一密” 相似,这是已知最安全的加密方法。)外面的用户必须知道使用 SSH 所需的端口号和密码,还必须知道打开端口并启用密码所需的敲门序列。如果没有这个序列,连接尝试就会静悄悄地失败。
这为什么是非常安全的方案?因为有 65,535 个端口(见 参考资料)。即使考虑到已经分配的端口,仍然有超过 60,000 个可用端口。如果敲门序列只包含四次 “敲门”,黑客要想通过强力攻击猜出序列,就必须测试大约 13,000,000,000,000,000,000 个序列(13 后面 18 个零)。这样的攻击显然不太可能奏效!当然,强力攻击或胡乱猜测并不是猜出正确序列的惟一方法。因此,不要只使用单一安全方法;而是使用一系列安全层来增加攻击的难度。
必须安装敲门守护进程 knockd;它监视敲门序列,当发现有效的序列时执行相应的操作。如果愿意,可以从头构建它,但是大多数(如果不是所有的话)发行版中都有这个包。最好使用包管理工具安装它。例如,在 OpenSUSE 中,可以使用 Yast2 或通过执行sudo zypper install knockd 安装它。在 Ubuntu 中可以使用 sudo apt-get install knockd,在 Debian 中使用 sudo aptitude install knockd。用发行版的软件安装工具搜索 knockd 往往能够找到它。
安装这个包之后,必须编辑 /etc/knockd.conf 文件以指定端口敲门规则,然后启动守护进程。为了完成所需的设置,必须了解您的防火墙的工作方式。例如,在 OpenSUSE 中,可以使用 清单 5 这样的设置。
清单 5. 针对 OpenSUSE 防火墙设计的示例配置文件
[opencloseSSH]
sequence= 7000,8000,9000
tcpflags= syn
seq_timeout= 15
cmd_timeout= 30
start_command= /usr/sbin/iptables -s %IP% -I input_ext 1 -p tcp –dport 22960 -j ACCEPT
stop_command= /usr/sbin/iptables -s %IP% -D input_ext -p tcp –dport 22960 -j ACCEPT
这个示例在用户依次在端口 7000、8000 和 9000 上敲门之后启用 SSH 访问。
在启动 knockd 之前,关闭端口 22960 并尝试远程登录。这个尝试应该会失败,见清单 6。
清单 6. 如果禁用 SSH 访问而且不启动敲门守护进程,登录尝试会失败
> ssh the.url.for.your.site -p 22960 -o ConnectTimeout=15
ssh: connect to host the.url.for.your.site port 22960: Connection timed out
现在,使用 sudo /etc/init.d/knockd start 或 sudo knockd -d 启动端口敲门守护进程(这两个命令是等效的),然后再试一下;端口敲门序列要求在端口 7000、8000 和 9000 上敲门。必须在 15 秒内完成这个序列。识别出序列之后端口打开,必须在 30 秒内登录。否则,端口再次关闭。
为了检验这个过程,回到您的远程机器上并登录。这一次提供所需的敲门序列,见 清单 7。注意,在安装 knockd 时通常也会安装knock 命令。如果不是这样,只需用发行版的包管理工具搜索它。
清单 7. 提供所需的敲门序列之后登录成功
> knock the.url.for.your.site 7000
> knock the.url.for.your.site 8000
> knock the.url.for.your.site 9000
> ssh the.url.for.your.site -p 22960 -o ConnectTimeout=10
Password:
如果提供了错误的敲门序列(或根本没有敲门),会收到 “Connection timed out” 消息,SSH 端口仍然完全关闭,看不出它是存在的。
如果您处于路由器后面
如果您的服务器通过路由器连接 Internet,就必须修改它的配置。具体细节因路由器和防火墙类型而异,但是一般来说应该:
尽管路由器会打开一些端口,但是对它们的所有访问都会到达您计算机的防火墙。访问会被阻止,除非探测到正确的端口敲门序列。
敲门配置
/etc/knockd.conf 文件有一个一般选项小节 options,希望使用的每个敲门序列各有一个小节。选项可以是大写、小写或大小写混合形式。
可以让 knockd 监听多个序列并以不同方式响应各个序列。在前面的示例中,让 knockd 打开 SSH 端口;可以简单地启用 HTTP 端口,让用户能够访问 web 服务器,也可以运行特定的进程。在配置文件中,每个序列都有相应的小节。
使用任何文本编辑器创建此文件;其中每行包含一个序列(按照上面所示的格式)。应该在远程计算机上保存此文件的拷贝以便记住如何登录。
iptables 向提供敲门序列的 IP 地址上的用户开放端口 22960。
在这里,因为只希望打开或关闭端口 22960,所以使用单一命令就够了。如果需要更复杂的操作,可以通过调用脚本执行所需的任何操作 — 操作甚至可以完全不涉及打开端口。可以触发任何操作,比如运行进程或执行备份。当然,了解要使用的命令可能有点儿难度。例如,因为我运行 OpenSUSE,它提供自己的防火墙前端,所以我不得不通过查看 iptables -l 的输出了解应该执行哪个命令来打开或关闭端口 22960。
对于 knockd 本身,有几个选项需要考虑:
最后,可以使用多种方法产生敲门序列本身,编写 knock 命令是最简单的方法。
以下命令在 TCP 端口 7000 上敲门:
knock the.url.for.your.site 7000
以下命令在 UDP 端口 8000 上敲门:
knock the.url.for.your.site -u 8000
或
knock the.url.for.your.site 8000:udp
-h 参数提供这个命令的帮助。
结束语
您看到了三种保护 SSH 访问的方法:修改 sshd 的配置参数,通过 PAM 限制可以登录的用户,以及使用端口敲门序列隐藏存在 SSH 访问的事实。尽管没有任何方法能够完全保护任何计算机,但是采取这三个措施会让您的服务器安全一些。
源文档