目录
- ssh
- ssh是什么
- ssh安装
- 使用ssh登录远程主机
- 退出登录
- 使用ssh执行单条指令
- 密钥验证
- 详细操作
- scp
- rsync
- sftp
- 进阶
ssh
ssh是什么
ssh (Secure SHell)
简单说,ssh是一种网络协议,用于计算机之间的加密登录。你可以通过 ssh 服务远程访问其他安装有 ssh 服务的主机,也可以向/从远程主机复制文件。ssh 服务包括 ssh,scp,sftp,rsync。
如果一个用户从本地计算机,使用ssh协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会泄露。
以下实验均以客户端:MacOS Sierra 和服务端 :Ubuntu 为组合, 如果你没有两台主机供实验,远程主机的地址可以使用 localhost 替代
ssh安装
大部分 linux 发行版都只默认包含ssh 客户端(即只能作为客户端连接其他主机,而不能被其他主机远程访问),要想让你的 linux 供他人远程访问,还必须安装 ssh 服务器端软件(openssh-server),Ubuntu 通过如下指令安装:
apt-get install openssh-server
安装完成后,我们的服务器主机就具备了被远程访问的能力了
使用ssh登录远程主机
在本地主机终端输入ssh username@addr
连接远程主机。其中 username 为远程主机中存在的用户名,addr 为远程主机的 ip 地址。如ssh gustplus@192.168.1.10
就是以gustplus 账号登录地址为192.168.1.10的主机。
如果是第一次登录该主机,你会收到类似如下信息:
The authenticity of host ‘192.168.1.10 (192.168.1.10)’ can’t be established.
RSA key fingerprint is a4:28:03:85:89:6d:08:fa:99:15:ed:fb:b0:67:55:89.
Are you sure you want to continue connecting (yes/no)?yes
当输入 yes 后会显示如下信息:
Warning: Permanently added ‘192.168.1.10’ (RSA) to the list of known hosts.
此时,你已接收到了服务器端发给你的公钥(public key),并存储在你的~/.ssh/known_hosts文件中。这行为保证了你与服务器端的通信经过了RSA加密。
此时, 客户端主机的~/.ssh/known_hosts的内容如下
192.168.1.10 ssh-rsa XXXXXX3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
此时,客户端主机已经与远程主机建立的加密的安全连接,你可以像在本地终端一样操作远程主机了
退出登录
你可以通过 exit
指令来退出登录
使用ssh执行单条指令
你可以如下指令使用 ssh 执行一条指令:
$ ssh gustplus@192.168.1.10 hostname
johndoe@10.140.67.23's password: **********
friday
比如上条指令在192.168.1.10上执行了 hostname
指令
如果你需要执行的指令包含选项或参数,最好将整条指令用双引号(“”)包裹
$ ssh gustplus@192.168.1.10 "cat myfile"
不然像”~/”这样具有特殊含义的指示符会被提前展开,如下面这条例子:
shizhandeMacBook-Pro:~ shizhan$ ssh gustplus@192.168.1.10 ls ~/
ls: cannot access '/Users/shizhan/': No such file or directory
这里的~/被提前展开为 ‘/Users/shizhan/’而不是期望的‘/home/gustplus’。使用双引号的效果如下:
shizhandeMacBook-Pro:~ shizhan$ ssh shizhan@192.168.1.10 "ls ~/"
Desktop
Documents
Downloads
examples.desktop
Music
Pictures
Public
shell.sh
sub_shell.sh
Templates
Videos
同时需要注意的是,如果你的指令中含有相对路径,这条相对路径是相对于用户的home目录而言的,比如上例中的’~/’指代的是 gustplus 的 home 目录/home/gustplus
密钥验证
如果你频繁的使用 ssh工具与远程主机交互,你就会发现每次都要输入密码是一件多么糟心的事,所以除了密码验证,ssh 还提供了密钥验证。下面是它的工作原理:
- 首先由你在本地主机上创建一对公钥和私钥
- 私钥由本地主机自行保管,公钥上传到需要登录的远程主机
- 在上传的公钥放置到合适位置之后,之后的 ssh 连接会直接将远程主机的公钥与本地主机的私钥进行匹配,而无需在输入密码
详细操作
- 本地主机通过
ssh-keygen -t rsa -P ''
生成公私钥对。
其中-P表示密码,-P ” 就表示空密码,也可以不用-P参数,这样就要三车回车,用-P就一次回车。
-t表示密钥的加密类型,可以选择的加密类型有:dsa, ecdsa, ed25519, rsa, rsa1
指令会在/home/$(user_name)目录下生成.ssh/目录,并在.ssh目录下生成id_rsa和id_rsa.pub两份公钥和私钥文件 - 执行 ssh-copy-id,将生成的公钥文件上传至远程主机
$ ssh-copy-id -i ~/.ssh/id_rsa.pub gustplus@192.168.1.10
其中 ssh-copy-id的说明如下:
ssh-copy-id [-f] [-n] [-i [公钥文件路径]] [-p 端口号] [-o ssh 选项] [user@]hostname
此操作会将本地主机的公钥的内容添加到远程主机指定用户home 路径下的.ssh/authorized_keys文件中
当然这些操作也可以通过手动完成
scp ~/.ssh/id_rsa.pub gustplus@192.168.1.10:./ #将 id_rsa.pub 文件拷贝到远程主机的 home 目录下
ssh gustplus@192.168.1.10 "touch ~/.ssh/authorized_keys;\
cat ~/id_rsa.pub >> ~/.ssh/authorized_keys;\
chmod 644 ~/.ssh/authorized_keys" #将 id_rsa.pub 的内容添加到~/.ssh/authorized_keys文件中,并修改该文件的权限,别忘了双引号噢!
- 接下来在通过 ssh 登录远程主机试试,是不是不需要密码了?当然使用到 ssh 服务的所有操作(ssh, scp, rsync…)都将不需要输入密码了!
scp
在客户端和服务器之间传输文件
scp 的传输也是经过加密的
scp from to
from和to 分别为服务器或客户端路径路径中的一个,其中服务器的路径格式为user_name@$ip_addr: $path。如下面的例子,是将本地/Users/shizhan/memo
的文件拷贝到服务器的/tmp路径下
$ scp /Users/shizhan/memo gustplus@192.168.1.10:/tmp
shizhan@192.168.1.10's
memo 100%|****************| 153 0:00
和cp
指令一样,你可以使用-r 选项拷贝一整个目录
$ scp -r /etc/ shizhan@192.168.1.10:etc/
afpovertcp.cfg 100% 515 153.1KB/s 00:00
afpovertcp.cfg~orig 100% 515 96.5KB/s 00:00
aliases 100% 9970 1.3MB/s 00:00
......
你可能会想到,可以利用scp
来进行数据的备份,但不幸的是,scp
本身有些属性注定了它并不适合备份:
- 属性丢失。权限或者时间属性和 原始文件不一样。这是备份所不希望看到的
下面是使用scp 拷贝文件后的对比:
#原始文件
-rw-rw-rw- 1 shizhan staff 398 5 31 2015 id_rsa.pub
#复制
scp ~/Documents/id_rsa.pub gustplus@192.168.1.10:./
#复制后的文件
ssh gustplus@192.168.1.10 "ls -al id_rsa.pub"
-rw-rw-r-- 1 shizhan shizhan 398 8月 5 11:59 id_rsa.pub
可见,复制后,文件的权限(权限会由远程用户的umask 限制)和日期属性都发生了改变
- 软链接丢失。如果拷贝过程中遇到软链接,
scp
将会拷贝链接指向的文件/目录而不是链接本身 - 拷贝了重复的文件。如果执行两次相同的拷贝操作且被拷贝的文件没有改动,拷贝行为仍会执行,浪费
那么,有没有适合备份的指令呐?当然有!
rsync
使用rsync就可以避免scp
在备份文件时的这些问题
通过-avl 选项(-a (recursive archive), -v (verbose), and -l (copy symbolic links))可以实现文件的备份而没有以上的问题(但文件的 user:group 还是会变成登录用户的 user:group)
当重复备份相同的文件时,rsync
命令会忽略没有修改的文件
#第一次备份
shizhandeMacBook-Pro:~ shizhan$ rsync -avl rsync_test gustplus@192.168.1.10:
building file list ... done
rsync_test/
rsync_test/test.txt
sent 151 bytes received 48 bytes 79.60 bytes/sec
total size is 0 speedup is 0.00
#第二次备份
shizhandeMacBook-Pro:~ shizhan$ rsync -avl rsync_test gustplus@192.168.1.10:
building file list ... done
sent 103 bytes received 20 bytes 35.14 bytes/sec
total size is 0 speedup is 0.00
我们可以发现,第二次备份并没有复制文件,正是因为rsync
忽略了没有修改的文件
使用-avl 选项是备份的好方法,但如果想要两台机器上的两个目录完全相同,还需要其他操作,看下面的例子:
#创建测试文件夹及文件
$ mkdir scp_test
$ touch scp_test/scp_test.txt
#备份文件夹到远程主机
$ rsync -avl scp_test gustplus@192.168.1.10:
#删除本地文件
$ rm scp_test/*
#再次备份文件夹到远程主机
$ rsync -avl scp_test gustplus@192.168.1.10:
这时候我们查看远程主机里的scp_test
文件夹,会发现本地已删除的文件仍然存在
$ ll scp_test/
total 8
drwxr-xr-x 2 gustplus gustplus 4096 8月 5 15:58 ./
drwxr-xr-x 18 gustplus gustplus 4096 8月 5 15:57 ../
-rw-r--r-- 1 gustplus gustplus 0 8月 5 15:55 scp_test.txt
如果你想备份所有的历史文件以防止被备份主机上文件被误删除,这种结果是正确的。但如果只是想备份现有数据,这可以添加--delete
选项来消除这种行为
$ rsync -avl --delete scp_test shizhan@192.168.1.10:
building file list ... done
deleting scp_test/scp_test.txt
scp_test/
sent 91 bytes received 26 bytes 33.43 bytes/sec
total size is 0 speedup is 0.00
添加--delete
选项后,我们可以看到本机删除的文件在备份主机上的相应文件也删除了
sftp
如果你并不知道远程主机的目录结构,可以使用 sftp
来创建通过 ssh 服务的 ftp 对话(session)。通过 sftp
,你可以在ssh连接到远程主机后切换目录(cd
),显示目录内容(ls
)以及从主机上下载文件。
不要被指令名字误导,其实sftp 和 ftp协议没有任何关系,也没有使用 ftp 服务器。
更多操作可在运行 sftp
后输入 help
查看
sftp> help
Available commands:
bye Quit sftp
cd path Change remote directory to 'path'
chgrp grp path Change group of file 'path' to 'grp'
chmod mode path Change permissions of file 'path' to 'mode'
chown own path Change owner of file 'path' to 'own'
df [-hi] [path] Display statistics for current directory or
filesystem containing 'path'
exit Quit sftp
get [-afPpRr] remote [local] Download file
reget [-fPpRr] remote [local] Resume download file
reput [-fPpRr] [local] remote Resume upload file
help Display this help text
lcd path Change local directory to 'path'
lls [ls-options [path]] Display local directory listing
lmkdir path Create local directory
ln [-s] oldpath newpath Link remote file (-s for symlink)
lpwd Print local working directory
ls [-1afhlnrSt] [path] Display remote directory listing
lumask umask Set local umask to 'umask'
mkdir path Create remote directory
progress Toggle display of progress meter
put [-afPpRr] local [remote] Upload file
pwd Display remote working directory
quit Quit sftp
rename oldpath newpath Rename remote file
rm path Delete remote file
rmdir path Remove remote directory
symlink oldpath newpath Symlink remote file
version Show SFTP version
!command Execute 'command' in local shell
! Escape to local shell
? Synonym for help
进阶
你可以编辑/etc/ssh/sshd_config
来修改 ssh 服务的行为/etc/ssh/sshd_config
文件在行为定义的前面都有简明的注释,这里摘录一些常用的选项:
# What ports, IPs and protocols we listen for
# ssh服务监听的端口
Port 22
# HostKeys for protocol version 2
# 用于加密的密钥路径, 还记得之前说的 “在第一次登录远程主机时会接收到服务器端发给你的公钥”?吗,
# 如果你查看~/.ssh/known_hosts中对应主机的记录,会发现这条数据与下面指定的四个文件中的一个是一样的(根据加密方法的不同来选择文件)
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
想让你的远程主机更安全?当然可以。
在你设置好所有允许远程登录主机的免密码登录后,你可以通过修改/etc/ssh/sshd_config
配置来禁止使用密码登录
PasswordAuthentication no
这样没有加入到信任列表的主机将不能登录这台主机,即使他有密码也不行,这样即使你不小心泄露了密码,对方也无法入侵你的主机
通过添加一行
PermitRootLogin no
到/etc/ssh/sshd_config
配置文件中, 任何尝试通过root密码登录你的主机的连接都会被驳回
Permission denied
所有修改都会在重启 ssh 服务后生效
service ssh restart
实例
登录远程服务器
ssh -p端口号 root@域名或IP地址
将本地的文件夹/文件,拷贝到远程服务器上
scp -P端口号 -r Desktop/hospital/ root@域名或IP地址:/home/hospital/
将 远程服务器上 的文件夹/文件,拷贝到 本地
scp -P端口号 -r root@域名或IP地址:/home/hospital/ Desktop/hospital/