(您搜索到这个,自然是遇到了类似的问题,自然是知道upnp是什么,所以我不介绍它了)
我使用的环境是:
windows10 + openwrt-19.07 + miniupnpd-2.2.1
前言:
我一开始使用的是miniupnpd-2.1.2019,使用这个版本时,是可以成功内网穿透的,换成2.2.1版本后,失效了,搜索过很多,基本都是降miniupnpd的版本,因为某些原因,我又必须得使用2.2.1,所以,研究了一下,有点点小收获,分享给同样陷入迷茫的你。
1. 抓包发现,只有电脑的M-Search数据包,没有路由器发出来的"notify"组播包
解决方案:
mcpd配置中添加:
igmp-mcast-snoop-exceptions 224.0.255.135/255.255.255.255 239.255.255.250/255.255.255.255
igmp-snooping-interfaces br-lan
可以"ps | grep mcpd" 或者查看"/etc/init.d/mcpd"文件,看看mcpd的配置文件是谁
如果添加后还是不起作用,可以看看 ipv4 多播转发功能是否在所有网络接口上启用
查看方式:
sysctl net.ipv4 | grep mc_forwarding
理论上,"net.ipv4.conf.all.mc_forwarding"和“net.ipv4.conf.br-lan.mc_forwarding”是要打开的
2. 调用/etc/miniupnpd/iptscript.sh 失败
https://miniupnp.tuxfamily.org/files/
win10用上面的网站,下载下面的upnpc,解压并把它加入电脑的环境变量中
win + r ,cmd下输入下面的指令
upnpc-shared.exe -l #查看已经添加的端口映射
upnpc-shared.exe -a 192.168.1.200 1234 5678 TCP #添加规则(通过wan口的5678端口可以访问lan口1.200 ip的1234端口)
-a: 添加 (-D是删除)
192.168.1.200 : pc的ip
1234 : pc的内部端口
5678 : 外部端口
这里有个小注意:
1. 使用 upnpc-shared.exe这种方式,最好断开pc的其他网线
2. 使用 upnpc-shared.exe这种方式,需要设置任意外网ip
uci set upnpd.config.external_ip='任意一个外网的ip'
uci commit
然后重启miniupnpd
为什么需要外网ip,可以查看下面的网站的说明(反正我是看它加所以我加的)
https://forum.openwrt.org/t/miniupnpd-problem-getexternalipaddress-error-unable-to-add-forward-rule/61008
打开miniupnpd的调试(加 ‘-d’ )可以看到,port是被允许的,但是iptscript.sh这个脚本调用失败
解决方案:
iptscript.sh这个脚本来自于“opensync”的core里面,也可以自己编辑一个,大致的内容是用于实现iptables规则的
win10 执行这个: upnpc-shared.exe -a 192.168.1.200 1234 5678 TCP
与之对应要在 iptscript.sh下实现:
iptables -t nat -A MINIUPNPD -p tcp -m tcp --dport 5678 -j DNAT --to-destination 192.168.1.200:1234
iptables -t nat -A MINIUPNPD-POSTROUTING -s 192.168.1.200/32 -p tcp -m tcp --sport 1234 -j MASQUERADE --to-ports 5678
3. 实现了 iptscript.sh脚本后,你会发现,手动执行上面的两条iptables规则,是可以映射了,但,miniupnpd实现不了
win 10 执行 upnpc-shared.exe -a 192.168.1.200 1234 5678 TCP
miniupnpd的log里面有如下内容:
我在iptscript.sh里面加入“id”命令,确定它是root权限执行
miniupnpd调用iptscript.sh也很简单
int iptscript_exec_a(const char * const argv[])
{
int status;
pid_t cpid = fork();
if (cpid != 0)
{
if (waitpid(cpid, &status, 0) != cpid || !WIFEXITED(status))
{
return -1;
}
return WEXITSTATUS(status);
}
execvp(IPTSCRIPT_PATH, (char * const *)argv);
syslog(LOG_ERR, "Error executing: %s %s", IPTSCRIPT_PATH, argv[1]);
return 0;
};
fork创建子进程后,通过execvp去替换子进程,miniupnpd是root权限运行,调用iptscript.sh脚本应该也是root权限,事实上我加入“id”命令也确认iptscript.sh脚本是root权限,甚至我在“iptscript.sh”脚本里加了20秒延迟,ps查看iptscript.sh的运行状态也能看到是root权限。
咋会这样?
遍历了下代码,可以看到有个capability机制在降权
把这部分内容屏蔽或者在capng_updatev里加入适量的权限,就可以解决了
4. 来到这一步,使用win 10的upnpc,是可以内网穿透了
但,“网络邻居”里面的upnp设备,应该有个“常规”->“设置”的页面可以添加端口的
目前卡在这里,它没有这个页面,后来人如果有能力,可以试着去解决这个问题
最后附上:
win7/10 是不support IGDv2的,去网页里把它关闭掉IGDv2,勾选下面的框让它运行IGDv1
其次,你也可以试着关闭Makefile里面的"--iptscript"
因为我这边是要运行opensync,需要用到“--iptscript”
开了它以至于才有上面的一系列的问题