tldr ssh
Secure Shell is a protocol used to securely log onto remote systems.It can be used for logging or executing commands on a remote server.- Connect to a remote server: ssh username@remote_host- Connect to a remote server with a specific identity (private key): ssh -i path/to/key_file username@remote_host- Connect to a remote server using a specific port: ssh username@remote_host -p 2222- Run a command on a remote server: ssh remote_host command -with -flags- SSH tunneling: Dynamic port forwarding (SOCKS proxy on localhost:9999): ssh -D 9999 -C username@remote_host- SSH tunneling: Forward a specific port (localhost:9999 to slashdot.org:80): ssh -L 9999:slashdot.org:80 username@remote_host- Enable the option to forward the authentication information to the remote machine (see `man ssh_config` for available options): ssh -o "ForwardAgent=yes" username@remote_host |
using ssh agent
ssh-agent命令是一种用来保存公钥身份验证所使用的私钥的程序,本质上ssh-agent就是一个密钥管理器,运行ssh-agent以后,使用ssh-add将私钥交给ssh-agent保管,其他程序需要身份验证的时候可以将验证申请交给ssh-agent来完成整个认证过程。
关于ssh-agent的工作原理可以查看An Illustrated Guide to SSH Agent Forwarding这篇文章,这里简单举例子说明其作用:
假设当前机器为A,另有远程服务器B、C、D,将A的公钥发布到3台远程服务器上,在机器A开启ssh-agent,然后ssh-add当前A机器的私钥,并且在~/.ssh/config中开启转发ForwardAgent yes,这样B、C和D三台服务器之间 ssh 登录都可以通过A的这个公钥进行验证登录,而不用配置A的私钥,比如先 ssh 到B,可以从B直接 ssh 到C和D。
A 机器执行的命令
B,C和D服务器上只要开启sshd服务,并且将用户目录下面的~/.ssh目录备份删除掉。A机器上备份删除原来的~/.ssh目录后,执行以下命令:
# 创建密钥 ssh-keygen -t rsa -C "username@A"# 一般 Mac OSX 和 Linux 都已经开启`ssh-agent`服务,可以使用以下命令确认 echo "$SSH_AUTH_SOCK"# 如果没有开启 ssh-agent,则手动输入下面这个命令 eval "$(ssh-agent -s)"# 显示ssh-agent中的公钥 ssh-add -L# 如果没有显示任何公钥信息,则手动加入个人的密钥 ssh-add ~/.ssh/id_rsa# 开启转发,一定要有这个配置,不然开启了 ssh-agent 也不会转发 echo "Host *\n ForwardAgent yes" > ~/.ssh/config# 用 ssh-copy-id 命令发布 A 机器的公钥到 B,C,D 服务器上,不要手动去创建目录和文件 ssh-copy-id username@B ssh-copy-id username@C ssh-copy-id username@D |
检查本地被代理的密钥
- -L:显示ssh-agent中的公钥
- -l:显示ssh-agent中的密钥
ssh-add -LThe agent has no identities. |
如果提示如上,则目前没有代理任何密钥,Linux 上可以通过ssh-add ~/.ssh/id_rsa命令添加指定的密钥。Mac OSX 上启动和添加密钥的操作说明,可以参考github文档的说明:
# Note: The -K option is Apple standard version of ssh-add, which stores the passphrase in your keychain for you when you add an ssh key to the ssh-agent. ssh-add -K ~/.ssh/id_rsaPassphrase stored in keychain: /Users/username/.ssh/id_rsaIdentity added: /Users/username/.ssh/id_rsa (/Users/username/.ssh/id_rsa) ssh-add -L2048 2f:31:ba:0c:3e:b2:70:52:00:bc:85:37:a2:a7:77:ad /Users/username/.ssh/id_rsa (RSA) |
ssh -t jumpbox.server ssh remote.server
ssh -t -i ~/.ssh/jumpbox_rsa.pub username@jumpbox.server ssh username@remote.server ssh -t username@jumpbox.server ssh username@remote.server |
~/.ssh/config 文件配置
上面的命令参数有点多,通过配置~/.ssh/config文件,可以简化ssh命令连接常用服务器的参数:
Host * ForwardAgent yesHost jumpbox.server HostName 192.168.1.11 User username IdentityFile ~/.ssh/jumpbox_rsa.pub ControlMaster auto ControlPath ~/.ssh/socket/master-%l-%r@%h:%pHost remote.server1 HostName 192.168.1.2 User username Port 22 ForwardAgent yes ProxyCommand ssh -i ~/.ssh/jumpbox_rsa.pub username@remote.server 'nc %h %p'Host remote.server2 HostName 192.168.1.3 User username Port 22 ForwardAgent yes ProxyCommand ssh jumpbox.server nc %h %p |
如上配置之后,就不用在命令行里每次显示的指定jumpbox.server,可以直接连接远程服务器,这里服务器的别名不需要 DNS 解析,ssh会从~/.ssh/config中获取服务器地址:
ssh remote.server1 ssh remote.server2 |
set up socks5 ssh tunnel
ssh -D 1337 -N -C -f -q username@jump.server.com# 如果有密钥,则指定 -i 参数 ssh -D 1337 -N -C -f -q -i ~/.ssh/jumpbox_rsa.pub username@jump.server.com |
use socks5 tunnel with proxychains-ng
proxychains-ng安装请参考官方文档,在/etc/proxychains.conf文件[ProxyList]下面加入代理配置:
socks5 127.0.0.1 1337 |
如果需要jumpbox.server转发到目标服务器,像正常scp命令一样使用,只是在前面加上proxychains4, 如下:
proxychains4 scp pom.xml username@remote.server:/home/username |
ssh local forwarding
不用proxychains-ng的话,则使用ssh本地端口转发命令,示例如下,访问本地8022端口的数据会被转发到192.168.1.3:22端口:
- -L [bind_address:]port:host:hostport
- -N Do not execute a remote command. This is useful for just forwarding ports (protocol version 2 only)
ssh -N -L 8022:192.168.1.3:22 -i ~/.ssh/jumpbox_rsa.pub username@jumpbox.server scp -P 8022 README.md username@localhost:/home/username |
mysql客户端连接本地3307端口,即可经过jumpbox.server的ssh转发到远程remote.mysql.server:
ssh -N -L 3307:remote.mysql.server:3306 -i ~/.ssh/jumpbox_rsa.pub username@jumpbox.server mysql -u root -P 3307 -p -h localhost test |
ssh remote forwarding
可以通过ssh将本地或者内网的服务暴露给外网,如访问远程服务器jumpbox.server:8080的请求会经过ssh转发到本地的localhost:443端口:
- -R [bind_address:]port:host:hostport
- -N Do not execute a remote command. This is useful for just forwarding ports (protocol version 2 only)
本地监听443端口:
nc -l 443 |
从本地使用ssh连接远程服务器jumpbox.server,并会在远程服务器开启监听端口8090,加入-N参数是指不需要真实远程登陆到jumpbox.server上:
ssh -N -R 8090:localhost:443 username@jumpbox.server |
这时再访问远程服务器,可以用netstat命令查看到,通过ssh在远程服务器上打开了一个监听端口8090:
netstat -an | grep 8090tcp 0 0 127.0.0.1:8090 0.0.0.0:* LISTEN |
在jumpbox.server上执行以下命令:
echo test | nc localhost 8090 |
本地监听443的端口会收到远程服务器转发过来的字符串test,如果本地没有监听443端口,则提示:
connect_to localhost port 443: failed.
ssh-agent 登录碰到的一个问题
从当前机器A可以经过jumpbox.server服务器登录到B和C,却在登录D时需要密码输入之后才能进入。D和B、C服务器一样,在~/.ssh/authorized_keys文件中有A的公钥信息,sshd服务器版本和配置都是一样的,同时检查了一下~/.ssh/authorized_keys文件的权限都是600,这个文件没有问题。
当前机器A上的环境如下:
~/.ssh/configHost * ForwardAgent yesHost jumpbox.server HostName 192.168.1.11 User username IdentityFile ~/.ssh/jumpbox_rsa.pub ControlMaster auto ControlPath ~/.ssh/socket/master-%l-%r@%h:%p ssh-add -Lssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQnnbiFwLHAQemEg4kHBvqpPe4k8X07tZoakf6Ky5hSn222qTCrS1WJVIgXs5nuxKVTGFe6mkywQh64e6Lluu4bWCL/gE7IbEDPEZd6viQSYnaEiCDLvIfENrAC7LynnHRXBMimp2pPGU+j/I/+uOjnUkvHNPy9v7GxRU7Dak3mewMHM4DdsPJJrG8eSMu4PBbK3mGbKI96gsg2uQ3GXJeZmG5tLVFUTnywJHX++s3q1FBeDrWsqcQsD9uRxpDAv7CUbtjBxRzmsXwGTQZjcupX33bhGWHfOp4ELTqfMv2PwaeE+PatU45bsciQeZDmG8myBpiuZujNV4OoBH1F2yr username@localhost |
通过ssh -vvv server.D.ip也没有得到明显的提示信息,在网上 GOOGLE 了一些文章之后,在这个帖子里,看到有个人提到了~/.ssh目录的权限需要是700,一般这个目录是用ssh-keygen生成的就是700权限,可是在服务器D上,这个目录却是755的权限,也就是这个目录是手工创建的,所以密钥登录验证没有通过,只能使用密码方式验证登录的用户了,另外authorized_keys最好是通过客户端的ssh-copy-id命令创建,如果手工创建也要确保文件权限是600的。
ls -la ~drwxrwxr-x 2 username username 4096 Apr 7 11:28 .ssh ls -la ~/.ssh/authorized_keys-rw------- 1 username username 398 Apr 7 11:28 authorized_keys |
上面的.ssh目录权限不正确,正确应该如下:
chmod 700 ~/.ssh ls -la ~drwx------ 2 username username 4096 Apr 7 11:29 .ssh |
用户主目录的权限对 SSH 的影响
在 Mac OSX 和 Ubuntu 里,用户主目录的权限为755,用户是可以使用公钥登录的,但是 CentOS 系统中,用户目录的权限必须是700的,不然也会因为宿主目录权限不正确,而被服务器拒绝公钥登录。
/etc/security/access.conf
这个文件的配置也可以控制用户的登录权限。
References
- Generating a new SSH key and adding it to the ssh-agent
- Using SSH agent forwarding
- An Illustrated Guide to SSH Agent Forwarding
- SSH CONFIG FILE
- SSH PORT FORWARDING EXAMPLE
- ProxyChains-NG ver 4.12 README
- Create a SOCKS proxy on a Linux server with SSH
- SSH from A through B to C, using private key on B
- Using Jump Servers and Port Forwarding
- Mac OSX系统下通过ProxyChains-NG实现终端下的代理
- ssh-agent not working properly