Skip to content

Instantly share code, notes, and snippets.

@veltlion
Last active March 31, 2024 05:05
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save veltlion/b59d73654f0ae36725f5a571602729cb to your computer and use it in GitHub Desktop.
Save veltlion/b59d73654f0ae36725f5a571602729cb to your computer and use it in GitHub Desktop.
Natter/NATMap 打洞后自动更新 qBittorrent/Transmission 监听端口和 OpenWrt 防火墙规则/iptables 规则 并推送到 Telegram
#!/bin/sh
# Natter
protocol=$1
inner_ip=$2
inner_port=$3
outter_ip=$4
outter_port=$5
# ipv4hex=$(printf '%02x' ${outter_ip//./ })
# ip4p="2001::$(printf '%2x' ${outter_port}):${ipv4hex:0:4}:${ipv4hex:4}"
# # NATMap
# protocol=$5
# inner_ip=$6
# inner_port=$4
# outter_ip=$1
# outter_port=$2
# ip4p=$3
# echo "[Script] - Upload to server: ${protocol}: ${inner_ip}:${inner_port} -> ${outter_ip}:${outter_port}"
# Write your upload script below...
logger -t "Natter" "Upload to server: ${protocol}: ${inner_ip}:${inner_port} -> ${outter_ip}:${outter_port}"
case ${inner_port} in
# qBittorrent
8089)
qbv4="10.0.0.6"
qbv6="::1eaf/::ffff:ffff:ffff:ffff"
qbwebport="9080"
qbusername=""
qbpassword=""
if type uci >/dev/null 2>&1; then
# OpenWrt Firewall
# ipv6 allow
uci set firewall.allowqbv6_${inner_port}=rule
uci set firewall.allowqbv6_${inner_port}.name="Allow-qBittorrent-${inner_port}"
uci set firewall.allowqbv6_${inner_port}.src='wan'
uci set firewall.allowqbv6_${inner_port}.dest='lan'
uci set firewall.allowqbv6_${inner_port}.target='ACCEPT'
uci set firewall.allowqbv6_${inner_port}.dest_ip="${qbv6}"
uci set firewall.allowqbv6_${inner_port}.family='ipv6'
uci set firewall.allowqbv6_${inner_port}.dest_port="${outter_port}"
# ipv4 redirect
uci set firewall.redirectqbv4_${inner_port}=redirect
uci set firewall.redirectqbv4_${inner_port}.name="Redirect-qBittorrent-${inner_port}"
uci set firewall.redirectqbv4_${inner_port}.proto="${protocol}"
uci set firewall.redirectqbv4_${inner_port}.src='wan'
uci set firewall.redirectqbv4_${inner_port}.dest='lan'
uci set firewall.redirectqbv4_${inner_port}.target='DNAT'
uci set firewall.redirectqbv4_${inner_port}.src_dip="${inner_ip}"
uci set firewall.redirectqbv4_${inner_port}.src_dport="${inner_port}"
uci set firewall.redirectqbv4_${inner_port}.dest_ip="${qbv4}"
uci set firewall.redirectqbv4_${inner_port}.dest_port="${outter_port}"
# reload
uci commit firewall
/etc/init.d/firewall reload
sleep 3
else
# iptables
# ipv4
# delete old v4rules
iptables -t nat -D PREROUTING -j redirectqbv4-$inner_port
iptables -t nat -F redirectqbv4-$inner_port
iptables -t nat -X redirectqbv4-$inner_port
# add v4rule
iptables -t nat -N redirectqbv4-$inner_port
iptables -t nat -A redirectqbv4-$inner_port -p $protocol -d $inner_ip --dport $inner_port -j DNAT --to-destination $qbv4:$outter_port
iptables -t nat -I PREROUTING -j redirectqbv4-$inner_port
# ipv6
qbv6ipt=$(echo $qbv6|sed 's/ /,/g')
# delete old v6rules
ip6tables -D FORWARD -j allowqbv6-$inner_port
ip6tables -F allowqbv6-$inner_port
ip6tables -X allowqbv6-$inner_port
# add v6rule
ip6tables -N allowqbv6-$inner_port
ip6tables -A allowqbv6-$inner_port -p tcp -d $qbv6ipt --dport $outter_port -j ACCEPT
ip6tables -A allowqbv6-$inner_port -p udp -d $qbv6ipt --dport $outter_port -j ACCEPT
ip6tables -I FORWARD -j allowqbv6-$inner_port
fi
# update port
date=$(date +%s); echo $date > /tmp/natter${inner_port}
while true; do
[[ $(cat /tmp/natter$inner_port) != $date ]] && exit 0
tcping -c1 -p${qbwebport} ${qbv4} >/dev/null
if [ $? -eq 0 ]; then
qbcookie=$(\
curl -Ssi -X POST \
-d "username=${qbusername}&password=${qbpassword}" \
"http://${qbv4}:${qbwebport}/api/v2/auth/login" | \
sed -n 's/.*\(SID=.\{32\}\);.*/\1/p' )
curl -X POST \
-b "${qbcookie}" \
-d 'json={"listen_port":"'${outter_port}'"}' \
"http://${qbv4}:${qbwebport}/api/v2/app/setPreferences"
text="[Natter] qBittorrent TCP Port:\n$outter_ip:$outter_port -> $inner_ip:$inner_port -> $qbv4:$outter_port"
break
fi
sleep 3
done
;;
# Transmission
8091)
trv4="10.0.0.6"
trv6="::fc71:5d8b:28c4:1805/::ffff:ffff:ffff:ffff ::1eaf/::ffff:ffff:ffff:ffff"
trwebport="9091"
trusername=""
trpassword=""
if type uci >/dev/null 2>&1; then
# OpenWrt Firewall
# ipv6 allow
uci set firewall.allowtrv6_${inner_port}=rule
uci set firewall.allowtrv6_${inner_port}.name="Allow-Transmission-${inner_port}"
uci set firewall.allowtrv6_${inner_port}.src='wan'
uci set firewall.allowtrv6_${inner_port}.dest='lan'
uci set firewall.allowtrv6_${inner_port}.target='ACCEPT'
uci set firewall.allowtrv6_${inner_port}.dest_ip="${trv6}"
uci set firewall.allowtrv6_${inner_port}.family='ipv6'
uci set firewall.allowtrv6_${inner_port}.dest_port="${outter_port}"
# ipv4 redirect
uci set firewall.redirecttrv4_${inner_port}=redirect
uci set firewall.redirecttrv4_${inner_port}.name="Redirect-Transmission-${inner_port}"
uci set firewall.redirecttrv4_${inner_port}.proto="${protocol}"
uci set firewall.redirecttrv4_${inner_port}.src='wan'
uci set firewall.redirecttrv4_${inner_port}.dest='lan'
uci set firewall.redirecttrv4_${inner_port}.target='DNAT'
uci set firewall.redirecttrv4_${inner_port}.src_dip="${inner_ip}"
uci set firewall.redirecttrv4_${inner_port}.src_dport="${inner_port}"
uci set firewall.redirecttrv4_${inner_port}.dest_ip="${trv4}"
uci set firewall.redirecttrv4_${inner_port}.dest_port="${outter_port}"
# reload
uci commit firewall
/etc/init.d/firewall reload
sleep 3
else
# iptables
# ipv4
# delete old v4rules
iptables -t nat -D PREROUTING -j redirecttrv4-$inner_port
iptables -t nat -F redirecttrv4-$inner_port
iptables -t nat -X redirecttrv4-$inner_port
# add v4rule
iptables -t nat -N redirecttrv4-$inner_port
iptables -t nat -A redirecttrv4-$inner_port -p $protocol -d $inner_ip --dport $inner_port -j DNAT --to-destination $trv4:$outter_port
iptables -t nat -I PREROUTING -j redirecttrv4-$inner_port
# ipv6
trv6ipt=$(echo $trv6|sed 's/ /,/g')
# delete old v6rules
ip6tables -D FORWARD -j allowtrv6-$inner_port
ip6tables -F allowtrv6-$inner_port
ip6tables -X allowtrv6-$inner_port
# add v6rule
ip6tables -N allowtrv6-$inner_port
ip6tables -A allowtrv6-$inner_port -p tcp -d $trv6ipt --dport $outter_port -j ACCEPT
ip6tables -A allowtrv6-$inner_port -p udp -d $trv6ipt --dport $outter_port -j ACCEPT
ip6tables -I FORWARD -j allowtrv6-$inner_port
fi
# update port
date=$(date +%s); echo $date > /tmp/natter${inner_port}
while true; do
[[ $(cat /tmp/natter$inner_port) != $date ]] && exit 0
tcping -c1 -p${trwebport} ${trv4} >/dev/null
if [ $? -eq 0 ]; then
if [ -n ${trusername} ]; then
trauth="-u $trusername:$trpassword"
fi
trsid=$(curl -s $trauth http://${trv4}:${trwebport}/transmission/rpc | sed 's/.*<code>//g;s/<\/code>.*//g')
curl -X POST \
-H "${trsid}" $trauth \
-d '{"method":"session-set","arguments":{"peer-port":'${outter_port}'}}' \
"http://${trv4}:${trwebport}/transmission/rpc"
text="[Natter] Transmission TCP Port:\n$outter_ip:$outter_port -&gt; $inner_ip:$inner_port -&gt; $trv4:$outter_port"
break
fi
sleep 3
done
;;
*)
text="[Natter] Upload to server: ${protocol}: ${inner_ip}:${inner_port} -&gt; ${outter_ip}:${outter_port}"
;;
esac
tgid=""
bottoken=""
if [ "${text}" ]; then
echo "${text}"
logger -t "Natter" "${text}"
curl -Ss -o /dev/null -X POST \
-H 'Content-Type: application/json' \
-d '{"chat_id": "'${tgid}'", "text": "'"${text}"'", "parse_mode": "HTML", "disable_notification": "false"}' \
"https://api.telegram.org/bot${bottoken}/sendMessage"
fi
@veltlion
Copy link
Author

如果只有来自路由器 IP 的传入连接,可能需要禁用 OpenWrt 的地址重写。
防火墙 - NAT 规则添加
屏幕截图 2022-12-29 214222

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment