.
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Natter 使用指南
2 |
3 | 本项目旨在帮助大家应用 [Natter v0.9](https://github.com/MikeWang000000/Natter/tree/v0.9) ,在 **Full Cone NAT** 网络环境下打开 TCP 端口,获得在 IPv4 可连接的端口,并提供一些Hook的模板。
4 |
5 |
6 | Natter 官方交流群组:Q 657590400 | TG
7 |
8 |
9 | ## Natter 基本使用
10 |
11 | ### 前提条件
12 |
13 | 1. 网络环境 NAT 为 **Full Cone NAT**,又称 NAT1。
14 |
15 | 以下家庭网络环境很有可能是 NAT1 ,例如:
16 |
17 | * 使用光猫拨号,但拥有光猫控制权,能够设置DMZ。
18 |
19 | * 光猫为桥接模式,使用路由拨号,拥有路由控制权。
20 |
21 | 处于以上环境时,使用 [NatTypeTester](https://github.com/HMBSbige/NatTypeTester) 进行 NAT 检测,结果为下图便可以继续后续步骤。
22 |
23 | 2. 运营商没有配置防火墙
24 |
25 | 一般我们无法感知,有条件的用户可以使用 `nmap` 在外部网络对出口IP进行 TCP 全端口扫描,期望结果是不为全部关闭。
26 |
27 | ### 使用教程
28 |
29 | PS:由于我的路由限制,暂时只讲解在路由下挂设备上运行 Natter 。
30 |
31 | #### 在路由下挂设备上运行
32 |
33 | 
34 |
35 | 本例讲解光猫桥接,且在 NAS 上运行 Natter 。
36 |
37 | 1. 在准备运行 Natter 的设备上下载源码
38 | ```shell
39 | # 下载源码
40 | git clone https://github.com/MikeWang000000/Natter.git
41 | # 进入Natter目录
42 | cd Natter/
43 | # 切换到v0.9版本
44 | git checkout v0.9
45 | ```
46 |
47 | 2. 编辑配置文件
48 |
49 | 复制 `natter-config.template.json` 并重命名为 `config.json`,根据注释填写配置,参考 `config.template.json`。PS:json 不支持注释,请不要在配置文件中添加注释。
50 |
51 | 这里我们采用仅打洞方式,手动设置端口转发。如:在 "open_port" -> "tcp" 中添加 "0.0.0.0:50000"。
52 | ```
53 | {
54 | "logging": {
55 | "level": "info", // 日志等级:可选值:"debug"、"info"、"warning"、"error"
56 | "log_file": "./natter.log" // 日志文件路径,不需要日志则置空:""
57 | },
58 | "status_report": {
59 | "hook": "bash ./natter-hook.sh '{protocol}' '{inner_ip} ' '{inner_port} ' '{outer_ip}' '{outer_port}'", // Hook文件路径
60 | "status_file": "./natter-status.json" // 实时端口映射状态储存至指定文件,不 需要则置空:""
61 | },
62 | "open_port": {
63 | // 此处设置 Natter 打洞IP:端口。(仅打洞)
64 | // 此处地址为 Natter 绑定(监听)的地址,Natter 仅对这些地址打洞,您需要手动 设置端口转发。
65 | // 注意:使用默认出口IP,请使用 0.0.0.0 ,而不是 127.0.0.1 。
66 | "tcp": [
67 | "0.0.0.0:50000"
68 | ],
69 | "udp": [
70 | ]
71 | },
72 | "forward_port": {
73 | // 此处设置需要 Natter 开放至公网的 IP:端口。(打洞 + 内置转发)
74 | // Natter 会全自动打洞、转发,您无需做任何干预。
75 | // 注意:使用本机IP,请使用 127.0.0.1,而不是 0.0.0.0 。
76 | // 注意:我们采用仅打洞方式,不使用内置转发,清空所有规则
77 | "tcp": [
78 | ],
79 | "udp": [
80 | ]
81 | },
82 | "stun_server": {
83 | // 此处设置公共 STUN 服务器。
84 | // TCP 服务器请确保 TCP/3478 端口开放可用;
85 | // UDP 服务器请确保 UDP/3478 端口开放可用。
86 | // 一般无需改动
87 | "tcp": [
88 | "fwa.lifesizecloud.com",
89 | "stun.isp.net.au",
90 | "stun.freeswitch.org",
91 | "stun.voip.blackberry.com",
92 | "stun.nextcloud.com",
93 | "stun.stunprotocol.org",
94 | "stun.sipnet.com",
95 | "stun.radiojar.com",
96 | "stun.sonetel.com",
97 | "stun.voipgate.com"
98 | ],
99 | "udp": [
100 | "stun.miwifi.com",
101 | "stun.qq.com"
102 | ]
103 | },
104 | // 此处设置 HTTP Keep-Alive 服务器。请确保该服务器 80 端口开放,且支持 HTTP Keep-Alive。
105 | "keep_alive": "www.qq.com"
106 | }
107 | ```
108 |
109 | 3. 运行 Natter
110 |
111 | 配置完成后的目录结构:
112 | ```
113 | .
114 | ├── config.json
115 | ├── natter-hook.sh
116 | └── natter.py
117 | ```
118 |
119 | 由于 STUN 特性,需要后台运行以保持长连接,这里建议使用 `screen` 来运行 Natter ,且可以随时切回。
120 |
121 | ```shell
122 | # 新建screen,名为nat
123 | screen -S nat
124 |
125 | # 运行脚本
126 | python natter.py -c ./config.json
127 |
128 | # 离开screen
129 | 按 Ctrl + A 再按 Ctrl + D
130 |
131 | # 回到screen
132 | screen -r nat
133 | ```
134 | 运行成功后会有以下打印
135 | ```
136 | [INFO] - >>> [TCP] ('192.168.1.100', 50000) -> ('61.157.1.123', 46087) <<<
137 | [Script] - Upload to server: tcp: 192.168.1.100:50000 -> 61.157.1.123:46087
138 | ```
139 | 至此,我们完成了内网 `192.168.1.100:50000` 到外网 `61.157.1.123:46087` 的 TCP 打洞,接下来需要在路由中设置端口转发把 `50000` 转发到目标的端口上。
140 |
141 | 4. 修改端口转发
142 |
143 | 进入路由器后台,防火墙->端口转发->新建规则,进行如下设置:
144 | ```
145 | 来源:WAN
146 | 来源端口:50000
147 | 目标:LAN
148 | 目标地址:内网设备IP地址
149 | 目标端口:内网设备提供服务的端口
150 | ```
151 |
152 | 5. 验证
153 |
154 | 建议将目标指向到web服务,方便访问以检测打通是否成功,如:qBittorrent web等。
155 |
156 | #### 在路由上运行
157 |
158 | *待补充*
159 |
160 | ## 高级用法
161 |
162 | [Natter v0.9](https://github.com/MikeWang000000/Natter/tree/v0.9) 支持了Hook调用,即在打洞成功后执行脚本。
163 |
164 | 利用这一点,我们可以在打洞成功后自动登录到路由器并设置端口转发,实现一些自动化功能,例如:自动设置端口转发、自动修改 qBittorrent 传输端口、配置消息推送等。
165 |
166 | 以下提供一些使用模板,仅建议愿意折腾的小伙伴使用,欢迎大家PR!
167 |
168 | * [自动设置端口转发](https://github.com/1368129224/Natter-User-Guide/blob/main/template/auto_forward/auto_forward.md)
169 |
170 | 适用于具有 [UCI](https://openwrt.org/zh/docs/guide-user/base-system/uci) 系统的 OpenWRT 路由器,自动设置端口转发。
171 |
172 | * [自动设置 qBittorrent 传输端口](https://github.com/1368129224/Natter-User-Guide/blob/main/template/qBittorrent/qBittorrent.md)
173 |
174 | 自动修改 qBittorrent 传输端口,提高连通性。
175 |
176 | * [使用 message-pusher 进行推送消息](https://github.com/1368129224/Natter-User-Guide/blob/main/template/push/push.md)
177 |
178 | 使用 [message-pusher](https://github.com/songquanpeng/message-pusher) 在网络环境改变时进行消息推送。
179 |
180 | ## Thanks
181 |
182 | * [Natter](https://github.com/MikeWang000000/Natter)
183 | * [NatTypeTester](https://github.com/HMBSbige/NatTypeTester)
184 |
--------------------------------------------------------------------------------
/config.template.json:
--------------------------------------------------------------------------------
1 | {
2 | "logging": {
3 | "level": "info",
4 | "log_file": "./natter.log"
5 | },
6 | "status_report": {
7 | "hook": "bash ./natter-hook.sh '{protocol}' '{inner_ip}' '{inner_port}' '{outer_ip}' '{outer_port}'",
8 | "status_file": "./natter-status.json"
9 | },
10 | "open_port": {
11 | "tcp": [
12 | "0.0.0.0:50000"
13 | ],
14 | "udp": [
15 | ]
16 | },
17 | "forward_port": {
18 | "tcp": [
19 | ],
20 | "udp": [
21 | ]
22 | },
23 | "stun_server": {
24 | "tcp": [
25 | "fwa.lifesizecloud.com",
26 | "stun.isp.net.au",
27 | "stun.freeswitch.org",
28 | "stun.voip.blackberry.com",
29 | "stun.nextcloud.com",
30 | "stun.stunprotocol.org",
31 | "stun.sipnet.com",
32 | "stun.radiojar.com",
33 | "stun.sonetel.com",
34 | "stun.voipgate.com"
35 | ],
36 | "udp": [
37 | "stun.miwifi.com",
38 | "stun.qq.com"
39 | ]
40 | },
41 | "keep_alive": "www.qq.com"
42 | }
43 |
--------------------------------------------------------------------------------
/img/network.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/1368129224/Natter-User-Guide/397bf58c7c8ceaebea6b39fae9d1050771a50d2b/img/network.jpg
--------------------------------------------------------------------------------
/img/push1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/1368129224/Natter-User-Guide/397bf58c7c8ceaebea6b39fae9d1050771a50d2b/img/push1.png
--------------------------------------------------------------------------------
/img/push2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/1368129224/Natter-User-Guide/397bf58c7c8ceaebea6b39fae9d1050771a50d2b/img/push2.png
--------------------------------------------------------------------------------
/img/push3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/1368129224/Natter-User-Guide/397bf58c7c8ceaebea6b39fae9d1050771a50d2b/img/push3.png
--------------------------------------------------------------------------------
/template/auto_forward/auto_forward.md:
--------------------------------------------------------------------------------
1 | # 自动设置端口转发
2 |
3 | ## 准备
4 |
5 | 登录路由后台,执行 `uci` 命令,有如下打印则具有 [UCI](https://openwrt.org/zh/docs/guide-user/base-system/uci) 系统。
6 |
7 | ```shell
8 | root@ImmortalWrt:~# uci
9 | Usage: uci [] []
10 | ```
11 |
12 | ## 配置
13 |
14 | 1. 配置私钥登录 openwrt 路由器
15 |
16 | 在运行 Natter 的机器上生成密钥对
17 | ```shell
18 | user@ubuntu:~# ssh-keygen
19 | Generating public/private rsa key pair.
20 | Enter file in which to save the key (/home/user/.ssh/id_rsa):
21 | Enter passphrase (empty for no passphrase):
22 | Enter same passphrase again:
23 | Your identification has been saved in /home/user/.ssh/id_rsa.
24 | Your public key has been saved in /home/user/.ssh/id_rsa.pub.
25 | The key fingerprint is:
26 | 51:2d:88:4b:05:f2:80:76:30:25:68:24:d2:e0:75:2f user@ubuntu
27 | The key's randomart image is:
28 | +--[ RSA 2048]----+
29 | |==+=+..+.... |
30 | |=.=oo++ ... . |
31 | |.o . E.o. . |
32 | | o . |
33 | | S |
34 | | |
35 | | |
36 | | |
37 | | |
38 | +-----------------+
39 | root@ubuntu:~/.ssh$ ls
40 | authorized_keys id_rsa id_rsa.pub known_hosts
41 | ```
42 |
43 | 将公钥 `id_rsa.pub` 内容拷贝到 OpenWRT 的 `/etc/dropbear/authorized_keys` 。
44 |
45 | 配置ssh,将以下内容添加到 `~/.ssh/config` 中,如果没有就新创建。
46 | ```
47 | Host openwrt
48 | HostName 192.168.1.1
49 | IdentityFile ~/.ssh/id_rsa
50 | User root
51 | ```
52 |
53 | 保存后即可使用 `ssh openwrt` 免密登录 OpenWRT 后台。
54 |
55 | 2. 创建端口转发规则
56 |
57 | 可以通过路由器Web后台创建规则,也可以通过登录到 OpenWRT 后台使用 UCI 系统创建规则。
58 |
59 | ```shell
60 | uci add firewall redirect
61 | uci set firewall.@redirect[-1].dest='lan'
62 | uci set firewall.@redirect[-1].target='DNAT'
63 | uci set firewall.@redirect[-1].name='ttyd' //按你的需求填写
64 | uci set firewall.@redirect[-1].src='wan'
65 | uci set firewall.@redirect[-1].src_dport='51000' //可任意填写
66 | uci set firewall.@redirect[-1].dest_ip='192.168.1.100' //可任意填写
67 | uci set firewall.@redirect[-1].dest_port='7681' //可任意填写
68 | uci commit firewall
69 | /etc/init.d/firewall restart
70 | ```
71 |
72 | PS: 经测试,`ImmortalWrt 21.02.5` 不需要执行 `/etc/init.d/firewall restart` 即可生效,建议初次配置时手动测试。
73 |
74 | **注意**:创建好规则后,请记住规则的ID,后面将会用到。
75 |
76 | 可以通过 `uci show firewall.@redirect[id]` 确定规则ID,也可以通过Web后台查看,从上到下ID从0递增。
77 |
78 | 3. 编辑Hook
79 |
80 | 参考 `auto_forward.template.sh` 修改你的Hook,规则ID即上一步中新创建的规则的ID。
81 |
82 | ```shell
83 | # 对应的规则ID
84 | rule_id="0"
85 | # 目标端口,内网设备提供服务的端口
86 | target_port=""
87 |
88 | echo "Update openwrt firewall..."
89 |
90 | ssh openwrt "uci set firewall.@redirect[$rule_id].dest_port=$target_port;uci set firewall.@redirect[$rule_id].src_dport=$inner_port;uci commit firewall;uci show firewall.@redirect[$rule_id];/etc/init.d/firewall restart;exit"
91 | ```
92 |
93 | PS: 经测试,`ImmortalWrt 21.02.5` 不需要执行 `/etc/init.d/firewall restart` 即可生效,填写Hook时根据实际情况增减restart步骤。
94 |
--------------------------------------------------------------------------------
/template/auto_forward/auto_forward.template.sh:
--------------------------------------------------------------------------------
1 | # 对应的规则ID
2 | rule_id="0"
3 | # 目标端口,内网设备提供服务的端口
4 | target_port=""
5 |
6 | echo "Update openwrt firewall..."
7 |
8 | ssh openwrt "uci set firewall.@redirect[$rule_id].dest_port=$target_port;uci set firewall.@redirect[$rule_id].src_dport=$inner_port;uci commit firewall;uci show firewall.@redirect[$rule_id];/etc/init.d/firewall restart;exit"
9 |
--------------------------------------------------------------------------------
/template/push/push.md:
--------------------------------------------------------------------------------
1 | # 配置消息推送
2 |
3 | [message-pusher](https://github.com/songquanpeng/message-pusher) 是一个消息推送服务,目前官方服务免费公开使用,支持多种推送方式:
4 | > * 邮件消息,
5 | > * 微信测试号,
6 | > * 企业微信应用号,
7 | > * 企业微信群机器人
8 | > * 飞书群机器人,
9 | > * 钉钉群机器人,
10 | > * Bark App,
11 | > * WebSocket 客户端(官方客户端,接入文档),
12 | > * Telegram 机器人,
13 | > * Discord 群机器人,
14 |
15 | 官方服务站:https://msgpusher.com/
16 |
17 | > 为什么不使用 `Server酱`?
18 | >
19 | > Server酱每天只有5条免费推送额度,如果运营商网络频繁变动,免费额度不满足使用。
20 |
21 | ## 准备
22 |
23 | 1. 打开官方服务站,并注册账号,进入推送设置。
24 | 
25 | 2. 根据需要和帮助信息配置需要的推送方式,并修改默认推送方式。这里我配置的是tg推送,并将默认推送方式改为tg。
26 | 
27 | 
28 | PS:如果设置了 推送token ,请记下来,后续推送时需要配置。
29 |
30 | ## 配置
31 |
32 | 参考 `push.template.sh` 修改你的Hook。
33 | 1. 替换用户名和推送token。
34 | 2. 根据需求选择推送函数,如:`send_message` 向默认频道发送消息。
35 | 3. 根据需求更改'title' 'description' 'content'。
36 |
37 | ```shell
38 | MESSAGE_PUSHER_SERVER="https://msgpusher.com"
39 | MESSAGE_PUSHER_USERNAME="your username"
40 | MESSAGE_PUSHER_TOKEN="your token"
41 |
42 | function send_message {
43 | # 向默认频道发送消息
44 | curl -s -X POST "$MESSAGE_PUSHER_SERVER/push/$MESSAGE_PUSHER_USERNAME" \
45 | -d "title=$1&description=$2&content=$3&token=$MESSAGE_PUSHER_TOKEN" \
46 | >/dev/null
47 | }
48 |
49 | function send_message_email {
50 | # 向邮箱发送消息
51 | curl -s -X POST "$MESSAGE_PUSHER_SERVER/push/$MESSAGE_PUSHER_USERNAME" \
52 | -d "title=$1&description=$2&content=$3&token=$MESSAGE_PUSHER_TOKEN&channel=email" \
53 | >/dev/null
54 | }
55 |
56 | function send_message_with_json {
57 | # 发送JSON格式的消息
58 | curl -s -X POST "$MESSAGE_PUSHER_SERVER/push/$MESSAGE_PUSHER_USERNAME" \
59 | -H 'Content-Type: application/json' \
60 | -d '{"title":"'"$1"'","desp":"'"$2"'", "content":"'"$3"'", "token":"'"$MESSAGE_PUSHER_TOKEN"'"}' \
61 | >/dev/null
62 | }
63 |
64 | send_message 'title' 'description' 'content'
65 | ```
--------------------------------------------------------------------------------
/template/push/push.template.sh:
--------------------------------------------------------------------------------
1 | MESSAGE_PUSHER_SERVER="https://msgpusher.com"
2 | MESSAGE_PUSHER_USERNAME="your username"
3 | MESSAGE_PUSHER_TOKEN="your token"
4 |
5 | function send_message {
6 | # 向默认频道发送消息
7 | curl -s -X POST "$MESSAGE_PUSHER_SERVER/push/$MESSAGE_PUSHER_USERNAME" \
8 | -d "title=$1&description=$2&content=$3&token=$MESSAGE_PUSHER_TOKEN" \
9 | >/dev/null
10 | }
11 |
12 | function send_message_email {
13 | # 向邮箱发送消息
14 | curl -s -X POST "$MESSAGE_PUSHER_SERVER/push/$MESSAGE_PUSHER_USERNAME" \
15 | -d "title=$1&description=$2&content=$3&token=$MESSAGE_PUSHER_TOKEN&channel=email" \
16 | >/dev/null
17 | }
18 |
19 | function send_message_with_json {
20 | # 发送JSON格式的消息
21 | curl -s -X POST "$MESSAGE_PUSHER_SERVER/push/$MESSAGE_PUSHER_USERNAME" \
22 | -H 'Content-Type: application/json' \
23 | -d '{"title":"'"$1"'","desp":"'"$2"'", "content":"'"$3"'", "token":"'"$MESSAGE_PUSHER_TOKEN"'"}' \
24 | >/dev/null
25 | }
26 |
27 | send_message 'title' 'description' 'content'
28 |
--------------------------------------------------------------------------------
/template/qBittorrent/qBittorrent.md:
--------------------------------------------------------------------------------
1 | # 自动设置qBittorrent传输端口
2 |
3 | ## 配置
4 |
5 | 1. 测试能否或正常登录
6 |
7 | 在运行 Natter 的设备上执行 `curl --insecure -s -i --header "Referer: https://localhost:8080" --data "username=admin&password=adminadmin" https://localhost:8080/api/v2/auth/login | grep -i set-cookie | cut -c13-48`(IP、账号及密码请自行替换),检查能否打印 `SID=6oavHb8b4MtL6PZvVqDpd9vb9eeedryh` 类似的token,如果不行则登陆失败,请自行排除问题。
8 |
9 | 2. 编辑Hook
10 |
11 | 参考 `qBittorrent.template.sh` 修改你的Hook,这里搭配自动修改端口转发使用,**注意**:qBittorrent传输需要内外端口一致 `target_port=$outter_port`。
12 |
13 | ```shell
14 | # 配置qBittorrent,注意是http还是https
15 | qb_web_url="https://192.168.1.100:18080"
16 | qb_username="admin"
17 | qb_password="adminadmin"
18 |
19 | # 这里搭配自动修改端口转发的Hook,qBittorrent传输需要内外端口一致
20 | target_port=$outter_port
21 |
22 | echo "Update qBittorrent listen port to $outter_port..."
23 |
24 | qb_cookie=$(curl --insecure -s -i --header "Referer: $qb_web_url" --data "username=$qb_username&password=$qb_password" $qb_web_url/api/v2/ auth/login | grep -i set-cookie | cut -c13-48)
25 | curl --insecure -X POST -b "$qb_cookie" -d 'json={"listen_port":"'$outter_port'"}' "$qb_web_url/api/v2/app/setPreferences"
26 | ```
27 |
--------------------------------------------------------------------------------
/template/qBittorrent/qBittorrent.template.sh:
--------------------------------------------------------------------------------
1 | # 配置qBittorrent,注意是http还是https
2 | qb_web_url="https://192.168.1.100:18080"
3 | qb_username="admin"
4 | qb_password="adminadmin"
5 |
6 | # 这里搭配自动修改端口转发的Hook,qBittorrent传输需要内外端口一致
7 | target_port=$outter_port
8 |
9 | echo "Update qBittorrent listen port to $outter_port..."
10 |
11 | qb_cookie=$(curl --insecure -s -i --header "Referer: $qb_web_url" --data "username=$qb_username&password=$qb_password" $qb_web_url/api/v2/auth/login | grep -i set-cookie | cut -c13-48)
12 | curl --insecure -X POST -b "$qb_cookie" -d 'json={"listen_port":"'$outter_port'"}' "$qb_web_url/api/v2/app/setPreferences"
--------------------------------------------------------------------------------