ssh使用指南(转)

【我的前言】最近在分析一个web上传文件失败的问题,虽然最后找到的原因是配置文件错了,但是这个问题也引起我对SSH的小兴趣,看到一个很好的帖子,就转过来学习一下。
mail:win2linux#163.com  转载请著名出处,并保留原作者

SSH全称Secure SHell,顾名思义就是非常安全的shell的意思,SSH协议是IETF(Internet Engineering Task Force)的Network Working Group所制定的一种协议。SSH的主要目的是用来取代传统的telnet和R系列命令(rlogin,rsh,rexec等)远程登陆和远程执行命令的工具,实现对远程登陆和远程执行命令加密。防止由于网络监听而出现的密码泄漏,对系统构成威胁。

ssh协议目前有SSH1和SSH2,SSH2协议兼容SSH1。目前实现SSH1和SSH2协议的主要软件有OpenSSH和SSH Communications Security Corporation 公司的SSH Communications 软件。前者是OpenBSD组织开发的一款免费的SSH软件,后者是商业软件,因此在linux、FreeBSD、OpenBSD、NetBSD等免费类UNIX系统种,通畅都使用OpenSSH作为SSH协议的实现软件。因此,本文重点介绍一下OpenSSH的使用。需要注意的是OpenSSH和SSH Communications的登陆公钥/私钥的格式是不同的,如果想用SSH Communications产生的私钥/公钥对来登入到使用OpenSSH的linux系统需要对公钥/私钥进行格式转换。

在出现SSH之前,系统管理员需要登入远程服务器执行系统管理任务时,都是用telnet来实现的,telnet协议采用明文密码传送,在传送过程中对数据也不加密,很容易被不怀好意的人在网络上监听到密码。同样,在SSH工具出现之前R系列命令也很流行(由于这些命令都以字母r开头,故把这些命令合称为R系列命令R是remote的意思),比如rexec是用来执行远程服务器上的命令的,和telnet的区别是telnet需要先登陆远程服务器再实行相关的命令,而R系列命令可以把登陆和执行命令并登出系统的操作整合在一起。这样就不需要为在远程服务器上执行一个命令而特地登陆服务器了。

SSH出现后R系列命令已经基本废止了,如果你从来都不知道UNIX历史上有过这些命令,那最好了,如果你知道那么彻底忘记他们吧。telnet命令除了在路由器等网络设备中还使用外,在正式的生产系统中也基本废止不用了,目前telnet最大的用处是用来检测某个网络端口是否正常打开并提供服务,比如我经常用telnet 10.0.0.1 25来检查我的邮件服务器是否正常。

SSH是一种加密协议,不仅在登陆过程中对密码进行加密传送,而且对登陆后执行的命令的数据也进行加密,这样即使别人在网络上监听并截获了你的数据包,他也看不到其中的内容。OpenSSH已经是目前大多数linux和BSD操作系统(甚至cygwin)的标准组件,因此关于如何安装OpenSSH本文就不再叙述了,如果不出意外,你的系统上必定已经安装好了OpenSSH。

OpenSSH软件包包含以下命令:
sshd      ―― SSH服务端程序
sftp-server  ―― SFTP服务端程序(类似FTP但提供数据加密的一种协议)
scp     ―― 非交互式sftp-server的客户端,用来向服务器上传/下载文件
sftp     ―― 交互式sftp-server客户端,用法和ftp命令一样。
slogin    ―― ssh的别名
ssh     ―― SSH协议的客户端程序,用来登入远程系统或远程执行命令
ssh-add   ―― SSH代理相关程序,用来向SSH代理添加dsa key
ssh-agent     ―― ssh代理程序
ssh-keyscan  ―― ssh public key 生成器

SSH最常用的使用方式是代替telnet进行远程登陆。不同于telnet的密码登陆,SSH还同时支持Publickey、Keybord Interactive、GSSAPI等多种登入方式,不像telnet那样只有输入系统密码一种途径。目前最常用的登陆方式还是传统的Password方式和Publickey方式登陆。下面以Redhat AS4为例,举例说明这两种登陆方式的用法。

1,采用传统的password方式登陆
如果想用传统的password方式登陆系统你的OpenSSH配置文件中必须有如下配置指令:

[Copy to clipboard] [ - ]
CODE:
PasswordAuthentication yes

在Redhat系统中sshd的配置文件是/etc/ssh/sshd_config,默认安装的OpenSSH默认是允许使用password方式登陆系统的。

用ssh 客户端登陆系统,首次登陆一个之前没有登陆过的系统,ssh会询问你是否发送加密指纹并且链接服务器。
第一次登陆:

QUOTE:
[root@mail ~]# ssh 172.18.6.227
The authenticity of host '172.18.6.227 (172.18.6.227)' can't be established.
RSA key fingerprint is 43:80:f2:e1:9b:b6:6e:c0:e2:dd:57:8f:ed:89:b3:81.
Are you sure you want to continue connecting (yes/no)?

回答yes ssh提示输入密码:

QUOTE:
[root@mail ~]# ssh 172.18.6.227
The authenticity of host '172.18.6.227 (172.18.6.227)' can't be established.
RSA key fingerprint is 43:80:f2:e1:9b:b6:6e:c0:e2:dd:57:8f:ed:89:b3:81.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.18.6.227' (RSA) to the list of known hosts.
[email protected]'s password:

如果密码输入正确,那么就顺利登陆到了远程系统,出现远程系统提示符:

QUOTE:
[root@mail ~]# ssh 172.18.6.227
The authenticity of host '172.18.6.227 (172.18.6.227)' can't be established.
RSA key fingerprint is 43:80:f2:e1:9b:b6:6e:c0:e2:dd:57:8f:ed:89:b3:81.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.18.6.227' (RSA) to the list of known hosts.
[email protected]'s password:
Last login: Thu Jul 12 18:47:47 2007 from 172.18.6.130
[root@qmail ~]#

第一次登陆后,ssh就会把登陆的ssh指纹存放在用户home目录的.ssh目录的know_hosts文件中,如果远程系统重装过系统,ssh指纹已经改变,你需要把 .ssh 目录下的know_hosts中的相应指纹删除,再登陆回答yes,方可登陆。请注意.ssh目录是开头是”.”的隐藏目录,需要ls –a参数才能看到。而且这个目录的权限必须是700,并且用户的home目录也不能给其他用户写权限,否则ssh服务器会拒绝登陆。如果发生不能登陆的问题,请察看服务器上的日志文件/var/log/secure。通常能很快找到不能登陆的原因。

远程系统的登陆用户名和当前登陆的本地用户相同,如果想以普通用户user的身份登陆远程系统可以这样:

[Copy to clipboard] [ - ]
CODE:
[root@mail ~]# ssh [email][email protected][/email]   

或者这样:

[Copy to clipboard] [ - ]
CODE:
[root@mail ~]# ssh -l user 172.18.6.227 

ssh命令还有很多非常有用的参数,具体请看man手册。

ssh最有用的功能是远程执行命令:

QUOTE:
[root@mail ~]# ssh 172.18.6.227 ls -l /
[email protected]'s password:
total 1244
drwxr-xr-x    2 root root    4096 Jun 26 04:02 bin
drwxr-xr-x    4 root root    4096 Mar 29 11:17 boot
drwxr-xr-x    2 root root    4096 Jan 25 11:26 command
drwxr-xr-x   15 root root    4096 Jun 12 20:09 data
drwxr-xr-x    9 root root    5360 Jul  2 13:38 dev
drwxr-xr-x   87 root root   12288 Jul 11 04:02 etc
drwxr-xr-x   20 root root    4096 Apr 10 10:54 home
drwxr-xr-x    2 root root    4096 Aug 13  2004 initrd

输入正确的密码后,ssh会链接远程服务器的sshd服务器程序,然后执行远程服务器上的
ls –l /命令 ,并把输入结果传到本地服务器。相当于你先登陆到远程服务器,然后再实行命令ls –l /,最后再登出服务器。需要提醒的是,如果你需要登陆服务器并执行不止一个命令,必须要把命令用单引号或双引号引起来:

[Copy to clipboard] [ - ]
CODE:
ssh 172.18.6.227 "cd /root && ls "

如果不用引号引起来:

[Copy to clipboard] [ - ]
CODE:
ssh 172.18.6.227 cd /root && ls

那么其实第二个命令ls执行的是本地服务器的ls,而并非远程服务器上执行的ls,输出结果也是本地的内容。

ssh的远程实行命令的功能是用来代替原始的R系列命令的,在ssh出现之前系统管理员们不得不用rexec, rsh等不安全的远程执行命令工具来完成同样的操作。这个功能在管理大批机器的时候是非常有用的,比如我要重启10.0.0.0/24网段内所有的服务器,只要输入一条命令:

[Copy to clipboard] [ - ]
CODE:
for i in $(seq 1 254) ; do  ssh 10.0.0.${i} reboot ; done

就可以完成重启所有服务器的操作,也许你会说,这要虽然不需要再登陆每一台服务器了,但是还是要每次输入密码,多麻烦啊。别急,下面要讲的用ssh public key方式登陆就是要解决问题。

2,采用public key登陆远程服务器:

首先来对password方式和public方式登陆服务器的不同做一个对比:比如你要进入一个秘密基地,以password方式登陆,就好比这个秘密基地采用口令的方式让外来人员进入,哨兵只关心外来人员提供的口令是否正确,如果正确就放行。public key方式就好比用钥匙和锁的方式进入基地,只要外来人员有这个基地大门门锁的钥匙,并且钥匙确实能开这把锁,那么哨兵就将这个人放行。哨兵只认钥匙,不人口令和人员。口令的缺点是,你的口令可能被敌人窃听去,敌人会冒充友军进入秘密基地,因为哨兵只凭口令来决定是否放行外来人员。而用钥匙的方式则敌人必须得到一把一模一样的钥匙在能登入。

采用ssh的public key方式登陆系统,需要先用相关的工具生成一个公钥/私钥对,公钥和私钥的就好比锁和钥匙的关系。公钥就是锁,锁是公开挂在大门上的,是一个对外可见的东西,任何有钥匙的人都可以去开锁,私钥就是钥匙,钥匙要自己妥善保管好,不能让别人偷去。否则别人拿到了钥匙并知道你锁的位置(IP地址)就可以轻易的进入基地了。

openssh的ssh-keygen命令用来产生这样的私钥和公钥。

[root@mail ~]# ssh-keygen -b 1024 -t dsa -C [email protected]
Generating public/private dsa key pair.
Enter file in which to save the key (/root/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_dsa.
Your public key has been saved in /root/.ssh/id_dsa.pub.
The key fingerprint is:
71:e5:cb:15:d3:8c:05:ed:05:84:85:32:ce:b1:31:ce [email protected]

说明:
-b 1024 采用长度为1024字节的公钥/私钥对,最长4096字节,一般1024或2048就可以了,太长的话加密解密需要的时间也长。
-t dsa  采用dsa加密方式的公钥/私钥对,除了dsa还有rsa方式,rsa方式最短不能小于768字节长度。
-C [email protected] 对这个公钥/私钥对的一个注释和说明,一般用所有人的邮件代替。可以省略不写,更多其他参数请man ssh-keygen。

QUOTE:
[root@mail ~]# ssh-keygen -b 1024 -t dsa -C [email protected]
Generating public/private dsa key pair.
#提示正在生成,如果选择4096长度,可能需要较长时间
Enter file in which to save the key (/root/.ssh/id_dsa):
#询问把公钥和私钥放在那里,回车用默认位置即可
Enter passphrase (empty for no passphrase):
#询问输入私钥密语,为了实现自动登陆,应该不要密语,直接回车
Enter same passphrase again:
#再次提示输入密语,再次直接回车
Your identification has been saved in /root/.ssh/id_dsa.
Your public key has been saved in /root/.ssh/id_dsa.pub.
#提示公钥和私钥已经存放在/root/.ssh/目录下
The key fingerprint is:
71:e5:cb:15:d3:8c:05:ed:05:84:85:32:ce:b1:31:ce [email protected]
#提示key的指纹

需要特别说明的是私钥密语,我之所以用“密语”这个词来描述,而避开“密码”这个词,是为了区分密码登陆方式中使用的密码。在密码登陆方式中使用的密码是远程服务器操作系统的密码,而这里的“密语”是私钥的密码。设想你的钥匙是非常智能的高科技产品,你在用钥匙开锁的时候还必须向钥匙中输入一个密码,钥匙才能开锁。这样的话,即便你的钥匙被人偷去了,偷钥匙的人不知道钥匙中的密码他也不能用这个钥匙开锁。一般情况下,假如你管理100台服务器,为了在这100台服务器之间不用密码就能自由穿梭,你需要生成一个不带“密语”的钥匙。你可以在这100台服务器中选择一台服务器作为外界登陆到这群服务的入口,这个从外界登陆到这台入口服务器的钥匙就应该要加上一个“密语”。而服务器群之间的公钥/私钥对就不要加“密语”。

QUOTE:
[root@mail ~]# ls -l /root/.ssh
total 16
-rw-------  1 root root 668 Jul 12 20:07 id_dsa
-rw-r--r--  1 root root 611 Jul 12 20:07 id_dsa.pub
-rw-r--r--  1 root root 222 Jul 12 19:37 known_hosts

产生的公钥/私钥文件在用户home目录的.ssh目录下,其中id_dsa.pub是公钥,把产生的公钥上传到需要登陆的服务器的对应用户目录的home目录的.ssh目录下,再一次强调用户自己的目录(home目录)必须不能有其他人可写的权限,.ssh目录的权限必须是700,即除了用户自己,其他人没有任何读写察看该目录的权限,否则ssh服务器会拒绝登陆。ssh默认的公钥文件是用户home目录下的.ssh目录下的authorized_keys文件,因此需要把产生的公钥以这个文件名放到服务器的/root/.ssh/目录下,这个文件中可以存放多个客户端的公钥文件,就好比一个大门上可以上很多锁,可以有不同的钥匙来尝试开锁,只要有一个锁被打开了,门就可以打开了。放到服务器上应该是这样子的:

QUOTE:
-rw-r--r--  1 root root  611 Jul 12 20:04 authorized_keys
-rw-r--r--  1 root root 1046 Apr 28 09:36 known_hosts

公钥和know_hosts文件可以有其他人可度的权限,因为是“公钥”嘛,本来就可以公开的。但是实际上这个文件别人还是读不到的,因为目录.ssh是别人没有权限进去的。

而在客户端的/root/.ssh/目录下,私钥应该是这个样子的:

[Copy to clipboard] [ - ]
CODE:
-rw-------  1 root root 668 Jul 12 20:07 id_dsa

私钥必须是600权限,否则ssh服务器会拒绝用户登陆。

这样,你在ssh客户端那里就可以直接登陆到ssh服务端了,当然,如果是第一次登陆,那么还是会提示yes/no 询问是否将ssh指纹存入known_hosts中。存入后,就标明ssh已经“认识”那台服务器了,以后就可以直接登陆了。
当然,采用ssh key方式登陆还需要sshd配置文件中配置支持才行:
vi /etc/ssh/sshd_config

[Copy to clipboard] [ - ]
CODE:
PubkeyAuthentication yes

一般默认安装的OpenSSH都默认开启了key方式登陆的选项。现在可以直接登陆了:

QUOTE:
[root@mail ~]# ssh 172.18.6.227
Last login: Thu Jul 12 20:04:21 2007 from notebook.a
[root@qmail ~]#

还可以自由的在远程服务器上执行命令:
如察看远程服务器的磁盘使用情况:

QUOTE:
[root@mail ~]# ssh 172.18.6.227 df -h   
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1             966M  365M  552M  40% /
/dev/sda3             9.4G  7.1G  1.9G  80% /data
none                  506M     0  506M   0% /dev/shm
/dev/sda2             9.4G  3.0G  6.0G  34% /usr
/dev/sda6              12G  2.6G  8.8G  23% /var

ssh再也不会向你问询对方服务器的密码,世界显示执行结果,因为 ssh会自动取/root/.ssh/id_dsa这个“钥匙”去开服务器上的/root/.ssh/authorized_keys这把“锁”。开通了就直接登陆上去了或者直接执行命令并返回结果了,不管该用户在远程系统上的系统密码到底是多少,服务器只关心钥匙能不能开自己的锁,而不关心用户密码是多少。

如果你要这两台机器互访,那么把产生的公钥和私钥在服务器和客户端上各放一份就可以了。同样如果你要100台服务器这样直接互访,那么只要把authorized_keys和id_dsa在这100台服务器上各自放一份就可以了。第一传这些比较麻烦,但是传完之后,以后就太方便了。比如我要看这100台服务器的内存使用情况,我只要输入命令:

QUOTE:
[root@DISK_253_11 root]# for i in `seq 1 100` ;do ssh 10.60.8.${i} free -m; done
             total       used       free     shared    buffers     cached
Mem:          1006        578        427          0         57        173
-/+ buffers/cache:        347        658
Swap:          509         18        491
             total       used       free     shared    buffers     cached
Mem:          1006        559        446          0         59        127
-/+ buffers/cache:        372        633
Swap:          509          0        509
             total       used       free     shared    buffers     cached
Mem:          1006        556        449          0         58        127
-/+ buffers/cache:        370        635
Swap:          509          0        509
……

ssh把远程执行的结果显示到当前客户机的屏幕上,再也不用一台一台登陆然后执行了。连密码都不用输入。

再比如我要重启所有服务器,只要简单的输入:

[Copy to clipboard] [ - ]
CODE:
for i in `seq 1 100`; do ssh 10.60.0.${i} reboot ;done

敲下回车后,你只要喝点咖啡,等着这100台服务器重启完毕就可以了。

过5分钟,看看是否所有服务器重启完了:

[Copy to clipboard] [ - ]
CODE:
for i in `seq 1 100`; do ssh 10.60.0.${i} uptime; done

再比如一次性修改所有服务器上的一个配置文件,并使其生效:

[Copy to clipboard] [ - ]
CODE:
for i in `seq 1 100`;do ssh 10.60.0.${i} “echo /usr/local/mysql/lib > /etc/ld.so.conf && ldconfig”

[quote][/quote]

现在看到ssh的远程执行命令功能的强大了吧,如果你有一点shell基础,编写出更复杂的shell,用scp统一拷贝到远程服务器上,再远程执行,那么一下子可以自动完成N多任务。即便是管理1000台服务器,也会和管理10台服务器一样轻松。

3.scp命令的使用:
scp是OpenSSH软件包中一个用来向服务器拷贝文件或者下载文件的命令。需要使得服务器支持scp你的sshd配置文件中必须有如下指令,一般默认安装都打开了这个功能。

[Copy to clipboard] [ - ]
CODE:
Subsystem       sftp    /usr/libexec/openssh/sftp-server

sftp是ssh协议中的一个子协议,也用22号端口。

sftp-server就是这个子协议的服务器端程序,scp和sftp是客户端程序。sftp不讲了,反正用法和ftp命令一样,会用ftp命令的就一定会用sftp。

scp是非交互式命令,可以直接在服务器之间拷贝文件。它和ssh程序一样,会自动取/root/.ssh/id_dsa这把“钥匙”去开服务器上的“锁”,开好锁服务器就允许你自由的上传下载文件了:
比如:

[Copy to clipboard] [ - ]
CODE:
[root@mail ~]# scp install.log 172.18.6.227:/root/

表示把本地文件install.log拷贝到服务器172.18.6.227的/root目录下。同样,由于采用了public key方式登陆,scp也不会向你问询密码,直接执行成功。在服务器间拷贝文件就和在本机上拷贝文件那么简单。

如果要拷贝整个目录,可以用-r参数,而不必先tar包再拷贝:

[Copy to clipboard] [ - ]
CODE:
scp -r /root/test 172.18.6.227:/root/   

如果要拷贝过程中保持文件权限和用户组不变就用-p参数,更多scp参数请看man scp

[Copy to clipboard] [ - ]
CODE:
[root@mail ~]# scp -rp /root/test 172.18.6.227:/root/  

现在同样假设你有100台服务器要拷贝相同的文件上去,那么非常的轻松:

[Copy to clipboard] [ - ]
CODE:
for i in `seq 1 100`; scp –rp  myfile.dat 10.60.0.${i}:/some/path ; done

敲下回车,接下来你只要喝点咖啡等待命令执行完成。

再比如,你要让100台服务器的某个配置文件都相同,那么可以这样:

[Copy to clipboard] [ - ]
CODE:
for i in `seq 1 100`; scp –rp  /etc/hosts 10.60.0.${i}:/etc/ ; done

敲下命令后几秒钟,所有服务器的/etc/host文件和当前服务器相同了。


需要注意的是,如果你发现ssh登陆或者远程执行命令很慢,比如ssh 10.0.0.1需要等待十多秒时间,那么多半是你的dns有问题,要么删除/etc/resolv.conf文件中的内容,要么正确配置DNS,并且能让你的主机IP能在DNS服务器中找到,还有方法就是关闭SSH的DNS反解功能。

以上所讲的只是ssh浩瀚的功能的冰山一角,还有很多更高级的功能,如ssh代理等等,ssh和scp的更多有用参数等,各位就自己去研究吧。我这里只抛砖引玉,希望更多人知道ssh并不是代替telnet,并不只能每次输入密码登陆。ssh+scp+publickey认证,可以让你实现轻松管理数百台UNIX服务器的目的。使得管理1000台服务器和管理10台服务器一样简单。这就是我写这个文档的目的所在。

你可能感兴趣的:(加密,redhat,shell,ssh,服务器,DNS服务器)