Contents

ssh 常用连接方式总结

欠了四个周更。先随便更新一个。这三周搞Kali Nethunter的移植,就是余弦口中的“黑客手机”[斜眼],踩了太多坑。写成文章绝壁能把欠的周更补全……

回归正题。说实话关于ssh的高级用法,网上的教程不能更多,不过遗憾的是, 他们理科生 的思维我真的理解不能,比如对于本地转发和远程转发的区别,我每次用到转发都要谷歌一个教程,每次都要看半天,很讨厌的真是。这篇文章想将重点从ssh的各种命令、参数上移开,将视角聚焦在具体的网络环境中,讨论在不同的 恶劣 网络环境中如何轻松自由的使用ssh这一强大的工具连接任意主机。

下面所有的例子中,机器A代表我们小黑客(A for ahahaha),机器B是我们的靶子(B for bazi),我们要从A上搞B机器上(或者B所在网络中)的东西,包括连接B上的一个shell,或者转发B上的一个端口。如果需要网络中转的地方,我会用机器P表示(P for proxy)。

端口转发是ssh的一个很强大的功能,在我们干坏事时候也必不可少,比如Bazi上面有一个绑定在 127.0.0.1:3306 端口上面的MySQL数据库。127.0.0.1只能在Bazi本地访问,我们想用工具扫描它,是把我们的黑阔小工具传到Bazi上运行呢?还是把这个端口转发到我们的机器A上用我们的小工具攻击它呢?转发的用处不言而喻。

双向可连接的网络穿透

双向可连接的意思,就是 A 和 B 两方都可以互相发起tcp连接(这里不讨论正向连接反向连接的概念)。下面这些情况都可以从任一方发起ssh连接。

  • A和B可以互相ping的到(都拥有公网IP或处于同一局域网内,且中间 没有防火墙
  • A和B虽然在有可能在路由器后面ping不到,但是路由器好心把机器的端口转发出来了。(中间经过NAT,但存在 两个以上 端口可访问)

这两种情况都有限制条件, (所以理想网络环境很少嘛所以才需要这篇教程嘛哈哈哈) 情景2需要两个路由器转发的端口是因为,除了我们需要端口转发出来用的端口,sshd监听ssh连接也要一个单独的端口。当然,如果不想做转发,只想连接个shell,那确实一个端口就够了。一个端口都没有的话,还连个毛线!

这两种网络情况对我们来说最好的,因为我们用这篇文章中的任何方法都可以随意连接两台机器。我们先说最简单的连接方法,连接shell永远是 ssh hostB 不说了。下面只聊端口转发

转发整个网段

对我们来讲权限最大的方式,也是最理想情况下能用的方式,就是在B上打开一个网络代理(ssh中叫 动态转发 dynamic port forwarding ),这种方式下 A 可以以 B 在网络中的视角访问 B 网络中所有的机器,即实现网络穿透的作用, 而不用一个机器一个端口点对点的转发, 极大提高攻击效率

下面这条命令将在Bazi的1080端口打开一个 socks 代理(同时支持socks4、socks5)。如果中途有NAT,这个1080端口就是路由器需要转发的第二个端口,因为我们要连接它嘛。

ssh -D 1080 hostB

如果我们要用什么羞羞的小工具,在小工具里面设置hostB:1080为代理服务器就好啦~

转发一个端口

在 hostA 上进行连接(本地转发,转发到本地),即可绑定 hostA:6666 到 hostB 上的 localhost:3306

ssh -L 6666:localhost:3306 hostB

HostB 上进行连接(远程转发,转发到远端),同样效果。如果我们拿到了webshell,但是没有B的ssh密码的话,这个蛮好用。下面也会提到,A想要B的东西却要B连A,这就叫_反向连接_。

ssh -R 6666:localhost:3306 hostA

上面两个命令只需要ssh端口可以访问就可以,不需要第二个端口。

只允许单向连接的网络

单向连接的情景为:

  • A或者B在路由器后面(经过NAT),而且没有好心人做端口转发
  • 防火墙(如iptables规则或云服务商的安全策略)禁止了传入连接

这种情况下是决计用不得动态转发了。现在一般情况下,是我们的B被好好的被防火墙保护着。这种情况下,我们就假设我们已经拿到了webshell或者奇技淫巧能运行命令。嗯我们当然在有权限之后才能干别的事情嘛……

连hostB的localhost我们已经试过了,我们想干别的了。现在我们在hostB的命令行历史里面发现它连过内网里面的hostSB.local,运行远程命令echo一下,可以连接的哟。现在我们想把hostSB也转发过来,毕竟webshell不是交互式的嘛。我们可以这样。

ssh -R 6666:hostsb.local:22 hostA

这样,连接hostA:6666就等效于hostSB:22了。同理,如果我们只能从A连接B的话,参考上面的方法用 ssh -L 转发到本地就行。

我是小黑客!谁也连不了我

人心不古世态炎凉,万一我暴露了,网络中心查我水表怎么办?所以,当我们

  • 通过代理或VPN连接互联网,无法接受传入连接
  • hostA和hostB都在NAT后面,两台机器二脸蒙逼

我们学校就是这样,虽然大家都能连上Wi-Fi,但是client互相之间的连接被防火墙主动drop掉,只有广播勉强能收到。不过通过校内的其它机器做跳板,就能连上,这时候就需要使用代理啦。

通过代理服务器

通过代理连接的方式实质上不属于ssh的功能,需要用到另一个程序netcat来转发流量。下面的命令使我们的连接通过socks5代理hostP去连接hostB

ssh -o ProxyComand='nc -x hostP:1080 %h %p' hostB

nc的代理连接方式支持http connect(加入参数 nc -X connect)、socks4(nc -X4)或socks5(不加参数如上或加 nc -X5

通过有ssh的跳板机

这个情况就等效于,hostP可以同时从 hostA 与 hostB 单向连接,这样的话,只需要用hostB连接hostP,把自己的ssh端口转发到远程比如hostP:6666,然后再回过头来用hostA连接它,-R转发到hostA:2333,或者直接让hostA去连接hostP:6666即可。

高级用法&注意事项

后台转发,偷偷的

ssh -f 可以让ssh进程fork到后台,这样不妨碍我们继续打印shell。 ssh -N 不打开shell,只转发

基于SSH的VPN

man ssh 中的 “SSH-BASED VIRTUAL PRIVATE NETWORKS” 部分。 (我没看) 需要root权限。可以做路由转发。不用开代理,只需要一个端口,可以过NAT。好用爆炸。

被转发域名解析问题

在上文中,我们用 ssh -Rssh -L 分别转发了 localhost 和 hostsb.local 。这里其实有一个小问题。 hostB运行 ssh -R 6666:hostsb.local:22 hostA 转发到远程时,是在hostB上,即在 运行ssh命令的本地主机 将hostsb.local转换为hostSB的IP的!如果向上面一样反过来,在hostA上运行 ssh -L 6666:hostsb.local:22 hostB ,hostA不在hostB的网络里毋庸置疑,它不知道hostsb.local是啥,因此,使用 ssh -L 转发到本地时,是在 接受ssh连接的远程主机 上进行被转发域名的解析!在某些环境中,这将产生非常大的区别。如果hostB环境部署有IDS和蜜罐,而我们想把它作为跳板机攻击其它网络,他们解析的域名可能把我们拉到陷阱里,然后呵呵呵呵呵。

开启转发的配置问题

在ssh连接中转发端口的那一端,在系统的 /etc/ssh/sshd_config 中必须允许端口的转发。否则会报错 Administrative prohibited。默认是 any,全部允许。

PermitOpen any
PermitOpen host:port
PermitOpen IPv4_addr:port
PermitOpen [IPv6_addr]:port
PermitOpen none

在绑定端口的那一端的 sshd_config 中,可以设置是否允许修改绑定端口所监听的interface,设置为 no 时,只能绑定到localhost上,设置为 yes 时,强制绑定到所有网卡的指定端口上(绑定到0.0.0.0 wildcard address),设置为 clientspecified 时,使用 ssh -L [bind_address:]port:host:hostport-R 时,那个可选的 bind_address 参数指定绑定到哪个IP上。不举例子了,具体参见 ssh 的 manpage。简而言之,如果需要做端口转发的中转,类似上文的最后一种情况,最好不设成no。

GatewayPorts no

而其他 (特别是中文文章艹!) 文章里喜欢说的 PermitTunnel 参数,实际上是为了允许上文所说的 ssh-based vpn 所准备的。