传统的 telnet、rcp ftp、rlogin、rsh 都是极不安全的,并且会使用明文传送密码,OpenSSH 提供了服务端后台程序和客户端工具,用来加密远程控件和文件传输过程中的数据,并由此来代替原来的类似服务。
OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现,SSH 协议族可以用来进行远程控制,或在计算机之间传送文件。这里简单介绍下 SSH 和 OpenSSH 的使用。
简介
SSH 采用的是公私钥加密方式,利用公钥进行加密,通过私钥解密,公钥任何人都可以看到,而私钥是私有的,需要安全保存。目前 ssh 有 V1 和 V2 两个版本, V2 加入了联机检测功能,可以避免联机过程中插入恶意攻击代码。
最常用的是远程登录,除此之外,还支持端口映射、X11 转发、sftp 文件传输等。
工作过程
- 服务器侧私钥文件,安装后会生成
/etc/ssh/ssh_host*
密钥文件,启动时会进行检查。 - 客户端将已知服务器的公钥保存在
~/.ssh/known_hosts
中,如果不存在则提醒用户是否添加。
安装使用
OpenSSH 不仅提供了一个 shell,而且还提供了一个较为安全的 ftp-server
做文本传输。
# dpkg --list | grep ssh # Ubuntu中查看/安装OpenSSH Server
# apt-get install openssh-server
# yum install openssh-server openssh-clients openssh # CentOS中安装
Ubutnu 中安装之后会包括 /etc/init.d/ssh
文件,可以通过如下方式启动/停止/重启 Openssh Server 。
# /etc/init.d/ssh [start | stop | restart]
# service ssh [start | stop | restart]
通过如下命令可以查看服务是否已经启动,其中 ssh 使用的是 22 号端口,使用 tcp 协议, ftp 同样使用 22 号端口。
# netstat -vatn | grep 22
在 CentOS7 中,可以通过如下命令启动。
# systemctl start sshd.service
客户端使用
正常情况下在安装完服务器后,可以通过如下命令进行简单的登录,如果远程主机的用户名和本地用户名一致可以省略 user,否则需要显示指定。
$ ssh user@host command
关于 ssh 客户端的详细参数可以参考 man 命令,常用的参数有:
-p
指定端口号,如果服务端非默认的 22 端口通过该参数指定。-f
不登入主机直接执行一个命令。-v
查看登录时候的详细信息,参数越多显示的详细信息越多,例如-vv
、-vvv
。-i
指定登录用的私钥文件。
另外,最常用的是通过 -o
参数指定选项,例如 ConnectTimeout=10
指定超时时间为 10 秒,如下是常见选项:
ConnectTimeout=N
与服务端建立链接时超时等待的时间。StrictHostKeyChecking=[yes|no|ask]
新服务器如何添加到known_hosts
文件,默认是 ask 由客户决定,或者 yes 直接加入。PreferredAuthentications=publickey
指定登录时权限认证方案,包括publickey、password、keyboard-interactive 等。IdentitiesOnly=yes
只使用指定的鉴权方式,否则通过-i
指定后还会尝试默认的私钥,通过该参数则只使用指定。
如下简单介绍经常使用的场景。
在服务端执行命令
登入对方主机执行过指令后立刻离开。
$ ssh student@127.0.0.1 find / & > ~/find1.log
此时你会发现怎么画面卡住了,这是因为上头的指令会造成,已经登入远程主机,但是执行的指令尚未跑完,因此会在等待当中。
与上相似,但是让对方主机自己跑该指令,立刻回到本地主机继续工作。
$ ssh -f student@127.0.0.1 find / &> ~/find1.log
此时你会立刻注销 127.0.0.1 ,但 find 指令会自己在远程服务器跑喔!
配置文件
默认包括了如下的配置文件:
/etc/ssh/sshd_config
服务器配置文件。~/.ssh/authorized_keys
服务端保存的用户公钥,在登录用户主目录下,需手动设置,常用于“无密码登录”。/etc/ssh/ssh_config
~/.ssh/ssh_config
客户端全局、用户配置文件。~/.ssh/known_hosts
客户端记录已通过验证的服务器,第一次登录时会提示是否将服务器添加到该文件中,以后再登录时,会利用该文件检测是否是之前的服务器,从而防止中间人攻击。
如下介绍服务端的详细介绍。
整体配置
Protocol 2,1 # SSH协议版本,1可能会有中间人攻击,建议只配置为2
登入设定部分
PermitRootLogin yes # 是否允许root登入
StrictModes yes # 严格检查目录权限,权限设置出错则不允许登陆
PubkeyAuthentication yes # 允许公钥登陆
AuthorizedKeysFile .ssh/authorized_keys # 公钥保存文件
HostbasedAuthentication no # 取消基于host的授权
PasswordAuthentication yes # 使用密码验证
PermitEmptyPasswords no # 是否允许以空的密码登入
AllowUsers list # 允许登陆的用户,用空格分开,可以用*?通配符
DenyUsers foobar # 禁止某一个用户登入
AllowGroups nosh # 允许某一个组登入
DenyGroups nosh # 禁止某一个组登入
登入后设置
ClientAliveInterval 300 # 若300秒内没有收到客户端消息,则发送心跳报文
ClientAliveCountMax 0 # 客户端断开连接之前,能发送保活信息的条数,此时踢出用户
安全设置
IgnoreRhosts yes # 取消使用~/.ssh/.rhosts来做为认证
其它
UseDNS yes # 关闭DNS验证,详见后面的介绍
杂项
整理一些常见的配置、注意事项、使用技巧。
目录权限设置
ssh 对目录的权限有要求,主要是为了防止一些加密信息泄漏,使用时要设置好新生成的 config 文件权限才行,包括 ~
目录权限是 750,~/.ssh
的是 700,~/.ssh/*
的是 600,~/.ssh/config
是 700 。
客户端心跳报文
主要是为了防止长时间没有交互导致链接断开,不同客户端设置略有区别。
SecureCRT:
Properties->Terminal->Anti-dile
设置每隔80秒发送一个字符串或是NO-OP协议包
Putty:
Properties->Connection->Seconds between keepalives(0 to turn off)
默认为0,改为80
Xshell:
File->Properties->Connection->Keep Alive
设置为80s
Linux:
在/etc/ssh/ssh_config添加ServerAliveInterval 80
关闭DNS检查
OpenSSH 服务器有一个 DNS 查找选项 UseDNS
默认是打开的。
当客户端试图登录 OpenSSH 服务器时,服务器端先根据客户端的 IP 地址进行 DNS PTR 反向查询,查询出客户端的 host name,然后根据查询出的客户端 host name 进行 DNS 正向 A 记录查询,验证与其原始 IP 地址是否一致。
这是防止客户端欺骗的一种手段,但一般 IP 是动态的,不会有 PTR 记录的,打开这个选项不过是在浪费时间。
减少延迟
如果每次连接服务器都意味着你需要等待几十秒而无所事事,那么你或许应该试试在你的 SSH 配置中加入下面这条,这一配置可以在客户端或者服务端配置,或者在 ssh 登录时加上 -o GSSAPIAuthentication=no
。
GSSAPIAuthentication no
GSSAPI 是 Generic Security Services Application Program Interface (通用安全服务应用程序接口) 是 ITEF 的一个标准,允许不同的安全算法使用一个标准化的 API 来为网络产品提供加密认证。
OpenSSH 使用这个 API 并且底层的 kerberos 5 协议代码提供除了 ssh_keys 的另一种 ssh 认证方式。
参考
- github 上收集的与 SSH 相关的经典内容 ssh awesome 。
- 可以参考 SSH The Secure Shell The Definitive Guide 文档。