heiher / natmap

TCP/UDP port mapping for full cone NAT
MIT License
1.38k stars 103 forks source link

[shares] notification scripts #12

Open heiher opened 1 year ago

heiher commented 1 year ago

Welcome to share the notification scripts. 欢迎分享通知脚本。

heiher commented 1 year ago

Cloudflare DDNS IP4P(IPv4 and port encoding in AAAA record):

#!/bin/sh

ZONE=''
RECORD=''
EMAIL=''
AUTH=''
DOMAIN=''

IP4P=${3}

while true; do
    curl -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE}/dns_records/${RECORD}" \
        -H "X-Auth-Email: ${EMAIL}" \
        -H "Authorization: Bearer ${AUTH}" \
        -H "Content-Type:application/json" \
        --data "{\"type\":\"AAAA\",\"name\":\"${DOMAIN}\",\"content\":\"${IP4P}\",\"ttl\":60,\"proxied\":false}" > /dev/null 2> /dev/null
    if [ $? -eq 0 ]; then
        break
    fi
done

Applications supports IP4P:

heiher commented 1 year ago

Natter/NATMap 打洞后自动更新 qBittorrent/Transmission 监听端口和 OpenWrt 防火墙规则并推送到 Telegram:

https://gist.github.com/veltlion/b59d73654f0ae36725f5a571602729cb

据说让BT/PT客户端的侦听端口与打洞后的公网端口保持一致可以有效提高peer间的连通性,从而提升上传速度。 See also: https://www.v2ex.com/t/902093#reply29

ysc3839 commented 1 year ago

ns1.com scripts for update A (IPv4 address) and SRV (port) record. Requires OpenWrt's jshn (/usr/share/libubox/jshn.sh), used to format JSON string. https://gist.github.com/ysc3839/2c629d69f5fc3541a3f1900a23681f0c

Docs about SRV record: https://www.cloudflare.com/learning/dns/dns-records/dns-srv-record/ https://en.wikipedia.org/wiki/SRV_record

OpportunityLiu commented 1 year ago

据说让BT/PT客户端的侦听端口与打洞后的公网端口保持一致可以有效提高peer间的连通性,从而提升上传速度。 See also: https://www.v2ex.com/t/902093#reply29

image

qBittorrent 的实现应该没啥问题,是不是受 IPV4、V6 监听端口不一致的影响

好像是 tracker 实现的问题,有些 tracker 只能绑定一个端口 https://github.com/arvidn/libtorrent/issues/5746#issuecomment-832699374

OpenGG commented 1 year ago

dynv6 DDNS IP4P(IPv4 and port encoding in AAAA record):

#!/bin/sh

ZONE=''
TOKEN=''

IP4P=${3}

while true; do
    curl \
      "https://dynv6.com/api/update?hostname=${ZONE}&token=${TOKEN}&ipv6=${IP4P}&ipv6prefix=${IP4P}" \
      > /dev/null 2> /dev/null
    if [ $? -eq 0 ]; then
        break
    fi
done
Wikeolf commented 1 year ago

Fix someting wrong with my openwrt router from https://github.com/heiher/natmap/wiki/web /usr/bin/wdns

What's more, when you are using HTTP protocol, please create a Configuration Rules (zone-->Rules --> Configuration Rules) to switch SSL option to off for specific subdomain, or turn to use HTTPS

#!/bin/sh

ZONE='ZONE_ID'
RECORD='DNS_RECORD_ID'
RULE='ORIGIN_RULE_ID'
EMAIL='Cloudflare_EMAIL'
AUTH='Global_API_Key' 
#or you can use API Tokens but change "X-Auth-Key: ${AUTH}" to "Authorization: Bearer ${AUTH}"
DOMAIN='DEST_DOMAIN'

ADDR=${1}
PORT=${2}

# DNS
while true; do
    curl -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE}/dns_records/${RECORD}" \
        -H "X-Auth-Email: ${EMAIL}" \
        -H "X-Auth-Key: ${AUTH}" \
        -H "Content-Type:application/json" \
        --data "{\"type\":\"A\",\"name\":\"${DOMAIN}\",\"content\":\"${ADDR}\",\"ttl\":60,\"proxied\":true}" >> /tmp/wdns.log 2>&1
    if [ $? -eq 0 ]; then
        break
    fi
done

# Origin rule
while true; do
    curl -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE}/rulesets/${RULE}" \
        -H "X-Auth-Email: ${EMAIL}" \
        -H "X-Auth-Key: ${AUTH}" \
        -H "Content-Type:application/json" \
        --data "{\"rules\":[{\"expression\":\"(http.host eq \\\"${DOMAIN}\\\")\",\"description\":\"natmap\",\"action\":\"route\",\"action_parameters\":{\"origin\":{\"port\":${PORT}}}}]}" >> /tmp/wdns.log 2>&1
    if [ $? -eq 0 ]; then
        break
    fi
done
cwbsw commented 7 months ago

自动配置OpenWrt防火墙,将IPv4流量DNAT到内网地址(端口与公网映射端口一致),并且允许同一端口的IPv6流量。

#!/bin/sh

dest_ip="192.168.1.123"
dest_ip6="::1111:2222:3333:4444/::ffff:ffff:ffff:ffff"

. /usr/share/libubox/jshn.sh

json_init
json_add_string name natmap
json_add_object data
json_add_array firewall

for file in /var/run/natmap/*.json; do
    public_port=$(jsonfilter -i $file -e '@.port')
    bind_port=$(jsonfilter -i $file -e '@.inner_port')

    json_add_object
    json_add_string type redirect
    json_add_string target DNAT
    json_add_string proto tcp
    json_add_string src wan
    json_add_string dest lan
    json_add_string src_dport $bind_port
    json_add_string dest_ip $dest_ip
    json_add_string dest_port $public_port
    json_add_boolean reflection false
    json_close_object

    json_add_object
    json_add_string type rule
    json_add_string target ACCEPT
    json_add_string proto tcp
    json_add_string src wan
    json_add_string dest lan
    json_add_string dest_ip $dest_ip6
    json_add_string dest_port $public_port
    json_close_object
done

json_close_array
json_close_object

ubus call service set "$(json_dump)"

#Now fw4 can't reload correctly, so reload-sets first
/sbin/fw4 reload-sets && /sbin/fw4 reload
ysc3839 commented 6 months ago

@cwbsw 看上去使用这种方案可以让防火墙配置跟随 natmap 服务?重启系统是不是可以自动清除?有相关文档吗?

cwbsw commented 6 months ago

@ysc3839 这个不会写入配置文件,停掉natmap,重新加载防火墙就没了。在natmap的启动脚本加上停止时重新加载防火墙的命令可自动化。 https://openwrt.org/docs/guide-developer/ubus/service https://github.com/openwrt/firewall4/blob/698a53354fd280aae097efe08803c0c9a10c14c2/root/usr/share/ucode/fw4.uc#L573

ysc3839 commented 6 months ago

@cwbsw 去确认了一下代码,使用 service.set 时是会覆盖掉已有的 triggersvalidate,似乎必须先获取所有数据,更新,再设置。 https://github.com/openwrt/procd/blob/946552a7b598a0b88db6101e864679554ec4f221/service/service.c#L123-L141 既然要先获取原有设置,我觉得不如把 firewall 数据放到 instance 下的 data,甚至 natmap 返回的端口信息都可以放在 data 中,这样的话 luci 就可以直接获取到对应数据,不需要额外读取文件。 不过这里的 data 字段设计似乎是在服务启动时设置的,运行时修改可能违反了原有设计用途,有空我先提一个 PR 询问一下吧。 CC @heiher

ysc3839 commented 6 months ago

@cwbsw @heiher https://github.com/openwrt/packages/pull/24036

dmserver commented 6 months ago

多层路由 UPNP 映射端口, 当运行natmap设备 及上级路由全dhcp随机IP 时 这个很实用。 支持 爱快 京东 磊科 腾达 OpenWrt 路由混插,无论怎么串接都可以。 不支持 h3c 360 等 因为这些路由采用的随机UUID ipc,而upnp还无法跨路由发现,所以不支持。 理论支持 TP-Link ,因为想支持TP-Link,就得提前运行脚本去打开 混插在里面的TP-Link路由的UPNP端口, 否则一旦natmap运行起来,TP-Link将无法进行端口映射 upnp dmz,这属于TP-Link的设计缺陷,测试了手中全部TP-Link都这样 如果natmap 可以增加个先行脚本参数 例如-e 带的脚本 去执行准备任务,那么脚本可以支持TP-Link

https://github.com/heiher/natmap/issues/65 下面是脚本

`#!/bin/bash ###################################################################脚本测试模式数据

捆绑物理网卡

    eth="eth0"
    #路由层数   有几层路由就填几,当前主机上面只有一台路由就填1,可以使用ssh命令traceroute -n -m 10 223.5.5.5检查经过几个家用路由器(运营商的不算,具体看情况)
    wan_upnp=4
    #打开外网端口    这个是natmap -b的端口
    wan_upnp_port=9090
    #打开内网端口    这个是natmap -b的端口
    lan_upnp_port=2022
    #路由upnp xml 文件名 各家路由可能不一样 尽量搜集就是了
    upnp_xml="igd.xml rootDesc.xml UPnP/IGD.xml"
    #upnp 备注名
    upnp_port_name="STUN-TEXT"
    #旁路由跃迁  旁路由跃迁模式(yes/no),开启后,若发现路由网关信息内出现旁路由,将直接由主路映射至下级设备,流量不经转旁路,正常情况不会出现旁路信息
    side_route="no"
    #测试协议
    protocol="tcp"

########################################################################################################下方固定函数及内容 times=$(date +"%F %T") upnp_text_info=$times" upnp测试" if ! type upnpc > /dev/null 2>&1; then echo 'upnpc 未安装,开始安装'; apt-get install -y miniupnpc else cd / fi

if ! type traceroute > /dev/null 2>&1; then echo 'traceroute 未安装,开始安装'; apt-get install -y traceroute else cd / fi

if ! type fping > /dev/null 2>&1; then echo 'fping 未安装,开始安装'; apt-get install -y fping else cd / fi

lan_ip=$(ip address show $eth | head -n4 | grep inet | awk '{print$2}' | cut -d/ -f1-1) break_id=0 for ((;;)) do if [ -n "$eth" ]; then wan_gw_info=$(traceroute -n -m $wan_upnp -i $eth 223.5.5.5 | awk '{print$2}' | grep ".") else wan_gw_info=$(traceroute -n -m $wan_upnp 223.5.5.5 | awk '{print$2}' | grep ".") fi if [ -n "$wan_gw_info" ] || [ $break_id -eq 5 ]; then break fi ((break_id++)); done if [ ! -n "$wan_gw_info" ];then exit 0 fi #######################################################################操作函数 get_gw_upnp (){ gw_ip=$1 gx_xml=$2 break_id=1 upnp_xmls=(${gx_xml// / }) for ((upp=1;upp<3;upp++)) do upnp_port=$(nmap -F -max_rtt_timeout 1 -sT $gw_ip | grep open) if [ -n "$upnp_port" ] ; then break fi done upnp_port_info=$(echo $upnp_port | awk '{split($0, a, "open upnp"); print a[1]}' | rev | cut -d' ' -f2 | rev | cut -d/ -f1-1) if [[ -z $upnp_port_info ]] || [[ "$upnp_port_info" = "p" ]] || [[ "$upnp_port_info" = "p" ]]; then upnp_port_info="80 1900 5000" fi for upnp_xmlname in ${upnp_xmls[@]}; do for upnp_porti in ${upnp_port_info[@]}; do upnpxml_cs="http://"$gw_ip":"$upnp_porti"/"$upnp_xmlname upnp_xml_info=$(curl -L -k --connect-timeout 1 -m 1 -s "$upnpxml_cs") if [[ "$upnp_xml_info" = "xml"* ]];then upnpxml_url=$upnpxml_cs break fi done if [ ! -z $upnpxml_url ];then echo $upnpxml_url return 1 fi done break_id=1 for ((;;)) do upnpxml_cs=$(upnpc -i -P | grep "$gw_ip" | grep "desc" | cut -d: -f2-4) if [ -n "$upnpxml_cs" ]; then echo $upnpxml_cs return 1 fi upnpxml_cs=$(upnpc -P | grep "$gw_ip" | grep "desc" | cut -d: -f2-4) if [ -n "$upnpxml_cs" ]; then echo $upnpxml_cs return 1 fi if [ $break_id -eq 5 ];then echo $upnpxml_cs return 1 fi ((break_id++)); done } get_upnp_exip (){ upnpxml=$1 break_id=0 upnp_eth=$2 if [ -n "$upnp_eth" ]; then upnpeth=" -m "$upnp_eth else upnpeth=" " fi for ((;;)) do upnpexip=$(upnpc $upnpeth -u $upnpxml -S | grep ExternalIPAddress | awk '{print $3}') if [ -n "$upnpexip" ];then echo $upnpexip return 1 fi upnpexip=$(upnpc $upnpeth -i -u $upnpxml -S | grep ExternalIPAddress | awk '{print $3}') if [ -n "$upnpexip" ];then echo $upnpexip return 1 fi upnpexip=$(upnpc $upnpeth -u $upnpxml -s | grep ExternalIPAddress | awk '{print $3}') if [ -n "$upnpexip" ];then echo $upnpexip return 1 fi upnpexip=$(upnpc $upnpeth -i -u $upnpxml -s | grep ExternalIPAddress | awk '{print $3}') if [ -n "$upnpexip" ];then echo $upnpexip return 1 fi if [ $break_id -eq 5 ];then break fi ((break_id++)); done }

get_ip (){ gw_ip=$1 gw_port=$2 protocolas=$3 protocolac=$(echo $protocolas | tr a-z A-Z) upnp_text_infos=$4 ip_scan=$(echo $gw_ip | cut -d. -f1-3) ip_a_info=$(fping -a -g -q $ip_scan.0/24) ip_a_array=(${ip_a_info// / }) for ip_add in ${ip_a_array[@]}; do if [[ ${protocolac} = "TCP" ]] then ip_upnp_port=$(nc -z $ip_add $gw_port -w 2 && echo "open" || echo "close") ip_upnp_ports_a=$(curl -L -k --connect-timeout 1 -m 2 -s "http://$ip_add:$gw_port") ip_upnp_ports_b=$(curl -L -k --connect-timeout 1 -m 2 -s "https://$ip_add:$gw_port") else ip_upnp_port=$(nc -z $ip_add $gw_port -w 2 -u && echo "open" || echo "close") fi if [[ "$ip_upnp_port" = "open" ]] && [[ "$gw_ip" != "$ip_add" ]];then echo $ip_add return 1 fi done } upnp_nat_v2 (){ lan_ip_add=$1 route_upnp_xml=$2 lan_ip_port=$3 wan_ip_port=$4 upnp_protocol=$5 upnp_base=$6 upnp_eth=$7 upnp_pa=$upnpbase""$wan_ipport""$lan_ipport""$(echo $upnp_protocol | tr a-z A-Z) upnp_pb=$upnpbase""$wan_ipport""$lan_ipport""$upnp_protocol if [ -n "$upnp_eth" ]; then upnpeth=" -m "$upnp_eth else upnpeth=" " fi upnp_array=$(upnpc -u $route_upnp_xml $upnpeth -L | grep "$upnpbase" | awk '{print $3""$2}'| sed 's/-../ /g' | awk '{print $1""$1"_"$2}') for upnp_tp in ${upnp_array[@]}; do upnpc -u $route_upnp_xml $upnpeth -N $(echo $upnptp | sed 's/\/ /g') > /dev/null done upnpc -u $route_upnp_xml $upnpeth -N $wan_ip_port $wan_ip_port $upnp_protocol >/dev/null add_upnp_log=$(upnpc -u $route_upnp_xml $upnpeth -e "$upnp_base" -n $lan_ip_add $lan_ip_port $wan_ip_port $upnp_protocol 0) add_upnp_log_a=$(echo $add_upnp_log | grep "duration" | grep "InternalIP:Port") if [ -n "$add_upnp_log_a" ];then return 1 fi upnp_arrayp=$(upnpc -u $route_upnp_xml $upnpeth -L | grep "$upnpbase" | awk '{print $4""$3"_"$2}'| sed "s/->..:/_/g" | sed "s/'//g") for upnp_tpp in ${upnp_arrayp[@]}; do if [[ ${upnp_tpp} = ${upnp_pa} ]] || [[ ${upnp_tpp} = ${upnp_pb} ]] then return 1 else cd / fi done return 0 } upnp_nat_v2i (){ lan_ip_add=$1 route_upnp_xml=$2 lan_ip_port=$3 wan_ip_port=$4 upnp_protocol=$5 upnp_base=$6 upnp_eth=$7 upnp_pa=$upnpbase""$wan_ipport""$lan_ipport""$(echo $upnp_protocol | tr a-z A-Z) upnp_pb=$upnpbase""$wan_ipport""$lan_ipport""$upnp_protocol if [ -n "$upnp_eth" ]; then upnpeth=" -m "$upnp_eth else upnpeth=" " fi upnp_array=$(upnpc -i -u $route_upnp_xml $upnpeth -L | grep "$upnpbase" | awk '{print $3""$2}'| sed 's/-../ /g' | awk '{print $1""$1"_"$2}') for upnp_tp in ${upnp_array[@]}; do upnpc -i -u $route_upnp_xml $upnpeth -N $(echo $upnptp | sed 's/\/ /g') > /dev/null done upnpc -i -u $route_upnp_xml $upnpeth -N $wan_ip_port $wan_ip_port $upnp_protocol >/dev/null add_upnp_log=$(upnpc -i -u $route_upnp_xml $upnpeth -e "$upnp_base" -n $lan_ip_add $lan_ip_port $wan_ip_port $upnp_protocol 0) add_upnp_log_a=$(echo $add_upnp_log | grep "duration" | grep "InternalIP:Port") if [ -n "$add_upnp_log_a" ];then return 1 fi upnp_arrayp=$(upnpc -i -u $route_upnp_xml $upnpeth -L | grep "$upnpbase" | awk '{print $4""$3"_"$2}'| sed "s/->..:/_/g" | sed "s/'//g") for upnp_tpp in ${upnp_arrayp[@]}; do if [[ ${upnp_tpp} = ${upnp_pa} ]] || [[ ${upnp_tpp} = ${upnp_pb} ]] then return 1 else cd / fi done return 0 } upnp_nat_v1 (){ lan_ip_add=$1 route_upnp_xml=$2 lan_ip_port=$3 wan_ip_port=$4 upnp_protocol=$5 upnp_base=$6 upnp_eth=$7 upnp_pa=$upnpbase""$wan_ipport""$lan_ipport""$(echo $upnp_protocol | tr a-z A-Z) upnp_pb=$upnpbase""$wan_ipport""$lan_ipport""$upnp_protocol if [ -n "$upnp_eth" ]; then upnpeth=" -m "$upnp_eth else upnpeth=" " fi upnp_array=$(upnpc -u $route_upnp_xml $upnpeth -l | grep "$upnpbase" | awk '{print $3""$2}'| sed 's/-..//g') for upnp_tp in ${upnp_array[@]}; do upnpc -u $route_upnp_xml $upnpeth -d $(echo $upnptp | sed 's/\/ /g') > /dev/null done upnpc -u $route_upnp_xml $upnpeth -d $wan_ip_port $upnp_protocol >/dev/null add_upnp_log=$(upnpc -u $route_upnp_xml $upnpeth -e "$upnp_base" -a $lan_ip_add $lan_ip_port $wan_ip_port $upnp_protocol 0) add_upnp_log_a=$(echo $add_upnp_log | grep "duration" | grep "InternalIP:Port") if [ -n "$add_upnp_log_a" ];then return 1 fi upnp_arrayp=$(upnpc -u $route_upnp_xml $upnpeth -l | grep "$upnpbase" | awk '{print $4""$3"_"$2}'| sed "s/->..:/_/g" | sed "s/'//g") for upnp_tpp in ${upnp_arrayp[@]}; do if [[ ${upnp_tpp} = ${upnp_pa} ]] || [[ ${upnp_tpp} = ${upnp_pb} ]] then return 1 else cd / fi done return 0 } upnp_nat_v1i (){ lan_ip_add=$1 route_upnp_xml=$2 lan_ip_port=$3 wan_ip_port=$4 upnp_protocol=$5 upnp_base=$6 upnp_eth=$7 upnp_pa=$upnpbase""$wan_ipport""$lan_ipport""$(echo $upnp_protocol | tr a-z A-Z) upnp_pb=$upnpbase""$wan_ipport""$lan_ipport""$upnp_protocol if [ -n "$upnp_eth" ]; then upnpeth=" -m "$upnp_eth else upnpeth=" " fi upnp_array=$(upnpc -i -u $route_upnp_xml $upnpeth -l | grep "$upnpbase" | awk '{print $3""$2}'| sed 's/-..//g') for upnp_tp in ${upnp_array[@]}; do upnpc -i -u $route_upnp_xml $upnpeth -d $(echo $upnptp | sed 's/\/ /g') > /dev/null done upnpc -i -u $route_upnp_xml $upnpeth -d $wan_ip_port $upnp_protocol >/dev/null add_upnp_log=$(upnpc -i -u $route_upnp_xml $upnpeth -e "$upnp_base" -a $lan_ip_add $lan_ip_port $wan_ip_port $upnp_protocol 0) add_upnp_log_a=$(echo $add_upnp_log | grep "duration" | grep "InternalIP:Port") if [ -n "$add_upnp_log_a" ];then return 1 fi upnp_arrayp=$(upnpc -i -u $route_upnp_xml $upnpeth -l | grep "$upnpbase" | awk '{print $4""$3"_"$2}'| sed "s/->..:/_/g" | sed "s/'//g") for upnp_tpp in ${upnp_arrayp[@]}; do if [[ ${upnp_tpp} = ${upnp_pa} ]] || [[ ${upnp_tpp} = ${upnp_pb} ]] then return 1 else cd / fi done return 0 } #######################################################################开始处理数据 fb=$(expr $wan_upnp - 1) echo upnp_exip_up="" upnp_exip_down="" wan_gw_array=(${wan_gw_info// / }) for ((i=0;i<$wan_upnp;i++)) do wan_gw_ip=${wan_gw_array[$i]} gw_upnp_xml=$(get_gw_upnp $wan_gw_ip "$upnp_xml") echo $(date +"%F %T")"获取网关xml:"$gw_upnp_xml upnp_exip_down=$(get_upnp_exip "$gw_upnp_xml" $eth) echo $(date +"%F %T")"获取网关出口IP:"$upnp_exip_down

    if [ ! -n "$gw_upnp_xml" ];then
        echo "网关"$wan_gw_ip"未找到UPNP服务"
        exit 0
    fi
    if [[ $i -eq 0 ]]
        then
            #本机IP OR 内网下lan IP
            upnp_exip_up=$lan_ip
        else
            #映射的内网端口
            lan_upnp_port=$wan_upnp_port
            #本机IP OR 内网下lan IP(上一轮的出口IP)
            upnp_exip_up=$upnp_exip_down_d
            if [ ! -n "$upnp_exip_up" ]; then
                #上一轮未获取到出口IP作为LAN IP,将通过服务信息检索出服务IP
                upnp_exip_up=$(get_ip $wan_gw_ip $wan_upnp_port $protocol "$upnp_text_info")
            fi
    fi
    #差值 将本轮出口IP 作为下一网关 内网下lan
    upnp_exip_down_d=$upnp_exip_down

    #旁路由判定-基于IP段是否相同的方式判定 因为正常路由wan和lan不能处于相同网段
    gw_wan_domain_a=$(echo ${wan_gw_array[$i]} | cut -d. -f1-3)
    gw_wan_domain_b=$(echo ${wan_gw_array[$i + 1]} | cut -d. -f1-3)
    if [[ "$gw_wan_domain_a" = "$gw_wan_domain_b" ]] && [[ "$side_route" = "yes" ]];then
        echo "疑似遇到旁路由模式,停止本网关映射,进行映射跃迁,不经过旁路映射"
        if [[ $i -eq 0 ]]
            then
                #差值 将本轮 LAN IP 作为下一网关 内网下lan
                upnp_exip_down_d=$lan_ip
            else
                #差值 将本轮 LAN IP 作为下一网关 内网下lan
                upnp_exip_down_d=$upnp_exip_up
        fi
        continue
    fi
    break_id=1
    for ((;;))
        do
            upnp_nat_v2 $upnp_exip_up "$gw_upnp_xml" $lan_upnp_port $wan_upnp_port $protocol "$upnp_port_name" $eth
            if [ $? -eq 1 ];then
                upnp_state="V2映射成功"
                break
            fi
            upnp_nat_v2i $upnp_exip_up "$gw_upnp_xml" $lan_upnp_port $wan_upnp_port $protocol "$upnp_port_name" $eth
            if [ $? -eq 1 ];then
                upnp_state="V2i映射成功"
                break
            fi
            upnp_nat_v1 $upnp_exip_up "$gw_upnp_xml" $lan_upnp_port $wan_upnp_port $protocol "$upnp_port_name" $eth
            if [ $? -eq 1 ];then
                upnp_state="V1映射成功"
                break
            fi
            upnp_nat_v1i $upnp_exip_up "$gw_upnp_xml" $lan_upnp_port $wan_upnp_port $protocol "$upnp_port_name" $eth
            if [ $? -eq 1 ];then
                upnp_state="V1i映射成功"
                break
            fi
            if [ $break_id -eq 1 ];then
                upnp_state="映射失败"
                break
            fi
            ((break_id++));
        done
    if [[ "$cspding" != "route" ]]
        then
            echo ""
            echo $upnp_exip_up "$gw_upnp_xml" $lan_upnp_port $wan_upnp_port $protocol "$upnp_port_name" $eth
            echo "路由层 "$i" "$upnp_state"--------"$upnp_exip_up "-->>" $wan_gw_ip "upnpXML" $gw_upnp_xml "ExitIP "$upnp_exip_down
        else
            echo $upnp_exip_up "$gw_upnp_xml" $lan_upnp_port $wan_upnp_port $protocol "$upnp_port_name" $eth
            echo "路由层 "$i" "$upnp_state"--------"$upnp_exip_up "-->>" $wan_gw_ip "upnpXML" $gw_upnp_xml "ExitIP "$upnp_exip_down
    fi
    echo ""
    echo ""
done`
lhongcai commented 2 months ago

如果是多个端口映射,配置起来就非常繁琐容易出错 PixPin_2024-09-11_02-36-08 同时想在同一个端口号配置多少个ddns脚本 所以我花费了三四天的时间构思和编写了这个一键脚本一键安装配置natmap插件脚本

为了方便使用我弄了个在线安装命令: curl -L w.1hc.us.kg/natmap_install.sh|sh

脚本只适合于padavan或者openwrt PixPin_2024-09-11_02-49-05

脚本使用方法: 在线安装 第一步:登录SSH终端,输入curl http://w.1hc.us.kg/natmap/natmap_install.sh | sh

第二步:Openwrt的编辑/etc/rc.local padavan的编辑_/etc/storage/startedscript.sh

第三步:输入 sh /etc/storage/natmap.sh 或者 sh /etc/natmap.sh

openwrt的

停止运行:sh /etc/natmap.sh 0 sh /etc/natmap.sh stop

重启运行:sh /etc/natmap.sh

卸载:sh /etc/natmap.sh uninstall

padavan的

停止运行:sh /etc/storage/natmap.sh 0 sh /etc/storage/natmap.sh stop

重启运行:sh /etc/storage/natmap.sh

卸载:sh /etc/storage/natmap.sh uninstall

目前预编辑几个natmap专用ddns脚本

cf_txt.sh <子域名> <域名> <电子邮箱> 域名以TXT记录 https://dash.cloudflare.com/login

cf_ip4p.sh <子域名> <域名> <电子邮箱> 域名以ip4p形式AAAA记录 https://dash.cloudflare.com/login

dedyn_ip4p.sh <子域名> <域名> 子域名以ip4p形式AAAA记录 https://desec.io/

dedyn_txt.sh <子域名> <域名> 子域名以TXT记录 https://desec.io/

dynv6_ip4p.sh <子域名> <域名> 子域名以ip4p形式AAAA记录 https://dynv6.com/

dynv6_aaaa.sh <域名>
主域名以ip4p形式AAAA记录 https://dynv6.com/

dynv6_txt.sh <子域名> <域名> 子域名以TXT记录 https://dynv6.com/

freedomain_ip4p.sh <子域名> <域名>
子域名以ip4p形式AAAA记录 https://freedomain.one/users/login/

freedomain_txt.sh <子域名> <域名>
域名以TXT记录 https://freedomain.one/users/login/

UrlShort_wr.sh <后缀> <服务器> <密码> 直接在浏览器中重定向。 现成的网站 https://1hc.us.kg/ https://Lhc.us.kg/ 相关的项目 https://github.com/lmq8267/CloudflareWorker-KV-UrlShort https://github.com/lmq8267/short-url https://github.com/lmq8267/short-url-go

UrlShort_ssh.sh <后缀> <服务器> <密码> 以文本形式在浏览器显示SSH信息

UrlShort_html.sh <后缀> <服务器> <密码> 在浏览器显示ip和端口号

gg_wr.sh <后缀> <电子邮箱> <密码> 直接在浏览器中重定向 https://gg.gg/login

shorten_wr.sh <后缀> <服务器> <密码> 直接在浏览器中重定向 相关的项目 https://github.com/lmq8267/Url-Shorten-Worker ——natmap_install.sh脚本内容——

#!/bin/sh

# 脚本制作人:liao*****
# 适用平台:pandavan和OpenWrt

log_ () {
#echo -e "\033[35m`date +%F' '%X ` \033[0m" "\033[32m ${loge} \033[0m"
echo -e "\033[36;1m【$(TZ=UTC-8 date -R +%Y年%m月%d月\ %X)】 : \033[0m\033[32;1m$1 \033[0m"
logger  "$1"
}

log_2 () {
local loge=$1
#echo -e "\033[35m`date +%F' '%X ` \033[0m" "\033[31m ${loge} \033[0m"
echo -e "\033[36;1m【$(TZ=UTC-8 date -R +%Y年%m月%d月\ %X)】 : \033[0m\033[31;1m$1 \033[0m"
logger  "${loge}"
}

if [ -f "/etc/storage/started_script.sh" ] ; then # 判断系统是否为padavan
boot_up="/etc/storage/started_script.sh"
natmap_sh="/etc/storage/natmap.sh"
n_ddns="/etc/storage/n_ddns"
#cp "${natmap}" /etc/storage/natmap
#iptable_sh="/etc/storage/post_iptables_script.sh"
#boot_up="/tmp/log/info.txt"
#natmap_sh="/tmp/natmap.sh"
else # 其他的系统
boot_up="/etc/rc.local"
natmap_sh="/etc/natmap.sh"
n_ddns="/etc/n_ddns"
#cp "${natmap}" /etc/natmap
#boot_up="/tmp/natmap_info.txt"
#natmap_sh="/tmp/log/natmap.sh"
#boot_up="/tmp/log/info.txt"
fi

log_ "开始下载启动natmap.sh脚本文件"
script="natmap.sh"
urls="
http://w.1hc.us.kg/natmap/${script}
http://lhc.us.kg:19213/natmap/${script}
http://liaoh.web3v.vip/natmap/${script}
"
# 尝试下载并检查每个URL
for url in ${urls}
do
    log_ "尝试下载: $url"

    # 使用curl下载文件
    if curl --connect-timeout 3 -#Lko "/tmp/${script}" "$url" ; then
        log_ "下载成功: $url"
         [ -x "/tmp/${script}" ] || chmod +x "/tmp/${script}"
        # 检查文件的第一行是否包含 #! 字符串
        if head -n 1 /tmp/${script} | grep -q '^#!'; then
         [ -x "/tmp/${script}" ] || chmod +x "/tmp/${script}"
            log_ "文件检查通过,是shell脚本"
            cp "/tmp/${script}" "${natmap_sh}"
            break  # 成功下载并验证后退出循环
        else
            log_2 "文件不是shell脚本,尝试下一个地址"
        fi
    else
        log_2 "下载失败: $url,尝试下一个地址"
    fi
done
log_ "启动natmap.sh脚本文件下载完毕"

log_ "开始下载natmap专用ddns脚本文件"
natmap_ddns_script="
cf_txt.sh
cf_ip4p.sh
dedyn_ip4p.sh
dedyn_txt.sh
dynv6_ip4p.sh
dynv6_aaaa.sh
dynv6_txt.sh
freedomain_ip4p.sh
freedomain_txt.sh
UrlShort_wr.sh
UrlShort_ssh.sh
UrlShort_html.sh
gg_wr.sh
shorten_wr.sh
"

for k in $natmap_ddns_script

do
[ ! -d "${n_ddns}" ] && mkdir "${n_ddns}"

ddns_script="${n_ddns}/$k"

[ -f "$ddns_script" ] || {

url_1="
http://w.1hc.us.kg/natmap/natmap_ddns_script/$k
http://lhc.us.kg:19213/natmap/natmap_ddns_script/$k
http://liaoh.web3v.vip/natmap_ddns_script/$k
http://${webd_t}/natmap_ddns_script/$k
"

for j in ${url_1}
do
curl -o "$ddns_script" -#Lks $j &>/dev/unll
if [ -f "$ddns_script" ] ; then
if head -n 1 "$ddns_script" | grep -q '\#!' ; then
    log_ "$j下载成功!"
    log_ " "
    break
else
    log_2 "$j文件错误!"
    [ -f "$ddns_script" ] && rm -f "$ddns_script" && log_ "$j删除成功!"
    log_ "即将尝试使用下一个网址进行下载 ······"
    log_ " "
fi
else
    [ -f "$ddns_script" ] && rm -f "$ddns_script" && log_ "$j删除成功!"
    log_2 "$j下载错误!"
    log_ "即将尝试使用下一个网址进行下载 ······"
    log_ " "
fi
done

}
 [ -x "$ddns_script" ] || chmod +x "$ddns_script"

done
log_ "natmap专用ddns脚本文件下载完毕"

log_ "请到${n_ddns}目录中查看natmap专用ddns脚本文件"

 [ -z "`cat $boot_up | grep -o 'natmap.sh'`" ] && {
sed -i '2i\sleep 55 && sh '"${natmap_sh}"' &' ${boot_up} # 插在开机启动脚本第二行中
} 

if [ -z "`cat $boot_up | grep -o 'natmap端口映射配置'`" ] ; then

cat <<EOF10>> "$boot_up"  # 加到开机启动脚本后

:<<'!mn'
natmap端口映射配置

像这样的格式,一条映射可以配置多个ddns脚本,同时要去掉“#”号!
已下载的natmap专用ddns脚本文件:
${n_ddns}/cf_txt.sh             域名以TXT记录
${n_ddns}/cf_ip4p.sh            域名以ip4p形式AAAA记录
${n_ddns}/dedyn_ip4p.sh         子域名以ip4p形式AAAA记录
${n_ddns}/dedyn_txt.sh      子域名以TXT记录
${n_ddns}/dynv6_ip4p.sh     子域名以ip4p形式AAAA记录
${n_ddns}/dynv6_aaaa.sh     主域名以ip4p形式AAAA记录
${n_ddns}/dynv6_txt.sh      子域名以TXT记录
${n_ddns}/freedomain_ip4p.sh        子域名以ip4p形式AAAA记录
${n_ddns}/freedomain_txt.sh         域名以TXT记录
${n_ddns}/UrlShort_wr.sh        直接在浏览器中重定向
${n_ddns}/UrlShort_ssh.sh       以文本形式在浏览器显示SSH信息
${n_ddns}/UrlShort_html.sh      在浏览器显示ip和端口号
${n_ddns}/gg_wr.sh      直接在浏览器中重定向
${n_ddns}/shorten_wr.sh         直接在浏览器中重定向
#udp/tcp 端口号 [(内网ip) (服务端口)]
#-/+ 脚本路径 后缀/子域名 域名 密码/token

例如:
#udp 20086 127.0.0.1 10086 # N2N服务 udp端口
#- ${n_ddns}/dynv6_txt.sh   <子域名>   <域名>        <token>

#udp 49872 127.0.0.1 29872 # vnts服务端udp端口
#- ${n_ddns}/dynv6_txt.sh   <子域名>   <域名>        <token>
#- ${n_ddns}/dedyn_txt.sh    <子域名>  <域名>        <token>

#udp 41820 127.0.0.1 51820 # wireguard服务
#- ${n_ddns}/dynv6_ip4p.sh  <子域名>   <域名>        <token>

#tcp 49872 127.0.0.1 29872 # vnts服务端tcp端口
#+ ${n_ddns}/cf_txt.sh  <子域名>   <域名>    <token>  <电子邮箱>  <key>
#+ ${n_ddns}/UrlShort_html.sh   <后缀>        <域名>        <密码>
#+ ${n_ddns}/dynv6_txt.sh   <子域名>   <域名>        <token>
#+ ${n_ddns}/dedyn_txt.sh    <子域名>  <域名>        <token>

#tcp 49870 127.0.0.1 29870 # vnts服务端web页面
#+ ${n_ddns}/UrlShort_wr.sh     <后缀>        <域名>        <密码>

#tcp 400180 192.168.1.10 80 # 其他web页面
#+ ${n_ddns}/UrlShort_wr.sh     <后缀>        <域名>        <密码>

#tcp 40080 <内网ip> 80 # 路由器主页,不要用127.0.0.1
#+ ${n_ddns}/UrlShort_wr.sh     <后缀>        <域名>        <密码>
#+ ${n_ddns}/UrlShort_wr.sh     <后缀>        <域名>        <密码>

#tcp 40022 127.0.0.1 22 # SSH 用户@ip -p 端口 信息
#+ ${n_ddns}/UrlShort_ssh.sh    <后缀>        <域名>        <密码>

!mn
EOF10
log_ "配置完毕"

fi

log_ "请到本地启动配置文件(${boot_up})中编辑你自己的"
log_ "编辑完成后,记得保存!"
log_ "最后运行下sh ${natmap_sh} 脚本即可"

——natmap.sh脚本内容——

#!/bin/sh

# 脚本制作人:liao******
# 适用平台:pandavan和OpenWrt

log_ (){
local loge=$1
echo -e "\033[36;1m【$(TZ=UTC-8 date -R +%Y年%m月%d月\ %X)】 : \033[0m\033[35;1m${loge} \033[0m"
logger  "${loge}"
}

( [ "$1" = "0" ] || [ "$1" = "stop" ] ) && {
    sh  "/tmp/log/kill_natmap.log"
    log_ "已停止运行"
    exit 0
}

if [ -f "/etc/storage/started_script.sh" ] ; then # 判断系统是否为padavan
boot_up="/etc/storage/started_script.sh"
natmap_sh="/etc/storage/natmap.sh"
n_ddns="/etc/storage/n_ddns"
etc_natmap="/etc/storage/natmap"
#iptable_sh="/etc/storage/post_iptables_script.sh"
#boot_up="/tmp/log/info.txt"
#natmap_sh="/tmp/natmap.sh"
else # 其他的系统
boot_up="/etc/rc.local"
natmap_sh="/etc/natmap.sh"
n_ddns="/etc/n_ddns"
etc_natmap="/etc/natmap"
#cp "${natmap}" /etc/natmap
#boot_up="/tmp/natmap_info.txt"
#natmap_sh="/tmp/log/natmap.sh"
#boot_up="/tmp/log/info.txt"
fi

find_ (){ # 查找natmap运行文件

if [ -f "/tmp/natmap" ] ; then  
    natmap="/tmp/natmap"
elif [ -f "/etc/storage/natmap" ] ; then
    natmap="/etc/storage/natmap"
elif [ -f "/etc/storage/bin/natmap" ] ; then
    natmap="/etc/storage/bin/natmap"
elif [ -f "/etc/natmap" ] ; then
    natmap="/etc/natmap"
elif [ -f "/usr/bin/natmap" ] ; then
    natmap="/usr/bin/natmap"
elif [ -f "/jffs/natmap" ] ; then
    natmap="/jffs/natmap"
else
    natmap=""

    echo "系统不存在natmap插件"
fi

[ -f "${natmap}" ] && [ ! -x "${natmap}" ] && chmod +x "${natmap}" 

}

if ( [ "$1" = "install" ] || [ "$1" = "安装" ] ) ; then

log_ "开始下载启动natmap.sh脚本文件"
script="natmap.sh"
urls="
http://w.lhc.us.kg/natmap/${script}
http://s4.serv00.com:19213/natmap/${script}
http://liaoh.web3v.vip/natmap/${script}
"
# 尝试下载并检查每个URL
for url in ${urls}
do
    log_ "尝试下载: $url"

    # 使用curl下载文件
    if curl --connect-timeout 3 -#Lko "/tmp/${script}" "$url" ; then
        log_ "下载成功: $url"
         [ -x "/tmp/${script}" ] || chmod +x "/tmp/${script}"
        # 检查文件的第一行是否包含 #! 字符串
        if head -n 1 /tmp/${script} | grep -q '^#!'; then
         [ -x "/tmp/${script}" ] || chmod +x "/tmp/${script}"
            log_ "文件检查通过,是shell脚本"
            cp "/tmp/${script}" "${natmap_sh}"
            break  # 成功下载并验证后退出循环
        else
            log_ "文件不是shell脚本,尝试下一个地址"
        fi
    else
        log_ "下载失败: $url,尝试下一个地址"
    fi
done
log_ "启动natmap.sh脚本文件下载完毕"

log_ "开始下载natmap专用ddns脚本文件"

shell_script="
cf_txt.sh
cf_ip4p.sh
dedyn_ip4p.sh
dedyn_txt.sh
dynv6_ip4p.sh
dynv6_aaaa.sh
dynv6_txt.sh
freedomain_ip4p.sh
freedomain_txt.sh
UrlShort_wr.sh
UrlShort_ssh.sh
UrlShort_html.sh
gg_wr.sh
shorten_wr.sh
"
dir="${n_ddns}"

url_1="
http://w.lhc.us.kg/natmap/natmap_ddns_script
http://s4.serv00.com:19213/natmap/natmap_ddns_script
http://liaoh.web3v.vip/natmap_ddns_script

"

for k in $shell_script
do
[ ! -d "${dir}" ] && mkdir "${dir}" # 判断是否存在这个目录,否则创建
    dir_script="${dir}/$k" # 路径
[ -f "${dir_script}" ] || {
for j in ${url_1}
do
curl -o "$dir_script" -#Lks "$j/$k" &>/dev/unll
if [ -f "$dir_script" ] ; then
if head -n 1 "$dir_script" | grep -q '\#!' ; then # 判断下载的文件是否为脚本
    log_ "从$j下载的$k脚本成功!"
    log_ " "
    break # 如果是,跳出内循环,进行下一个脚本下载
else

    log_ "从$j下载的$k文件不是shell脚本!"
    [ -f "$dir_script" ] && rm -f "$dir_script" && log_ "$k删除成功!"
    log_ "即将尝试使用下一个网址进行下载 ······"
    echo " "
fi
else
    [ -f "$dir_script" ] && rm -f "$dir_script" && log_ "$k删除成功!"
    log_ "$j下载地址错误,无法下载!"
    log_ "即将尝试使用下一个网址进行下载 ······"
    log_ " "
fi
done
}
 [ -x "$dir_script" ] || chmod +x "$dir_script" # 判断是否有运行权限,否则赋予运行权限!
done

log_ "natmap专用ddns脚本文件下载完毕"

log_ "请到${n_ddns}目录中查看natmap专用ddns脚本文件"

 [ -z "`cat $boot_up | grep -o 'natmap.sh'`" ] && {
sed -i '2i\sleep 55 && sh '"${natmap_sh}"' &' ${boot_up} # 插在开机启动脚本第二行中
} 

if [ -z "`cat $boot_up | grep -o 'natmap端口映射配置'`" ] ; then

cat <<EOF10>> "$boot_up"  # 加到开机启动脚本后

:<<'!mn'
natmap端口映射配置

像这样的格式,一条映射可以配置多个ddns脚本,同时要去掉“#”号!
已下载的natmap专用ddns脚本文件:

${n_ddns}/cf_txt.sh             域名以TXT记录
${n_ddns}/cf_ip4p.sh            域名以ip4p形式AAAA记录
${n_ddns}/dedyn_ip4p.sh         子域名以ip4p形式AAAA记录
${n_ddns}/dedyn_txt.sh      子域名以TXT记录
${n_ddns}/dynv6_ip4p.sh     子域名以ip4p形式AAAA记录
${n_ddns}/dynv6_aaaa.sh     主域名以ip4p形式AAAA记录
${n_ddns}/dynv6_txt.sh      子域名以TXT记录
${n_ddns}/freedomain_ip4p.sh        子域名以ip4p形式AAAA记录
${n_ddns}/freedomain_txt.sh         域名以TXT记录
${n_ddns}/UrlShort_wr.sh        直接在浏览器中重定向
${n_ddns}/UrlShort_ssh.sh       以文本形式在浏览器显示SSH信息
${n_ddns}/UrlShort_html.sh      在浏览器显示ip和端口号
${n_ddns}/gg_wr.sh          直接在浏览器中重定向
${n_ddns}/shorten_wr.sh         直接在浏览器中重定向
#udp/tcp 端口号 [(内网ip) (服务端口)]
#-/+ 脚本路径 后缀/子域名 域名 密码/token

例如:
#udp 20086 127.0.0.1 10086 # N2N服务 udp端口
#- ${n_ddns}/dynv6_txt.sh   <子域名>   <域名>        <token>

#udp 49872 127.0.0.1 29872 # vnts服务端udp端口
#- ${n_ddns}/dynv6_txt.sh   <子域名>   <域名>        <token>
#- ${n_ddns}/dedyn_txt.sh    <子域名>  <域名>        <token>

#udp 41820 127.0.0.1 51820 # wireguard服务
#- ${n_ddns}/dynv6_ip4p.sh  <子域名>   <域名>        <token>

#tcp 49872 127.0.0.1 29872 # vnts服务端tcp端口
#+ ${n_ddns}/cf_txt.sh  <子域名>   <域名>    <token>  <电子邮箱>  <key>
#+ ${n_ddns}/UrlShort_html.sh   <后缀>        <域名>        <密码>
#+ ${n_ddns}/dynv6_txt.sh   <子域名>   <域名>        <token>
#+ ${n_ddns}/dedyn_txt.sh    <子域名>  <域名>        <token>

#tcp 49870 127.0.0.1 29870 # vnts服务端web页面
#+ ${n_ddns}/UrlShort_wr.sh     <后缀>        <域名>        <密码>

#tcp 400180 192.168.1.10 80 # 其他web页面
#+ ${n_ddns}/UrlShort_wr.sh     <后缀>        <域名>        <密码>

#tcp 40080 <内网ip> 80 # 路由器主页,不要用127.0.0.1
#+ ${n_ddns}/UrlShort_wr.sh     <后缀>        <域名>        <密码>
#+ ${n_ddns}/UrlShort_wr.sh     <后缀>        <域名>        <密码>

#tcp 40022 127.0.0.1 22 # SSH 用户@ip -p 端口 信息
#+ ${n_ddns}/UrlShort_ssh.sh    <后缀>        <域名>        <密码>

!mn
EOF10
log_ "配置完毕"

fi

log_ "请到本地启动配置文件(${boot_up})中编辑你自己的"
log_ "编辑完成后,记得保存!"
log_ "最后运行下sh ${natmap_sh} 脚本即可"

exit 0
fi

if [ "$1" = "uninstall" ] ; then # 卸载

    [ -f "/tmp/log/kill_natmap.log" ] && sh "/tmp/log/kill_natmap.log"
    log_ "已停止运行"

    [ -d "${n_ddns}" ] && rm -rf "${n_ddns}" && log_ "删除${n_ddns}成功" # 是否存在这个文件夹,然后再删除
    [ -d "/tmp/n_ddns" ] && rm -rf "/tmp/n_ddns" && log_ "删除/tmp/n_ddns成功" # 是否存在这个文件夹,然后再删除
    [ -f "/tmp/log/kill_natmap.log" ] && rm -rf "/tmp/log/kill_natmap.log" && log_ "删除/tmp/log/kill_natmap.log成功" # 是否存在这个文件,然后再删除
    [ -f "${natmap_sh}" ] && rm "${natmap_sh}" && log_ "删除${natmap_sh}成功" # 是否存在这个文件,然后再删除
    [ -f "${etc_natmap}" ] && rm "${etc_natmap}" && log_ "删除${etc_natmap}成功" # 是否存在这个文件,然后再删除
#   [ -f "/tmp/natmap" ] && rm "/tmp/natmap" && log_ "删除/tmp/natmap成功" #是否存在这个文件,然后再删除

    sed -i '/natmap.sh/d' "${boot_up}" && log_ "从开始启动文件中删除natmap.sh字样成功" # 从开始启动中删除natmap.sh字样

    sed -i '/:<<'\''!mn'\''/,/!mn/d' "${boot_up}" && log_ "从开始启动文件中删除natmap配置成功" # 从开始启动中删除natmap.sh字样

    exit 0
fi

cputype_ (){
cputype=$(uname -ms | tr ' ' '_' | tr '[A-Z]' '[a-z]')
[ -n "$(echo $cputype | grep -E "linux.*armv.*")" ] && cpucore="arm"
[ -n "$(echo $cputype | grep -E "linux.*armv.*"| grep ddwrt )" ] && cpucore="ddwrt-arm"
[ -n "$(echo $cputype | grep -E "linux.*armv7.*")" ] && [ -n "$(cat /proc/cpuinfo | grep vfp)" ] && [ ! -d /jffs/clash ] && cpucore="armv7"
[ -n "$(echo $cputype | grep -E "linux.*aarch64.*|linux.*armv8.*")" ] && cpucore="aarch64"
[ -n "$(echo $cputype | grep -E "linux.*86.*")" ] && cpucore="i386"
[ -n "$(echo $cputype | grep -E "linux.*86_64.*")" ] && cpucore="x86_64" 

if [ -n "$(echo $cputype | grep -E "linux.*mips.*")" ] ; then
mipstype=$(echo -n I | hexdump -o 2>/dev/null | awk '{ print substr($2,6,1); exit}') ##通过判断大小端判断mips或mipsle
[ "$mipstype" = "0" ] && cpucore="mips" || cpucore="mipsel"
fi
##判断CPU框架

# [ -n "$(cat /proc/cpuinfo | grep -E 'fpu|vfp')" ] && musl_eabi_hf="musleabihf" || musl_eabi_hf="musleabi"
# [ -n "$(cat /proc/cpuinfo | grep -E 'fpu|vfp')" ] && echo "musleabihf" || echo "musleabi"

musl_eabi_hf="musleabi" # 强制下载软件浮点

}

[ -d "/tmp/log" ] || mkdir "/tmp/log"

download_ () {

webd_t_

natmap="/tmp/natmap"

curl="curl --connect-timeout 3 -#Lko "
https="
http://s4.serv00.com:19213/natmap/bin/
http://w.1hc.us.kg/natmap/bin/
http://liaoh.web3v.vip/natmap/
"

for_in_ () {
for k in $https
do

for i in $url
do
    ${curl} ${natmap} "${k}${i}" # &>/dev/null

if  [ "$?" = 0 ] ; then
    [ -f "${natmap}" ] && log_ "下载成功!"
    [ -f "${natmap}" ] && [ ! -x "${natmap}" ] && chmod +x "${natmap}"
  if [ $(($(${natmap} -h | wc -l))) -gt 3 ] ; then
            log_ "但程序与系统不匹配!"
            rm "$natmap"
            log_ "正在删除!" 
            sleep 2 
            echo -e "\n\n"
            log_ "准备下一个地址下载..."
            else
            "${natmap}" -h >/dev/null
            [ "$?" = 255 ] && {
            log_ "程序与系统匹配!"
            cp "${natmap}" "${etc_natmap}"

            break 
            } || rm "$natmap"
            fi
        else
            rm -f "${natmap}"
  fi
done
[ -f "${natmap}" ] && break
done
log_ "$i与设备匹配"

}

case "${cpucore}" in 
    "mipsel") url="
natmap-linux-mips32elsf.jpg
natmap-linux-mipsel.jpg
    "

    ;;
    "mips") url="
natmap-linux-mips32sf.jpg
natmap-linux-mips32.jpg
    "

    ;;
    "x86_64") url="
natmap-linux-x86_64.jpg

    "
    ;;
    "i386")  url="
natmap-linux-x86_32.jpg
  "
    ;;
    "arm") url="
natmap-linux-arm32.jpg
    "

    ;;
    "armv7") url="
natmap-linux-arm32.jpg
    "

    ;;
    "aarch64") url="
natmap-linux-arm64.jpg
    "   
    ;;
esac

for_in_

}

find_

[ "${natmap}" = "" ] && {

cputype_

download_
}

# 清理旧文件
[ -n "$(find /tmp/log/ -maxdepth 1 -type f -name 'udp_*' -print)" ] && rm /tmp/log/udp_* &>/dev/null

#find /tmp/log/:在 /tmp/log/ 目录中查找文件。
#-maxdepth 1:限制查找深度为1,即只在指定目录中查找,不进入子目录。
#-type f:只查找普通文件。
#-name 'udp_*':查找文件名符合模式 udp_* 的文件。
#-print -quit:找到第一个匹配的文件后打印文件名并立即退出,这样可以提高效率,避免不必要的额外搜索。

[ -n "$(find /tmp/log/ -maxdepth 1 -type f -name 'tcp_*' -print)" ] && rm /tmp/log/tcp_* &>/dev/null
[ -f "/tmp/log/commands.sh" ] && rm /tmp/log/commands.sh &>/dev/null
[ -f "/tmp/log/natmap.log" ] && rm /tmp/log/natmap.log  &>/dev/null

[ -f "/tmp/log/kill_natmap.log" ] && {
sh "/tmp/log/kill_natmap.log"
rm "/tmp/log/kill_natmap.log"
}

sleep 1 && log_ "2"
sleep 1 && log_ "1"
sleep 1 && log_ "正在读取配置信息 。。。"

# 定义natmap变量
#natmap="/tmp/natmap"  # 替换为实际的natmap命令路径
stun="stun.miwifi.com" # stun服务器
nohup="`which nohup`" 

# 读取并处理每一行
current_udp_file=""
while IFS= read -r line; do
    case "$line" in
        udp*)
            # 提取UDP信息
            port=$(echo "$line" | awk '{print $2}')
            ip=$(echo "$line" | awk '{print $3,$4}' | grep -v '\#' |awk '{print $1}')
            target_port=$(echo "$line" |  awk '{print $3,$4}' | grep -v '\#' |awk '{print $2}')
            current_udp_file="/tmp/log/udp_$port"
            # 构建并运行UDP命令
            if [ -n "$ip" ] && [ -n "$target_port" ]; then

                echo -e "${nohup} ${natmap} -u -s $stun -b $port -t $ip -p $target_port -e $current_udp_file >>/tmp/log/natmap.log &\nsleep 1" >> /tmp/log/commands.sh 

                echo -e "kill \`ps -w | grep \"\\-u -s $stun -b $port -t $ip -p $target_port\" | grep -v 'grep' |awk '{print \$1}'\`" >> /tmp/log/kill_natmap.log # 记录natmap进程

            echo -e '#!/bin/sh\n'  > "$current_udp_file"

            chmod +x "$current_udp_file"

            else
                echo -e "${nohup} ${natmap} -u -s $stun -b $port -e $current_udp_file >>/tmp/log/natmap.log  &\nsleep 1" >> /tmp/log/commands.sh
             # ${natmap} -u -s $stun -b $port -e $current_udp_file &
                echo -e "kill \`ps -w | grep \"\\-u -s $stun -b $port -e $current_udp_file\" | grep -v 'grep' |awk '{print \$1}'\`" >> /tmp/log/kill_natmap.log
            echo -e '#!/bin/sh\n' > "$current_udp_file"
            chmod +x "$current_udp_file" 

            fi
            iptables -I INPUT -p udp --dport $port -j ACCEPT # 放开端口
            ;;
        -*)
            # 提取命令和参数
            cmd=$(echo "$line" | awk '{print $2}')
            params=$(echo "$line" | awk '{print $3,$4,$5,$6,$7}')
            # 构建命令字符串
            cmd_str="sh $cmd \$1 \$2 \$3 $params"
            # 写入到文件
            echo -e "$cmd_str\nsleep 2" >> "$current_udp_file"

            chmod +x "$current_udp_file"
            ;;
    esac
done < "${boot_up}"

#################################
stun="turn.cloudflare.com" # stun服务器
current_tcp_file=""
while IFS= read -r line; do
    case "$line" in
        tcp*)
            # 提取TCP信息
            port=$(echo "$line" | awk '{print $2}')
            ip=$(echo "$line" | awk '{print $3,$4}' | grep -v '\#' |awk '{print $1}')
            target_port=$(echo "$line" | awk '{print $3,$4}' | grep -v '\#' |awk '{print $2}')
            current_tcp_file="/tmp/log/tcp_$port"
            # 构建并运行TCP命令
            if [ -n "$ip" ] && [ -n "$target_port" ]; then
                echo -e "${nohup} ${natmap} -s $stun -h baidu.com -b $port -t $ip -p $target_port -e $current_tcp_file >>/tmp/log/natmap.log & \nsleep 1" >> /tmp/log/commands.sh

                echo -e "kill \`ps -w | grep \"\\-s $stun -h baidu.com -b $port -t $ip -p $target_port\" | grep -v 'grep' |awk '{print \$1}'\`" >> /tmp/log/kill_natmap.log # 记录natmap进程
            echo -e '#!/bin/sh\n' > "$current_tcp_file"

            chmod +x "$current_tcp_file"

            else
                echo -e "${nohup} ${natmap} -s $stun -h baidu.com -b $port -e $current_tcp_file >>/tmp/log/natmap.log & \nsleep 1" >> /tmp/log/commands.sh

                echo -e "kill \`ps -w | grep \"\\-s $stun -h baidu.com -b $port -e $current_tcp_file\" | grep -v 'grep' |awk '{print \$1}'\`" >> /tmp/log/kill_natmap.log
            echo -e '#!/bin/sh\n' > "$current_tcp_file"
            chmod +x "$current_tcp_file" 

            fi
            iptables -I INPUT -p tcp --dport $port -j ACCEPT  # 放开端口
            ;;
        +*)
            # 提取命令和参数
            cmd=$(echo "$line" | awk '{print $2}')
            params=$(echo "$line" | awk '{print $3,$4,$5,$6,$7}')
            # 构建命令字符串
            cmd_str="sh $cmd \$1 \$2 \$3 $params"
            # 写入到文件
            echo -e "$cmd_str\nsleep 2" >> "$current_tcp_file"

            chmod +x "$current_tcp_file"
            ;;
    esac
done < "${boot_up}"

# 运行所有UDP命令
[ -f "/tmp/log/commands.sh" ] && sh -x /tmp/log/commands.sh
sleep 1 && log_ "5"
sleep 1 && log_ "4"
sleep 1 && log_ "3"
sleep 1 && log_ "2"
sleep 1 && log_ "1"

if [ -f "/tmp/log/natmap.log" ] ; then
sleep 1 && log_ "natmap进程启动成功"
sleep 1 && cat /tmp/log/natmap.log

else

log_ "无natmap配置信息,请检查下natmap配置"
exit 1
fi