Linux命令 ssh


原文链接: Linux命令 ssh

ssh的连接重用
牢记25个最佳的SSH命令
16条技巧让你更高效使用SSH
ssh通过代理连接服务器
SSH端口中转全攻略
Tunnel:论如何在内网中自由渗透
usage: ssh [-1246AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]

       [-D [bind_address:]port] [-E log_file] [-e escape_char]
       [-F configfile] [-I pkcs11] [-i identity_file] [-L address]
       [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
       [-Q query_option] [-R address] [-S ctl_path] [-W host:port]
       [-w local_tun[:remote_tun]] [user@]hostname [command]

-b bind_address 当有多个网卡时,指定绑定的ip
-c cipher_spec 加密算法 “3des”, “blowfish”, and “des”.

ssh-keygen
-b 2048 密钥长度,默认为 2048
-t rsa 密钥类型, rsa|des|ECDSA (默认类型为rsa)
-N 新密码
-f id_rsa 指定密钥文件,创建时会同时生成一个.pub结尾的公钥文件。
-C
-c 修改公钥或私钥文件中的注释
-p 修改私钥文件密码
-P 旧密码
-e 导出为其它格式的密钥文件,可以转换密钥类型
-i 从其他格式的密钥文件导入,可以转换密钥类型
-m 与-e,-i配合使用,指明导出或导入的密钥文件格式
-y 读入密钥并显示公钥


sshd_config 中 TOKENS 变量

%h    用户的HOME目录
%u    用户名

ChrootDirectory 可使用以下tokens %%, %h, 和 %u.

限制IP访问ssh

  1. 在ssh的配置文件:/etc/ssh/sshd_config 中添加如下一行即可

    Allowusers username@192.168.1.100 #允许某个ip用什么帐户登陆
    AllowUsers root@tardis root@tardis.drwho.com
    Allowusers root@123.132.226.66 root@123.132.252.42
    
  2. 修改 /etc/hosts.allow 会立即生效

    在这个文件中添加sshd: 允许访问的IP地址
    sshd:123.132.226.66,123.132.252.42:allow
    
    1:修改 /etc/hosts.allow 文件,在最下面添加一行:
    sshd:192.168.100.0/255.255.255.0        #允许局域网内所有机器访问服务器上的sshd进程
    sshd:60.28.160.244   #允许外网的60.28.160.244访问这个服务器上的sshd进程
    sshd:11.8.,12.1.,18.3.:allow
    sshd:123.132.252.42,123.132.226.66,139.129.234.31,139.129.108.163:allow
    2:修改 /etc/hosts.deny 文件,在最后一行添加:
    sshd:all:Deny  #禁止所有
    

消除每次问yes/no,避免需要手工输入 yes 这种情况

可以在 scp 或者 ssh 的时候加上 -o StrictHostKeyChecking=no 即可。
ssh -o StrictHostKeyChecking=no

vi /etc/ssh/ssh_config

  StrictHostKeyChecking no

2. ssh保持连接 5分钟发送一个数据包 5*60

ssh -o TCPKeepAlive=yes -o ServerAliveInterval=300

3. 免密码登录


#!/bin/sh
for i in {2..18}
do
expect<<!
  spawn ssh-copy-id -i root@10.114.0.${i}
  expect "*yes/no)?*"
  send "yes\r"
  expect "*password:*"
  send "Lyb@2017\r"
  expect eof
!
done

移除fingerprint
ssh-keygen -f "/home/ubuntu/.ssh/known_hosts" -R 47.90.57.192

允许密码登录

vi /etc/ssh/sshd_config

 PasswordAuthentication yes
 #PasswordAuthentication no

在服务器添加完公钥之后,ssh服务器然后报了错误 sign_and_send_pubkey: signing failed: agent refused operation
然后执行了以下命令才好 eval "$(ssh-agent -s)"
ssh-add

免密码登录SSH

  1. 生成密钥
    ssh-keygen -t rsa -b 2048 -C "kig5.com"
  2. 复制密钥
    cat ~/.ssh/id_rsa.pub | ssh user@machine “mkdir ~/.ssh; cat >> ~/.ssh/authorized_keys”
    ssh-copy-id root@deedbeef.com
    ssh-keyscan remote_servers >> ~/.ssh/known_hosts # ssh的时候不会提示是否保存key
  3. 修改 .ssh 目录权限
    0) /root目录用户必须 root:root
    1) .ssh目录的权限必须是700
    2) .ssh/authorized_keys文件权限必须大于400
    chown $(id -u):$(id -g) $HOME
    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/id_rsa
    chmod 644 ~/.ssh/id_rsa.pub
    chmod 400 ~/.ssh/authorized_keys
    3) chattr +i ~/.ssh/authorized_keys

  4. 编辑 sshd_config 配置文件
    vim /etc/ssh/sshd_config
    PubkeyAuthentication yes
    AuthorizedKeysFile %h/.ssh/authorized_keys
    useDNS no

远程执行命令

ssh 连接服务器时使自动启动 tmux

通过SSH连接屏幕
ssh -t root@keyicloud.com tmux a
ssh user@host -t 'tmux list-session; if [[ $? -eq 0 ]]; then tmux attach; else tmux;fi'

通过中间主机建立SSH连接

ssh -t reachable_host ssh unreachable_host
-t 提供一个远程服务器的虚拟tty终端

通过SSH运行复杂的远程shell命令

ssh host -l user 'cat cmd.txt'

通过ssh在远程机器上重启Nginx

ssh -f root@$ADMIN_SSH_HOST -p $ADMIN_SSH_PORT "sh $PROJECT_DIR/backend_deploy.sh $NAME $ADMIN_PORT $DB_HOST $DB_PORT $DB_USER $DB_PASSWORD $DB_DATABASE $REDIS_HOST $REDIS_PASSWORD";

scp nginx.conf root@10.114.0.2:/etc/nginx/
ssh -tt root@$NGINX_HOST <<EOF
nginx -t && nginx -s reload && exit 0
EOF

SSH 代理


RSA 公钥验证和匹配的已知可信远程主机是一种有效防止中间人攻击的手段。不过在批量 scp 或者 ssh 的时候,可能会出现一水儿的 RSA 公钥验证请求。这种时候,要不然需要手工输入一长串的 yes;要不然连输入的机会都没有,就被刷屏了。

-L 正向代理 端口转发 正向隧道

-L [bind_address:]port:host:hostport
-L [bind_address:]port:remote_socket
-L local_socket:host:hostport
-L local_socket:remote_socket

ssh -L 9999:localhost:8384 machine
This will bind to your local port 9999 and forward all connections from there to port 8384 on the target machine. This still works even if Syncthing is bound to listen on localhost only.

本机访问代理后面的内网机器,且中间没有防火墙; 执行点在本机localhost

LHOST -> proxy -> RHOST

本地访问127.0.0.1:port1就是host:port2(用的更多)
ssh -CfNg -L local_port:target_ip:target_port proxy_user@proxy_ip #本地转发
ssh -CNfg -L 0.0.0.0:2222:139.129.234.31:22 root@139.129.108.163 -p 222

可以将dmz_host的hostport端口通过proxy_ip转发到本地的port端口
ssh -qTfnN -L local_port:unreachable_ip:unreachable__port -l dmz_user dmz_ip -p 222 #正向隧道,监听本地port

dmz == proxy 代理机
target == Rhost==remote 目标机

-q Quiet mode.                    安静模式
-T Disable pseudo-tty allocation. 禁用伪终端,自动化时使用。不占用 shell 了
-C Enable compression.            压缩数据传输。
-N Do not execute a shell or command. 不执行远程命令,端口转发就用它了,通常与-f连用。
-f Fork into background after authentication.  后台运行 认证用户/密码,通常和-N连用,不用登录到远程主机。并推荐加上 -n 参数。
-n Redirects stdin from /dev/null (actually, prevents reading from stdin). -f 推荐的,不加这条参数应该也行。
-g Allow remote hosts to connect to forwarded ports. 在-L/-R/-D参数中,允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接。

-R 反向代理 反向隧道

-R [bind_address:]port:host:hostport
-R [bind_address:]port:local_socket
-R remote_socket:host:hostport
-R remote_socket:local_socket

用于内网穿透防火墙限制; 执行点在[RHOST]肉鸡target (RHOST)

LHOST<--->proxy<---firewall--->Rhost

ssh -CfNg -R port2:127.0.0.1:port1 user@host #远程转发
访问host:port2就是访问127.0.0.1:port1

  1. ssh -qTCNfg -R 8000:localhost:8080 root@139.129.108.163
    转发外网139.129.108.163:8000的流量->内网(RHOST) 127.0.0.1:8080 ((RHOST)内网执行)
  2. nc -l 8001 -c "nc localhost 8000" #外网执行 本机端口转发
    ssh -qTCNfL *:8001:localhost:8000 localhost #本机端口转发8001->8000

可以将dmz_host的hostport端口转发到remote_ip的port端口 dzm == local
ssh -qTCNfn -R remote_port:dmz_host:dmz_port -l user remote_ip #反向隧道,用于内网穿透防火墙限制之类

-D [bind_address:]port 动态映射 [做socks5代理使用]

ssh -qTfnN -D port remotehost

ssh方式使用google
ssh -qTfnN -D 7070 root@xx.xx.xx.xx -p3009

SOCKS主机:127.0.0.1 端口:7070
确定后就可以正常使用google

把socks代理转换成http代理:privoxy

5、自动连接和防断线脚本

```bat
:1
plink -pw “password” -D 7070 user@serverip
goto 1
```
apt-get install sshpass
`sshpass -p "password" ssh -D 7070 user@serverip`

然后写脚本autossh.sh,内容如下:
```bash
#!/bin/bash

while [ '' == '' ]
do
ssh_d_process_num=`ps aux|grep -E 'ssh \-' |grep -v grep |wc -l`
if [ "$ssh_d_process_num" == "0" ]; then
  /home/user/sshpass -p "password" ssh -D 7070 user@ServerIP &
fi

sleep 300
done
```

SSH打洞

使用场景

开发联调。别人只能访问到你的外网地址,但是你想在本地机器监测并调试
内网内容资源展示

基本流程就是别人访问外网,然后外网转发到内网,实际的内容是在内网。因为外网不能主动访问到内网,所以下面这条命令一定要从内网运行。
#暴露内网的3306给remotehost的9123,这样别人访问外网的9123实际就是访问的内网的3306
ssh -R 9123:127.0.0.1:3306 username@remotehost
流量转发
使用场景

本地不能直接连接处于内网的mysql,可以通过ssh forward上去

这条命令会转发本地3308的流程到mysqlhost的3306端口
ssh -L 3308:mysqlhost:3306 user@sshhost
还是比较好区分这两种命令的。R代表remote,L代表local,如果是-R表示remote -> local,-L标志local->remote

################################################################################

ssh 安全与后门

这里的场景和前段时间的 redis + ssh 漏洞很相似,那么这里需要看一下服务器是否有ssh服务,如果有的话,那么直接把/root/.ssh目录挂载到container内,比如/tmp /.ssh,然后修改/tmp/.ssh/authorized_keys 文件,把自己的public key写进去,修改权限为600,然后就可以以root用户登录了。

注:有些服务器会配置不允许root用户直接登录,可以通过挂载 /etc/ssh/sshd_config 查看配置。这个时候,你换一个用户目录写入就行,并且挂载修改 /etc/sudoers 文件,直接配置成免密码,sudo切换root即可。

如果没有运行ssh服务,那么也可以利用挂载写crontab定时任务,比如ubuntu root用户的crontab文件在 /var/spool/cron/crontabs/root,反弹一个shell~

配置允许指定user访问

AllowUsers
AllowGroups
DenyUsers
DenyGroups
AllowUsers允许指定的用户可以通过ssh服务登录该服务器,如果使用了AllowUsers,则只有AllowUsers的用户可以登录服务器,其它用户不能登录服务器.

注意:
1)如果我们使用PermitRootLogin no(阻止Root用户登录),那样AllowUsers root是不会生效的.
2)如果我们使用DenyUsers阻止某用户登录,而AllowUsers开放某用户登录,则以DenyUsers为准.
3)如果我们使用DenyGroups阻止某用户组登录,而AllowUsers开放某用户登录,也以DenyGroups为准.
4)如果增加多个用户,各用户名之间用空格分隔,例如:AllowUsers root test test1
最后我们对AllowUsers进行测试:
1) ssh服务端:
vi /etc/ssh/sshd_config
AllowUsers test
存盘退出,并重启sshd服务
/etc/init.d/sshd restart

2) ssh客户端:
此时我们使用用户test1登录系统,发现无法登录,如下:
ssh test1@192.168.27.142
test1@192.168.27.142's password:
Permission denied, please try again.

转为使用test用户,登录成功,说明AllowUsers是起作用的,如下:
ssh test@192.168.27.142
test@192.168.27.142's password:
Last login: Sat Jun 4 18:50:52 2011 from 192.168.27.143

AllowGroups/DenyUsers/DenyGroups的用法都比较简单,我们在此不一一举例.

ssh中如何配置只允许某个IP以某个账号登录服务器?

使用TCP wrappers仅允许指定的主机连接

如果你想在你的网络上只允许特定的主机才能连接到你的SSH服务,但又不想使用或弄乱你的iptables配置,那这个方法非常有用,你可以使用TCP wrappers。在这个例子中对sshd进行TCP包裹,我将创建一条规则允许本地子网192.168.1.0/24和远程193.180.177.13的自己连接到我的SSH服务。
默认情况下,TCP wrappers首先在/etc/hosts.deny中查找看主机是否允许访问该服务,接下来,TCP wrappers查找/etc/hosts.allow看是否有规则允许该主机服务指定的服务,我将在/etc/hosts.deny中创建一个规则,如下:
sshd: ALL

这意味着默认情况下所有主机被拒绝访问SSH服务,这是应该的,否则所有主机都能访问SSH服务,因为TCP wrappers首先在hosts.deny中查找,如果这里没有关于阻止SSH服务的规则,任何主机都可以连接。

接下来,在/etc/hosts.allow中创建一个规则允许指定的主机使用SSH服务:
sshd: 192.168.1 193.180.177.13

现在,只有来自192.168.1.0/24和193.180.177.13的主机能够访问SSH服务了,其他主机在连接时还没有到登陆提示符时就被断开了,并收到错误提示,如下:
ssh_exchange_identification: Connection closed by remote host

7、使用iptables允许特定的主机连接
iptables -A INPUT -p tcp -m state --state NEW --source 193.180.177.13 --dport 22 -j ACCEPT
并确保没有其他的主机可以访问SSH服务:
iptables -A INPUT -p tcp --dport 22 -j DROP

8、SSH时间锁定技巧
你可以使用不同的iptables参数来限制到SSH服务的连接,让其在一个特定的时间范围内可以连接,其他时间不能连接。你可以在下面的任何例子中使用/second、/minute、/hour或/day开关。
第一个例子,如果一个用户输入了错误的密码,锁定一分钟内不允许在访问SSH服务,这样每个用户在一分钟内只能尝试一次登陆:
~# iptables -A INPUT -p tcp -m state --syn --state NEW --dport 22 -m limit --limit 1/minute --limit-burst 1 -j ACCEPT
~# iptables -A INPUT -p tcp -m state --syn --state NEW --dport 22 -j DROP
第二个例子,设置iptables只允许主机193.180.177.13连接到SSH服务,在尝试三次失败登陆后,iptables允许该主机每分钟尝试一次登陆:
~# iptables -A INPUT -p tcp -s 193.180.177.13 -m state --syn --state NEW --dport 22 -m limit --limit 1/minute --limit-burst 1 -j ACCEPT
~# iptables -A INPUT -p tcp -s 193.180.177.13 -m state --syn --state NEW --dport 22 -j DROP


##剪切板
sudo apt-get install xclip
xclip -sele clip ~/.ssh/id_rsa.pub

ssh root@1.0.9.8

#add a user for login as root, add -m to create home/tsnd folder
useradd sona -m
passwd sona

cat /etc/sudoers
visudo

add line

Ctrl + X , then y, remove ending .tmp in file name to quit nano and save settings

sona ALL=(ALL:ALL) ALL

Configure SSH server settings

vi /etc/ssh/sshd_config

Port 420
#2048 or 1024 both working
ServerKeyBits 2048
PermitRooLogin no
PasswordAuthentication no
RSAAuthentication yes
PubkeyAuthentication yes

add new lines

MaxStartups 5
AllowUsers aywusq

Set SSH key for new SSH user

su sona #swicth to sona and set the public key
mkdir ~/.ssh
touch ~/.ssh/authorized_keys
vi ~/.ssh/authorized_keys

paste the public key

chmod 400 ~/.ssh/authorized_keys
chmod 700 ~/.ssh

#one said: id_rsa is 600,id_rsa.pub is 644

service ssh restart
#/etc//init.d/ssh restart

Test the new SSH server

Please note: DON't close the terminal, create a new terminal window to test the new ssh_config, we need to change settings if we are unable log in using the rsa key

#log in using the rsa key on local machine
ssh -i path_to_id_rsa -p 420 sona@1.0.9.8
su
#enter root password to swich as root user
exit

16条技巧让你更高效使用SSH
SSH有很多非常酷的特性,如何它是你每天的工作伴侣,那么我想你有必要了解以下16条高效使用SSH的秘籍,它们帮你节省的时间肯定会远远大于你用来配置它们的时间。

  1. 多条连接共享

  如果你需要在多个窗口中打开到同一个服务器的连接,而不想每次都输入用户名,密码,或是等待连接建立,那么你可以配置SSH的连接共享选项,在本地打开你的SSH配置文件,通常它们位于~/.ssh/config,然后添加下面2行:

ControlMaster auto
ControlPath /tmp/sshmux%h%p%r

  现在试试断开你与服务器的连接,并建立一条新连接,然后打开一个新窗口,再创建一条连接,你会发现,第二条连接几乎是在瞬间就建立好了。

  Windows用户

  如果你是Windows用户,很不幸,最流行的开源SSH客户端Putty并不支持这个特性,但是Windows上也有OpenSSH的实现,比如这个Copssh,如果你觉得下面的一些技巧对你很有帮助,或许你应该试试Copssh。

  文件传输

  连接共享不止可以帮助你共享多个SSH连接,如果你需要通过SFTP与服务器传输文件,你会发现,它们使用的依然是同一条连接,如果你使用的Bash,你会发现,你甚至SSH甚至支持Tab对服务器端文件进行自动补全,共享连接选项对于那些需要借助SSH的工具,比如rsync,git等等也同样有效。

  2. 长连接

  如果你发现自己每天需要连接同一个服务器无数次,那么长连接选项就是为你准备的:

ControlPersist 4h

  现在你每次通过SSH与服务器建立连接之后,这条连接将被保持4个小时,即使在你退出服务器之后,这条连接依然可以重用,因此,在你下一次(4小时之内)登录服务器时,你会发现连接以闪电般的速度建立完成,这个选项对于通过scp拷贝多个文件提速尤其明显,因为你不在需要为每个文件做单独的认证了。

  3. 别再输入密码

  如果你还在通过密码方式登录SSH,那么你或许应该试试SSH Keys,首先使用OpenSSH为自己声称一对密钥:

$ ssh-keygen

  跟随指示,完成之后,你应该可以在你的.ssh目录下看到两个文件,id_rsa就是你的私钥,而id_ras.pub则是你的公钥,现在你需要将你的公钥拷贝到服务器上,如果你的系统有ssh-copy-id命令,拷贝会很简单:  

$ ssh-copy-id smylers@compo.example.org

  否则,你需要手动将你的私钥拷贝的服务器上的~/.ssh/authorized_keys文件中:

$ < ~/.ssh/id_rsa.pub ssh clegg.example.org ‘mkdir -p .ssh; cat >> .ssh/authorized_keys; chmod go-w .ssh .ssh/authorized_keys’

  现在试试重新连接到SSH服务器,或是拷贝文件,是不是已经不需要再输入密码了?

  相关链接:不输入密码ssh直接登录阿里云Linux主机

  为Putty配置SSH Key

  Putty也可以使用SSH Key,从Putty网站下载PuttyGen和Pageant,然后使用PuttyGen生成你的密钥,将公钥拷贝到服务器的’.ssh/authorized_keys’目录,然后运行Pageant,导入你的私钥,让它在后台运行,险隘你就可以使用Putty通过公钥直接登录服务器了,你可以在Putty手册的第8,9章了解关于这一特性的详细介绍。

  4. 连接中转

  有时候你可能需要从一个服务器连接另外一个服务器,比如在两个服务器之间直接传输数据,而不用通过本地电脑中转:

www1 $ scp -pr templates www2:$PWD

  (顺便说一下,当你需要在两台服务器间拷贝文件时,$PWD变量时非常有用的),因为即使你已经在两台服务器上添加了你本地电脑的公钥,scp默认仍然会提示你输入密码:这是因为你用来作为跳板的那台服务器上并没有你的私钥,所以,第二胎服务器会拒绝你的公钥,但是一定不要通过将你的私钥拷贝到中转服务器上来解决这个问题,你可以使用agent forwarding来解决这个问题,只要在你的.ssh/config文件中加入下面这行代码就可以了:

ForwardAgent yes

  或者是在Putty中勾上Allow agent forwarding选项,现在你的本地SSH就变成了第一台服务器的SSH代理,从第一台服务器在连接其它服务器就变和和在你本地一样简单,注意,如果要开启这个选项,前提是这个中间服务器值得你信任。

  5. 省略主机名

  输入服务器的完整主机名来建立一个新的SSH连接实在是太乏味无聊了,尤其是当你有一组拥有相同域名但是子域名不同的服务器需要管理时,比如下面这样:

  * www1.example.com
  * www2.example.com
  * mail.example.com
  * intranet.internal.example.com
  * backup.internal.example.com
  * dev.internal.example.com

  或许你的网络已经配置了可以直接使用短域名,比如intranet,但是如果你的网络不支持,实际上你可以自己搞定这个问题,而不用求助网络管理员。

  解决办法根据你用的操作系统而略有差异,下面是我的Ubuntu系统的配置:

prepend domain-search internal.example.com, example.com;

  然后你需要重启网络:

$ sudo restart network-manager

  不同的系统,这两条命令可能会略有差异。

  5. 主机别名

  你也可以在你的SSH配置中直接定义主机别名,就像下面这样:

Host dev
HostName dev.internal.example.com

  你还可以使用通配符来进行分组:

Host dev intranet backup
HostName %h.internal.example.com

Host www* mail
HostName %h.example.com

  在Putty中你可以为每个主机名保存单独的session,然后双击建立连接(但是它可能没办法支持通配符)。

  7. 省去用户名

  如果你在远程服务器上的用户名和你本地的用户名不同,你同样可以在SSH配置中进行设置:

Host www* mail
HostName %h.example.com
User simon

  现在就算我的本地用户名是 smylers,我仍然可以这样连接我的服务器:  

$ ssh www2

  SSH会使用simon账户连接你的服务器,同样,Putty可以保存这个信息在你的session中。

  8. 在服务器间跳转

  有些时候,你可能没法直接连接到某台服务器,而需要使用一台中间服务器进行中转,这个过程也可以自动化。首先确保你已经为服务器配置了公钥访问,并开启了agent forwarding,现在你就可以通过2条命令来连接目标服务器,不会有任何提示输入:

$ ssh gateway
gateway $ ssh db

  然后在你的本地SSH配置中,添加下面这条配置:

Host db
HostName db.internal.example.com
ProxyCommand ssh gateway netcat -q 600 %h %p

  现在你就可以通过一条命令来直接连接目标服务器了:

$ ssh db

  这里你可能会需要等待长一点的时间,因为SSH需要进行两次认证,注意netcat也有可能被写成nc或者ncat或者前面还需要加上g,你需要检查你的中间服务器来确定实际的参数。

  9. 突破网络端口限制

  有些时候,你使用的网络可能只开放了80端口,或者它们封锁了SSH端口(默认的22端口),这种情况下,你可以通过配置SSH服务器在80或者443端口进行监听来突破封锁,只需要编辑你的服务器的/etc/ssh/sshd_config文件:

  Port 443

  然后重启SSH服务器:

$ sudo reload ssh

  当然这样做的前提是你的服务器没有使用HTTPS服务,但是实际上你只需要设置一台服务器使用HTTPS端口就够了,你可以访问这台服务器,使用我们前面提到的技术利用它作为跳板来访问其它服务器。但是记住,你需要提前配置好这台服务器,这样万一当你身处一个只能访问Web的网络环境时,就可以省掉打电话让其他人帮你配置中间服务器的麻烦了。

  10. 穿越Web代理

  有些时候,你所在的网络不止封锁SSH端口,它们有可能更进一步,只让你通过Web代理来访问网络,幸运的是我们有一个叫做Corkscrew的程序可以通过Web代理在发送SSH数据。Corkscrew的使用非常简单,一般我都是在需要时搜索,然后直接下载,跟随网站上的指示,然后就搞定了,一般你需要这样一条配置:  

ProxyCommand corkscrew proxy.example.org 8080 %h %p

  11. 远程GUI

  有时候通过本地的GUI程序来访问远程服务器的文件会非常有用,比如,编辑一副图片,或者查看一个PDF文件,或者只是简单的通过一个非命令行的编辑器来修改代码,我发现GVim要比终端里的Vim更有用,因为我可以通过gvimopens打开一个新窗口来编辑文件,而用当前的SSH窗口继续执行其它操作,不要这样做,你需要先在你的SSH配置中开启一个叫做X forwarding的选项:

ForwardX11 yes

  这个选项需要服务器配置才能起作用,服务器也需要开启X forwarding,你可以在服务器的/etc/ssh/sshd_config中添加下面这个命令:  

X11Forwarding yes

  同时你还需要确保安装了xauth,编辑器,图片查看器以及其它的你需要运行的图形化程序,这种方式只有在支持本地X服务器的操作提供才可以工作,Mac和Windows上都有免费的X Server,你可能需要花些时间配置它们,相比之下,切换到Linux相对会更容易一下。

  12. 本地操作远程文件

  另一种让远程GUI程序显示在本地的替代方案就是让本地的GUI程序可以直接操作远程文件,你可以通过SSHFS来实现,只需要创建一个空目录,然后使用SSHFS将一个远程目录mount到这个目录就可以了:

$ mkdir gallery_src
$ sshfs dev:projects/gallery/src gallery_src
$ cd gallery_src
$ ls

  现在你就可以使用任何你喜欢的本地程序来便捷这个目录中的文件了,它们看起来是在你的本地,但其实时远程服务器上的文件,你可以使用fusermount命令来unmount这些文件,不要担心记不住,它们就在sshfs手册的顶上:  

$ cd ..
$ fusermount -u gallery_src

  SSHFS可以在Linux和OSX上工作,Windows用户我目前还没找到什么好办法。

  13. 通过Vim访问远程文件

  Vim有一个内置的功能可以直接编辑远程文件,需要借助SCP URL:

$ gvim scp://dev/projects/gallery/src/templates/search.html.tt

  这中方式明显不如SSHFS灵活,但是如果你只需要对远程服务器的1,2个文件进行编辑时,这条命令就要更灵活一些了,并且可以在Windows上你也可以这样做:  

:help netrw-problems

  14. 使用本地App连接远程服务器

  有时可能有些服务,比如数据库或是Web服务器,它们运行在远程服务器上,但是如果有用方式可以直接从本地程序连接它们,那会非常有用,要做到这一点,你需要用到端口转发(port forwarding),举个例子,如果你的服务器运行Postgres(并且只允许本地访问),那么你就可以在你的SSH配置中加入:

Host db
LocalForward 5433 localhost:5432

  现在当你连接你的SSH服务器时,它会在你本地电脑打开一个5433端口(我随便挑的),并将所有发送到这个端口的数据转发到服务器的5432端口(Postgres的默认端口),然后,只要你和服务器建立了连接,你就可以通过5433端口来访问服务器的Postgres了。

$ ssh db

  现在打开另外一个窗口,你就可以通过下面这条命令在本地连接你的Postgres数据库了:

$ psql -h localhost -p 5443 orders

  如果你想要使用服务器不支持的图形化Postgres客户端时,这条命令会显得尤其有用:

$ pgadmin3 &

  或者你有一个后台的Web服务器,你不希望直接通过Internet访问它,你也可以通过端口转发来访问它:

Host api
LocalForward 8080 localhost:80

  现在连接到服务器:  

$ ssh api

  然后将浏览器指向你选择的端口号:  

$ firefox http://localhost:8080/

  15. 减少延迟

  如果每次连接服务器都意味着你需要等待几十秒而无所事事,那么你或许应该试试在你的SSH配置中加入下面这条:

GSSAPIAuthentication no

  如果这条命令有效的话,你应该通知你的系统管理员让他在服务器上禁用这个选项,这样其他人就不用再分别添加这条配置到它们的本地配置了。

  16. 加速连接

  如果你确保你和某个服务器之间的连接是安全的(比如通过公司内网连接),那么你就可以通过选择arcfourencryption算法来让数据传输更快一些:

Host dev
Ciphers arcfour

  注意这个加速是以牺牲数据的加密性为代价的,所以如果你连接的是位于网上的服务器,千万不要打开这个选项,并且确保你是通过VPN建立的连接。

  开始行动吧!

  以上就是我收集的高效使用SSH的技巧合集了,如果你还有更多技巧想要分享,记得通过Smylers@cpan.org或是通过@Smylers2来和我联系。

  现在就赶紧行动试试通过这些技巧来让你的SSH更有效率吧!

  • ssh_config
    ** man
    *** PATTERNS
    模式(patterns)包含零个或多个非空字符, '*' (匹配零个或多个字符), '?' (匹配至少一个字符).
    例如, 对 ".co.uk" 这组域名下的所有主机指定一组说明, 下面的模式(pattern)能够被使用:

    Host *.co.uk
    

    下面的模式(pattern)能够匹配任何在 192.168.0.[0-9] 网段下的主机:

    Host 192.168.0.?
    

    模式列表(pattern-list)是逗号分隔的模式(pattern)的列表. 模式列表中的模式可能需要在它们前面
    使用感叹号来进行排除. 例如, 允许在一个组织内, 来自任何地方的密钥被使用, 除了来自 "dialup"
    部分, 下面的条目可以被使用(在 authorized_keys):

    from="!*.dialup.example.com,*.example.com"
    
Port 22                           
AddressFamily any
ListenAddress 0.0.0.0
ListenAddress ::
Protocol 2
# Port:sshd服务端口,预设22,也可以开放多个端口
# AddressFamily:使用地址族,any(默认)、inet(仅IPv4)、inet6(仅IPv6)
# ListenAddress:设置监听的地址
# Protocol:SSH协议版本


# HostKey for protocol version 1
HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
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

# 主机私钥存放位置


KeyRegenerationInterval 1h
ServerKeyBits 1024
#对于SSH-1协议中秘钥的过期时间和大小


## Logging
SyslogFacility AUTH
SyslogFacility AUTHPRIV
LogLevel INFO

# SyslogFacility:日志系统选择
# LogLevel:日志等级选择


# Authentication:
LoginGraceTime 2m
PermitRootLogin yes
StrictModes yes
MaxAuthTries 6
MaxSessions 10

# LoginGraceTime:限制认证时限
# PermitRootLogin:允许ROOT账户登录
# StrictModes:检查用户主目录和相关的配置文件
# MaxAuthTries:最大认证次数
# MaxSessions:最大保持连接数


RSAAuthentication yes
PubkeyAuthentication yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
# RSAAuthentication:SSH-1公钥认证
# PubkeyAuthentication:SSH-2公钥认证
# AuthorizedKeysFile:授权秘钥文件

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# RhostsRSAAuthentication and HostbasedAuthentication
IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes

# RhostsRSAAuthentication:SSH-1强可信主机
# HostbasedAuthentication:SSH-2强可信主机
# IgnoreUserKnownHosts:认证过程中忽略用户的 ~/.ssh/known_hosts 文件
# IgnoreRhosts:认证过程中忽略 .rhosts 和 .shosts 文件


# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication yes
PermitEmptyPasswords no
# PasswordAuthentication:使用密码认证
# PermitEmptyPasswords:允许密码为空账户登录


# Change to no to disable s/key passwords
ChallengeResponseAuthentication yes

# ChallengeResponseAuthentication:是否允许质疑-应答(challenge-response)认证


# Kerberos options
KerberosAuthentication no
KerberosOrLocalPasswd yes
KerberosTicketCleanup yes
KerberosGetAFSToken no

# KerberosAuthentication:是否使用Kerberos认证
# KerberosOrLocalPasswd:如果 Kerberos 密码认证失败,那么该密码还将要通过其它的认证机制
# KerberosTicketCleanup:是否在用户退出登录后自动销毁用户的 ticket
# KerberosGetAFSToken:尝试获取一个 AFS token


# GSSAPI options
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
GSSAPIStrictAcceptorCheck yes
# GSSAPIAuthentication:是否允许使用基于 GSSAPI 的用户认证
# GSSAPICleanupCredentials:是否在用户退出登录后自动销毁用户凭证缓存
# GSSAPIStrictAcceptorCheck:是否严格检查GSSAPI的用户认证


# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several
# problems.
UsePAM yes
# UsePAM:是否使用PAM认证登录


AllowAgentForwarding yes
AllowTcpForwarding yes
GatewayPorts no
X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost yes
PermitTTY yes
PrintMotd yes
PrintLastLog yes
TCPKeepAlive yes
UseLogin no
UsePrivilegeSeparation sandbox      # Default for new installations.
PermitUserEnvironment no
Compression delayed
ClientAliveInterval 0
ClientAliveCountMax 3
ShowPatchLevel no
UseDNS yes
PidFile /var/run/sshd.pid
MaxStartups 10:30:100
PermitTunnel no
ChrootDirectory none
VersionAddendum none

# AllowAgentForwarding:是否允许转发ssh-agent
# AllowTcpForwarding:是否允许TCP转发
# GatewayPorts:是否允许远程主机连接本地的转发端口
# X11Forwarding:是否允许进行 X11 转发
# X11DisplayOffset:指定X11 转发的第一个可用的显示区(display)数字
# X11UseLocalhost:是否应当将X11转发服务器绑定到本地loopback地址
# PermitTTY:是否允许pty分配
# PrintMotd:是否在每一次交互式登录时打印 /etc/motd 文件的内容
# PrintLastLog:是否在每一次交互式登录时打印最后一位用户的登录时间
# TCPKeepAlive:是否向客户端发送 TCP keepalive 消息
# UseLogin:是否在交互式会话的登录过程中使用 login
# UsePrivilegeSeparation:是否让 sshd 通过创建非特权子进程处理接入请求的方法来进行权限分离
# PermitUserEnvironment:是否允许 sshd处理environment
# Compression:是否对通信数据进行加密
# ClientAliveInterval:设置一个以秒记的时长,向客户端发送一个”alive”消息,并等候应答
# ClientAliveCountMax:sshd 在未收到任何客户端回应前最多允许发送多少个”alive”消息
# ShowPatchLevel:是否显示ssh的补丁信息
# UseDNS:是否应该对远程主机名进行反向解析
# PidFile:pid文件位置
# MaxStartups: 指定并发未认证的最大数量节点到SSH守护进程
# PermitTunnel:是否允许 tun 设备转发
# ChrootDirectory:指定chroot认证的路径名
# VersionAddendum:连接时指定附加文本

# no default banner path
Banner none
# Banner:将这个指令指定的文件中的内容在用户进行认证前显示给远程用户


# Accept locale-related environment variables
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
# AcceptEnv:指定客户端发送的哪些环境变量将会被传递到会话环境中


# override default of no subsystems
Subsystem sftp  /usr/libexec/openssh/sftp-server
# Subsystem:配置一个外部子系统
`