sshd服务分析
00、阐述 sshd 服务
基本上,所有的 ssh 相关设定都放在 /etc/ssh/sshd_config 里面!不过,每个 Linux distribution 的预设设定都不太相同, 所以我们有必要来了解一下整个设定值的意义为何才好!(一般就看启动脚本的定义路径,像基于源码升级openssh)
service sshd restart |stop |reload #sshd脚本路径/etc/init.d/sshd
[root@mvp ~]# cat /etc/init.d/sshd #!/bin/bash # # sshd Start up the OpenSSH server daemon # # chkconfig: 2345 55 25 # description: SSH is a protocol for secure remote shell access. \ # This service starts up the OpenSSH server daemon. # # processname: sshd #sshd进程的默认配置 # config: /etc/ssh/ssh_host_key # config: /etc/ssh/ssh_host_key.pub # config: /etc/ssh/ssh_random_seed # config: /etc/ssh/sshd_config # pidfile: /var/run/sshd.pid ### BEGIN INIT INFO # Provides: sshd # Required-Start: $local_fs $network $syslog # Required-Stop: $local_fs $syslog # Should-Start: $syslog # Should-Stop: $network $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start up the OpenSSH server daemon # Description: SSH is a protocol for secure remote shell access. # This service starts up the OpenSSH server daemon. ### END INIT INFO # source function library . /etc/rc.d/init.d/functions # pull in sysconfig settings [ -f /etc/sysconfig/sshd ] && . /etc/sysconfig/sshd RETVAL=0 prog="sshd" lockfile=/var/lock/subsys/$prog # Some functions to make the below more readable #文件的路径 KEYGEN=/usr/bin/ssh-keygen SSHD=/usr/sbin/sshd RSA1_KEY=/etc/ssh/ssh_host_key RSA_KEY=/etc/ssh/ssh_host_rsa_key DSA_KEY=/etc/ssh/ssh_host_dsa_key PID_FILE=/var/run/sshd.pid runlevel=$(set -- $(runlevel); eval "echo \$$#" ) fips_enabled() { if [ -r /proc/sys/crypto/fips_enabled ]; then cat /proc/sys/crypto/fips_enabled else echo 0 fi } do_rsa1_keygen() { if [ ! -s $RSA1_KEY -a `fips_enabled` -eq 0 ]; then echo -n $"Generating SSH1 RSA host key: " rm -f $RSA1_KEY if test ! -f $RSA1_KEY && $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N '' >&/dev/ null; then chmod 600 $RSA1_KEY chmod 644 $RSA1_KEY.pub if [ -x /sbin/restorecon ]; then /sbin/restorecon $RSA1_KEY.pub fi success $"RSA1 key generation" echo else failure $"RSA1 key generation" echo exit 1 fi fi } do_rsa_keygen() { if [ ! -s $RSA_KEY ]; then echo -n $"Generating SSH2 RSA host key: " rm -f $RSA_KEY if test ! -f $RSA_KEY && $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N '' >&/dev/nul l; then chmod 600 $RSA_KEY chmod 644 $RSA_KEY.pub if [ -x /sbin/restorecon ]; then /sbin/restorecon $RSA_KEY.pub fi success $"RSA key generation" echo else failure $"RSA key generation" echo exit 1 fi fi } do_dsa_keygen() { if [ ! -s $DSA_KEY ]; then echo -n $"Generating SSH2 DSA host key: " rm -f $DSA_KEY if test ! -f $DSA_KEY && $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N '' >&/dev/nul l; then chmod 600 $DSA_KEY chmod 644 $DSA_KEY.pub if [ -x /sbin/restorecon ]; then /sbin/restorecon $DSA_KEY.pub fi success $"DSA key generation" echo else failure $"DSA key generation" echo exit 1 fi fi } do_restart_sanity_check() { $SSHD -t RETVAL=$? if [ $RETVAL -ne 0 ]; then failure $"Configuration file or keys are invalid" echo fi } start() { [ -x $SSHD ] || exit 5 [ -f /etc/ssh/sshd_config ] || exit 6 # Create keys if necessary if [ "x${AUTOCREATE_SERVER_KEYS}" != xNO ]; then do_rsa1_keygen do_rsa_keygen do_dsa_keygen fi echo -n $"Starting $prog: " $SSHD $OPTIONS && success || failure RETVAL=$? [ $RETVAL -eq 0 ] && touch $lockfile echo return $RETVAL } stop() { echo -n $"Stopping $prog: " killproc -p $PID_FILE $SSHD RETVAL=$? # if we are in halt or reboot runlevel kill all running sessions # so the TCP connections are closed cleanly if [ "x$runlevel" = x0 -o "x$runlevel" = x6 ] ; then trap '' TERM killall $prog 2>/dev/null trap TERM fi [ $RETVAL -eq 0 ] && rm -f $lockfile echo } reload() { echo -n $"Reloading $prog: " killproc -p $PID_FILE $SSHD -HUP RETVAL=$? echo } restart() { stop start } force_reload() { restart } rh_status() { status -p $PID_FILE openssh-daemon } rh_status_q() { rh_status >/dev/null 2>&1 } case "$1" in start) rh_status_q && exit 0 start ;; stop) if ! rh_status_q; then rm -f $lockfile exit 0 fi stop ;; restart) restart ;; reload) rh_status_q || exit 7 reload ;; force-reload) force_reload ;; condrestart|try-restart) rh_status_q || exit 0 if [ -f $lockfile ] ; then do_restart_sanity_check if [ $RETVAL -eq 0 ] ; then stop # avoid race sleep 3 start else RETVAL=6 fi fi ;; status) rh_status RETVAL=$? if [ $RETVAL -eq 3 -a -f $lockfile ] ; then RETVAL=2 fi ;; *) echo $"Usage: $0 {start|stop|restart|reload|force-reload|condrestart|try-rest art|status}" RETVAL=2 esac exit $RETVAL
01、sshd_config参数含义
[root@linux ~]# vi /etc/ssh/sshd_config
# 1. 关于 SSH Server 的整体设定,包含使用的 port ,以及使用的密码演算方式
# 先留意一下,在预设的档案内,只要是被注解的设定值(#),即为『预设值!』 #默认注释后面的值就是配置默认值
Port 22
# SSH 预设使用 22 这个port,也可以使用多个port,即重复使用 port 这个设定项目!
# 例如想要开放 sshd 在 22 与 443 ,则多加一行内容为∶
Port 443
Protocol 1,2
# 选择的 SSH 协定版本,可以是 1 也可以是 2 ,
# 如果要同时支持两者,就必须要使用 2,1 这个分隔了(Protocol 1,2)!
# 目前我们会建议您,直接使用 Protocol 2 即可!
#Protocol 2
#ListenAddress 0.0.0.0
ListenAddress 192.168.0.100 #对于多网卡,制定监听IP,默认监听所有
#PidFile /var/run/sshd.pid
# 可以放置 SSHD 这个 PID 的档案!左列为预设值
#LoginGraceTime 2m
# 当使用者连上 SSH server 之后,会出现输入密码的画面,在该画面中,
# 在多久时间内没有成功连上 SSH server ,就断线!若无单位则预设时间为秒!
#Compression yes
# 是否可以使用压缩指令?当然可以
# 2. 说明主机的 Private Key 放置的档案,预设使用下面的档案即可!
#HostKey /etc/ssh/ssh_host_key # SSH version 1 使用的私钥
#HostKey /etc/ssh/ssh_host_rsa_key # SSH version 2 使用的 RSA 私钥
#HostKey /etc/ssh/ssh_host_dsa_key # SSH version 2 使用的 DSA 私钥
#KeyRegenerationInterval 1h
# 由前面连线的说明可以知道, version 1 会使用 server 的 Public Key ,
# 那么如果这个 Public Key 被偷的话,岂不完蛋?所以需要每隔一段时间
# 来重新建立一次!这里的时间为秒!不过我们通常都仅使用 version 2 ,
# 所以这个设定可以被忽略喔!
#ServerKeyBits 768
# 没错!这个就是 Server key 的长度!用预设值即可。# 3. 关于登录档的讯息资料放置与 daemon 的名称!
SyslogFacility AUTHPRIV
# 当有人使用 SSH 登入系统的时候,SSH会记录资讯,这个资讯要记录在什么 daemon name
即是 /var/log/secure 里面!什么?忘记了!
#LogLevel INFO
# 登录记录的等级!嘿嘿!任何讯息!同样的,忘记了就回去参考!
# 4. 安全设定项目!极重要!
PermitRootLogin no # yes 允许root远程登录
# 是否允许 root 登入!预设是允许的,但是建议设定成 no!
#UserLogin no
# 在 SSH 底下本来就不接受 login 这个程序的登入!
#StrictModes yes
# 当使用者的 host key 改变之后,Server 就不接受连线,可以抵挡部分的木马程序!
#RSAAuthentication yes # 是否使用纯的 RSA 认证!?仅针对 version 1 !
#PubkeyAuthentication yes # 是否允许 Public Key ?当然允许!仅针对 version 2
#AuthorizedKeysFile .ssh/authorized_keys #默认公钥存储位置
# 上面这个在设定若要使用不需要密码登入的帐号时,那么那个帐号的存放档案所在档名!
# 这个设定值很重要喔!档名给他记一下!
# 4.2 认证部分
#RhostsAuthentication no
# 本机系统不使用 .rhosts,因为仅使用 .rhosts太不安全了,所以这里一定要设定为 no
#IgnoreRhosts yes
# 是否取消使用 ~/.ssh/.rhosts 来做为认证!当然是!
#RhostsRSAAuthentication no #
# 这个选项是专门给 version 1 用的,使用 rhosts 档案在 /etc/hosts.equiv
# 配合 RSA 演算方式来进行认证!不要使用啊!
#HostbasedAuthentication no
# 这个项目与上面的项目类似,不过是给 version 2 使用的!
#IgnoreUserKnownHosts no
# 是否忽略家目录内的 ~/.ssh/known_hosts 这个档案所记录的主机内容?
# 当然不要忽略,所以这里就是 no !
PasswordAuthentication yes
# 密码验证当然是需要的!所以这里写 yes !
#PermitEmptyPasswords no
# 若上面那一项如果设定为 yes 的话,这一项就最好设定为 no ,
# 这个项目在是否允许以空的密码登入!当然不许!
ChallengeResponseAuthentication no
# 允许任何的密码认证!所以,任何 login.conf 规定的认证方式,均可适用!
# 但目前我们比较喜欢使用 PAM 模组帮忙管理认证,因此这个选项可以设定为 no 喔!
UsePAM yes
# 利用 PAM 管理使用者认证有很多好处,可以记录与管理。
# 所以这里我们建议您使用 UsePAM 且 ChallengeResponseAuthentication 设定为 no
# 4.3 与 Kerberos 有关的参数设定!因为我们没有 Kerberos 主机,所以底下不用设定!
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosTgtPassing no
# 4.4 底下是有关在 X-Window 底下使用的相关设定!
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
# 4.5 登入后的项目∶
PrintMotd yes #
# 登入后是否显示出一些资讯呢?例如上次登入的时间、地点等等,预设是 yes
# 亦即是列印出 /etc/motd #登录进去提示的信息
PrintLastLog yes
# 显示上次登入的资讯!可以啊!预设也是 yes !
KeepAlive yes
# 一般而言,如果设定这项目的话,那么 SSH Server 会传送KeepAlive 的讯息给
# Client端,以确保两者的连线正常!在这个情况下,任何一端死掉后,SSH可以立刻知道!
# 而不会有僵尸程序的发生!
UsePrivilegeSeparation yes
# 使用者的权限设定项目!就设定为 yes 吧!
MaxStartups 10
# 同时允许几个尚未登入的连线画面?当我们连上 SSH ,但是尚未输入密码时,
# 这个时候就是我们所谓的连线画面!在这个连线画面中,为了保护主机,
# 所以需要设定最大值,预设最多十个连线画面,而已经建立连线的不计算在这十个当中
# 4.6 关于使用者抵挡的设定项目∶
DenyUsers *
# 设定受抵挡的使用者名称,如果是全部的使用者,那就是全部挡吧!
# 若是部分使用者,可以将该帐号填入!例如下列!
DenyUsers test #禁止登录用户、用户组
DenyGroups test
# 与 DenyUsers 相同!仅抵挡几个群组而已!
# 5. 关于 SFTP 服务的设定项目!
Subsystem sftp /usr/lib/ssh/sftp-server #sftp登录默认都是开启
02、key生成
[test2@test2 ~]$ ssh-keygen -t rsa <==这个步骤在产生 Key pair # -t dsa 默认rsa加密
Generating public/private rsa key pair.
Enter file in which to save the key (/home/test2/.ssh/id_rsa): <==这里按下Enter
Enter passphrase (empty for no passphrase): <==这里按 Enter #秘钥加密的密码
Enter same passphrase again: <==再按一次 Enter
Your identification has been saved in /home/test2/.ssh/id_rsa. <==这是私钥
Your public key has been saved in /home/test2/.ssh/id_rsa.pub. <==这是公钥
The key fingerprint is:
c4:ae:d9:02:d1:ba:06:5d:07:e6:92:e6:6a:c8:14:ba test2@test2.linux.org
# 注意∶ -t 指的是『使用何种密码演算方式?』由于我们使用 RSA ,
# 所以直接输入 -t rsa 即可建立两支 Keys !
# 此外,建立的两把 Keys 都放置在家目录下的 .ssh 这个目录中!
# 察看一下这两把 Keys 吧!
[test2@test2 ~]$ ll ~/.ssh
total 12
-rw------- 1 test2 test2 887 Nov 12 22:36 id_rsa
-rw-r--r-- 1 test2 test2 233 Nov 12 22:36 id_rsa.pub
-rw-r--r-- 1 test2 test2 222 Oct 31 11:20 known_hosts
1. 先在 Client 端以 sftp 将公钥丢到 test 上面去!
[test2@test2 ~]$ cd ~/.ssh
[test2@test2 .ssh]$ scp id_rsa.pub test@192.168.0.2:~/
test@192.168.0.2's password:
id_rsa.pub 100% 233 0.2KB/s 00:00
2. 到 Server 上面,将公钥转存到 authorized_keys 档案中!
[test@linux ~]$ cd ~/.ssh
[test@linux .ssh]$ cat ../id_rsa.pub >> authorized_keys
请注意上面的机器!由于 authorized_keys 可以保存相当多的公钥内容,因此, 可以使用 >> 的方式来将 Client 端的公钥新增到该档案内!!做完这一步一后,未来 test2 就可以直接在 test2sweet.com以
注意:假定远程主机没有authorized_keys,亦可以使用 ssh-copy-id -i ~/.ssh/xx.pub user@ip 自动生成authorized_keys
[test2@test2 ~]$ ssh test@linuxsweet.com
• Client 必须制作出 Public & Private 这两把 keys,且 Private 需放到 ~/.ssh/ 内;
• Server 必须要有 Public Key ,且放置到使用者家目录下的 ~/.ssh/authorized_keys;
未来,当您还想要登入其他的主机时,只要将您的 public key (就是 id_rsa.pub 这个档案) 给他 copy 到其他主机上面去,并且新增到某帐号的 ~/.ssh/authorized_keys 这个档案中!哈哈!成功
安全设定∶
老实说,大家都被『SSH 是个安全的服务』所欺骗了!其实 sshd 并不怎么安全的!翻开 openssh 的过去历史来看,确实有很多人是利用 ssh 的程序漏洞来取得远端主机 root 的权限,进一步黑掉对方的主机! #openssh的漏洞是致命的,多关注最新的安全动态
分别可以由∶
• /etc/ssh/sshd_config
• /etc/hosts.allow, /etc/hosts.deny
• iptables
• /etc/ssh/sshd_config
一般而言,这个档案的预设项目就已经很完备了!所以,事实上是不太需要更动他的! 但是,如果您有些使用者方面的顾虑,那么可以这样修正一些问题呢!
o 禁止 root 的登入∶
任何时候,不许 root 以远端连线的方式登入,都会是一个好主意!所以这里蛮建议大家直接将 root 的登入权限拿掉吧!所以,可以修改 /etc/ssh/sshd_config 这个档案的内容为∶
[root@linux ~]# vi /etc/ssh/sshd_config
PermitRootLogin no <== 将他改成 no 吧!
[root@linux ~]# /etc/init.d/sshd restart
o 不许某个群组登入∶
有些特殊情况中,我们想要让使用者只能使用 sendmail, pop3, ftp 等,但是不希望他可以远端连线进来,那么您可以这样做∶
1. 将这些使用者都归纳在某一个特殊群组之下,例如 nossh 这个群组好了;
2. 在 /etc/ssh/sshd_config 当中加入这一行∶『 DenyGroups nossh 』
3. 重新启动 sshd ∶ /etc/init.d/sshd restart
这样就OK!
o 不许某个使用者登入∶
跟 DenyGroups 类似,使用 DenyUsers 即可!参考 sshd_config 的设定喔!
• /etc/hosts.allow 及 /etc/hosts.deny
简单的方法就是∶
[root@linux ~]# vi /etc/hosts.allow
sshd: 192.168.0.1, 192.168.0.2, 192.168.0.3, 192.168.0.4, 192.168.0.5: allow
[root@linux ~]# vi /etc/hosts.deny
sshd : ALL : spawn (/bin/echo Security notice from host `/bin/hostname`; \
/bin/echo; /usr/sbin/safe_finger @%h ) | \
/bin/mail -s "%d -%h security" root@localhost & \
: twist ( /bin/echo -e "\n\nWARNING connectin not allowed.". )