ssh⽤法及命令
什么是SSH?
简单说,SSH是⼀种⽹络协议,⽤于计算机之间的加密登录。如果⼀个⽤户从本地计算机,使⽤SSH协议登录另⼀台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会泄露。最早的时候,互联⽹通信都是明⽂通信,⼀旦被截获,内容就暴露⽆疑。1995年,芬兰学者Tatu Ylonen设计了SSH协议,将登录信息全部加密,成为互联⽹安全的⼀个基本解决⽅案,迅速在全世界获得推⼴,⽬前已经成为Linux系统的标准配置。
SSH只是⼀种协议,存在多种实现,既有商业实现,也有开源实现。本⽂针对的实现是OpenSSH,它是⾃由软件,应⽤⾮常⼴泛。这⾥只讨论SSH在Linux Shell中的⽤法。如果要在Windows系统中使⽤SSH,会⽤到另⼀种软件PuTTY,这需要另⽂介绍。
中间⼈攻击
SSH之所以能够保证安全,原因在于它采⽤了公钥加密。
整个过程是这样的:(1)远程主机收到⽤户的登录请求,把⾃⼰的公钥发给⽤户。(2)⽤户使⽤这个公钥,将登录密码加密后,发送回来。(3)远程主机⽤⾃⼰的私钥,解密登录密码,如果密码正确,就
同意⽤户登录。
这个过程本⾝是安全的,但是实施的时候存在⼀个风险:如果有⼈截获了登录请求,然后冒充远程主机,将伪造的公钥发给⽤户,那么⽤户很难辨别真伪。因为不像https协议,SSH协议的公钥是没有证书中⼼(CA)公证的,也就是说,都是⾃⼰签发的。
可以设想,如果攻击者插在⽤户与远程主机之间(⽐如在公共的wifi区域),⽤伪造的公钥,获取⽤户的登录密码。再⽤这个密码登录远程主机,那么SSH的安全机制就荡然⽆存了。这种风险就是著名的"中间⼈攻击"(Man-in-the-middle attack)。
ssh的安装
SSH分客户端openssh-client和openssh-server
如果你只是想登陆别的机器的SSH只需要安装openssh-client(ubuntu有默认安装,如果没有则sudoapt-get install openssh-client),如果要使本机开放SSH服务就需要安装openssh-server。
Ubuntu/win10(powershell)缺省已经安装了ssh client。
#配置ssh#
echo -e "\033[31;1m ******************************* \033[0m"
echo -e "\033[31;1m ************安装和配置ssh************ \033[0m"
sudo apt-get install -y openssh-server 1> /dev/null
sudo sed -i 's/UsePAM no/UsePAM yes/g' /etc/ssh/sshd_config
sudo sed -i '8a /etc/init.d/ssh start' /etc/profile
sudo /etc/init.d/ssh start
ps -e | grep ssh
echo -e "\033[31;1m ssh授权 \033[0m"
cd ~/.ssh/
ssh-keygen -t rsa
cat ./id_rsa.pub >> ./authorized_keys
$ ps -e|grep ssh
2151 ? 00:00:00 ssh-agent
5313 ? 00:00:00 sshd
ssh-agent表⽰ssh-client启动,sshd表⽰ssh-server启动了。
如果缺少sshd,说明ssh服务没有启动或者没有安装。
配置ssh并连接github/gitlab
参考[]
SSH基本⽤法
SSH远程登录
⼝令登录
假定你要以⽤户名user,登录远程主机host,只要⼀条简单命令就可以了。
$ ssh user@host 如:ssh pika@192.168.0.111
如果本地⽤户名与远程⽤户名⼀致,登录时可以省略⽤户名。
$ ssh host
SSH的默认端⼝是22,也就是说,你的登录请求会送进远程主机的22端⼝。使⽤p参数,可以修改这个端⼝。
$ ssh -p 2222 user@host
上⾯这条命令表⽰,ssh直接连接远程主机的2222端⼝。
如果你是第⼀次登录对⽅主机,系统会出现下⾯的提⽰:
$ ssh user@host
The authenticity of host 'host (12.18.429.21)' can't be established.
RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.
Are you sure you want to continue connecting (yes/no)?
这段话的意思是,⽆法确认host主机的真实性,只知道它的公钥指纹,问你还想继续连接吗?
所谓"公钥指纹",是指公钥长度较长(这⾥采⽤RSA算法,长达1024位),很难⽐对,所以对其进⾏MD5计算,将它变成⼀个128位的指纹。上例中是98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d,再进⾏⽐较,就容易多了。
很⾃然的⼀个问题就是,⽤户怎么知道远程主机的公钥指纹应该是多少?回答是没有好办法,远程主机必须在⾃⼰的⽹站上贴出公钥指纹,以便⽤户⾃⾏核对。
假定经过风险衡量以后,⽤户决定接受这个远程主机的公钥。
Are you sure you want to continue connecting (yes/no)? yes
系统会出现⼀句提⽰,表⽰host主机已经得到认可。
Warning: Permanently added 'host,12.18.429.21' (RSA) to the list of known hosts.
然后,会要求输⼊密码。
Password: (enter password)
如果密码正确,就可以登录了。
当远程主机的公钥被接受以后,它就会被保存在⽂件$HOME/.ssh/known_hosts之中。下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从⽽跳过警告部分,直接提⽰输⼊密码。
每个SSH⽤户都有⾃⼰的known_hosts⽂件,此外系统也有⼀个这样的⽂件,通常是/etc/ssh/ssh_known_hosts,保存⼀些对所有⽤户都可信赖的远程主机的公钥。
公钥登录
使⽤密码登录,每次都必须输⼊密码,⾮常⿇烦。好在SSH还提供了公钥登录,可以省去输⼊密码的步骤。
所谓"公钥登录",原理很简单,就是⽤户将⾃⼰的公钥储存在远程主机上。登录的时候,远程主机会向⽤户发送⼀段随机字符串,⽤户⽤⾃⼰的私钥加密后,再发回来。远程主机⽤事先储存的公钥进⾏解密,如果成功,就证明⽤户是可信的,直接允许登录shell,不再要求密码。这种⽅法要求⽤户必须提供⾃⼰的公钥。如果没有现成的,可以直接⽤ssh-keygen⽣成⼀个:
$ ssh-keygen
运⾏上⾯的命令以后,系统会出现⼀系列提⽰,可以⼀路回车。其中有⼀个问题是,要不要对私钥设置⼝令(passphrase),如果担⼼私钥的安全,这⾥可以设置⼀个。
运⾏结束以后,在$HOME/.ssh/⽬录下,会新⽣成两个⽂件:id_rsa.pub和id_rsa。前者是你的公钥,后者是你的私钥。
这时再输⼊下⾯的命令,将公钥传送到远程主机host上⾯:
$ ssh-copy-id user@host
好了,从此你再登录,就不需要输⼊密码了。
如果还是不⾏,就打开远程主机的/etc/ssh/sshd_config这个⽂件,检查下⾯⼏⾏前⾯"#"注释是否取掉。
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
然后,重启远程主机的ssh服务。
// ubuntu系统
service ssh restart
// debian系统
/etc/init.d/ssh restart
authorized_keys⽂件
远程主机将⽤户的公钥,保存在登录后的⽤户主⽬录的$HOME/.ssh/authorized_keys⽂件中。公钥就是⼀段字符串,只要把它追加在authorized_keys⽂件的末尾就⾏了。
这⾥不使⽤上⾯的ssh-copy-id命令,改⽤下⾯的命令,解释公钥的保存过程:
$ ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub
这条命令由多个语句组成,依次分解开来看:(1)"$ ssh user@host",表⽰登录远程主机;(2)单引号中的mkdir .ssh && cat >>
.ssh/authorized_keys,表⽰登录后在远程shell上执⾏的命令:(3)"$ mkdir -p .ssh"的作⽤是,如果⽤户主⽬录中的.ssh⽬录不存在,就创建⼀个;(4)'cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub的作⽤是,将本地的公钥⽂件~/.ssh/id_rsa.pub,重定向追加到远程⽂件authorized_keys的末尾。
写⼊authorized_keys⽂件后,公钥登录的设置就完成了。
[]
使⽤ssh在远程后台不中断地跑程序
Linux关闭ssh(关闭终端等)后运⾏的程序或者服务⾃动停⽌,如python3 a.py &。
解决:使⽤nohup命令让程序在关闭窗⼝(切换SSH连接)的时候程序还能继续在后台运⾏。
nohup python3 a.py &
[]
ssh连接中断
如果使⽤的是iTerm2,要让ssh不断线: profiles -> sessions -> When idel, send ASCII code
其它命令⾏客户端,通过配置 ServerAliveInterval 来实现,在 ~/.ssh/config 中加⼊: ServerAliveInterval=30。表⽰ssh客户端每隔30秒给远程主机发送⼀个no-op包,no-op是⽆任何操作的意思,这样远程主机就不会关闭这个SSH会话。
vim ~/.ssh/config,然后新增
Host *
ServerAliveInterval 60
60秒就好了,⽽且基本去连的机器都保持,所以配置了*,如果有需要针对某个机器,可以⾃⾏配置为需要的serverHostName。
[]
SSH远程操作
SSH数据传输
SSH不仅可以⽤于远程主机登录,还可以直接在远程主机上执⾏操作。
$ ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub
单引号中间的部分,表⽰在远程主机上执⾏的操作;后⾯的输⼊重定向,表⽰数据通过SSH传向远程主机。cipher命令
这就是说,SSH可以在⽤户和远程主机之间,建⽴命令和数据的传输通道,因此很多事情都可以通过SSH来完成。
下⾯看⼏个例⼦。
【例1】
将$HOME/src/⽬录下⾯的所有⽂件,复制到远程主机的$HOME/src/⽬录。
$ cd && tar czv src | ssh user@host 'tar xz'
【例2】
将远程主机$HOME/src/⽬录下⾯的所有⽂件,复制到⽤户的当前⽬录。
$ ssh user@host 'tar cz src' | tar xzv
【例3】
查看远程主机是否运⾏进程httpd。
$ ssh user@host 'ps ax | grep [h]ttpd'
lz建议使⽤scp进⾏远程copy:
scp 跨机远程拷贝
scp是secure copy的简写,⽤于在Linux下进⾏远程拷贝⽂件的命令,和它类似的命令有cp,不过cp只是在本机进⾏拷贝不能跨服务器,⽽且scp传输是加密的。可能会稍微影响⼀下速度。两台主机之间复制⽂件必需得同时有两台主机的复制执⾏帐号和操作权限。
scp命令参数
-1 强制scp命令使⽤协议ssh1
-2 强制scp命令使⽤协议ssh2
-4 强制scp命令只使⽤IPv4寻址
-6 强制scp命令只使⽤IPv6寻址
-B 使⽤批处理模式(传输过程中不询问传输⼝令或短语)
-C 允许压缩。(将-C标志传递给ssh,从⽽打开压缩功能)
-p 留原⽂件的修改时间,访问时间和访问权限。
-q 不显⽰传输进度条。
-r 递归复制整个⽬录。
-v 详细⽅式显⽰输出。scp和ssh(1)会显⽰出整个过程的调试信息。这些信息⽤于调试连接,验证和配置问题。
-c cipher 以cipher将数据传输进⾏加密,这个选项将直接传递给ssh。
-F ssh_config 指定⼀个替代的ssh配置⽂件,此参数直接传递给ssh。
-i identity_file 从指定⽂件中读取传输时使⽤的密钥⽂件,此参数直接传递给ssh。
-l limit 限定⽤户所能使⽤的带宽,以Kbit/s为单位。
-o ssh_option 如果习惯于使⽤ssh_config(5)中的参数传递⽅式,
-P port 注意是⼤写的P, port是指定数据传输⽤到的端⼝号
-S program 指定加密传输时所使⽤的程序。此程序必须能够理解ssh(1)的选项。
scp⼀般有六种使⽤⽅法
本地复制远程⽂件:(把远程的⽂件复制到本地)
scp st:/val/test/ /val/test/
远程复制本地⽂件:(把本地的⽂件复制到远程主机上)
scp /val/ st:/val/
本地复制远程⽬录:(把远程的⽬录复制到本地)
scp -r st:/val/test/ /val/test/
远程复制本地⽬录:(把本地的⽬录复制到远程主机上)
scp -r ./ubuntu_env/ root@192.168.0.111:/home/pipi
pika:/media/pika/files/machine_learning/datasets$scp -r SocialNetworks/ piting@192.168.0.172:/media/data/pipi/datasets
本地复制远程⽂件到指定⽬录:(把远程的⽂件复制到本地)
scp st:/val/test/ /val/test/
远程复制本地⽂件到指定⽬录:(把本地的⽂件复制到远程主机上)
scp /val/ st:/val/
ps: scp复制⽂件时只指定服务器地址不加路径默认复制到哪⾥
[]
[]
SSH端⼝操作
绑定本地端⼝
既然SSH可以传送数据,那么我们可以让那些不加密的⽹络连接,全部改⾛SSH连接,从⽽提⾼安全性。
假定我们要让8080端⼝的数据,都通过SSH传向远程主机,命令就这样写:
$ ssh -D 8080 user@host
SSH会建⽴⼀个socket,去监听本地的8080端⼝。⼀旦有数据传向那个端⼝,就⾃动把它转移到SSH连接上⾯,发往远程主机。可以想象,如果8080端⼝原来是⼀个不加密端⼝,现在将变成⼀个加密端⼝。
本地端⼝转发
有时,绑定本地端⼝还不够,还必须指定数据传送的⽬标主机,从⽽形成点对点的"端⼝转发"。为了区别后⽂的"远程端⼝转发",我们把这种情况称为"本地端⼝转发"(Local forwarding)。
假定host1是本地主机,host2是远程主机。由于种种原因,这两台主机之间⽆法连通。但是,另外还有⼀台host3,可以同时连通前⾯两台主机。因此,很⾃然的想法就是,通过host3,将host1连上host2。
我们在host1执⾏下⾯的命令:
$ ssh -L 2121:host2:21 host3
命令中的L参数⼀共接受三个值,分别是"本地端⼝:⽬标主机:⽬标主机端⼝",它们之间⽤冒号分隔。这条命令的意思,就是指定SSH绑定本地端⼝2121,然后指定host3将所有的数据,转发到⽬标主机host2的21端⼝(假定host2运⾏FTP,默认端⼝为21)。
这样⼀来,我们只要连接host1的2121端⼝,就等于连上了host2的21端⼝。
$ ftp localhost:2121
"本地端⼝转发"使得host1和host3之间仿佛形成⼀个数据传输的秘密隧道,因此⼜被称为"SSH隧道"。
下⾯是⼀个⽐较有趣的例⼦。
$ ssh -L 5900:localhost:5900 host3
它表⽰将本机的5900端⼝绑定host3的5900端⼝(这⾥的localhost指的是host3,因为⽬标主机是相对host3⽽⾔的)。
另⼀个例⼦是通过host3的端⼝转发,ssh登录host2。
$ ssh -L 9001:host2:22 host3
这时,只要ssh登录本机的9001端⼝,就相当于登录host2了。
$ ssh -p 9001 localhost
上⾯的-p参数表⽰指定登录端⼝。
出错处理:ssh: Could not resolve hostname 192.168.*.*:***: Name or service not known
解决:指定端⼝不能直接使⽤ip:端⼝号,使⽤-p参数来解决就可以了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论