小 |
|||
(未显示同一用户的1个中间版本) | |||
第1行: | 第1行: | ||
+ | [[Category:脚本]] | ||
upnpsync是个小脚本。主要用来同步路由器的UPnP转发信息和Cable Modem的转发信息。 | upnpsync是个小脚本。主要用来同步路由器的UPnP转发信息和Cable Modem的转发信息。 | ||
第13行: | 第14行: | ||
于是搞了个小脚本,可以根据无线路由上UPnP的端口转发信息,在Cable Modem上用UPnP自动配好对应的端口转发~ | 于是搞了个小脚本,可以根据无线路由上UPnP的端口转发信息,在Cable Modem上用UPnP自动配好对应的端口转发~ | ||
+ | |||
+ | 后来又加了个小功能,会自动把在本地找不到的Modem上的转发信息干掉,这样在程序结束后能自动清理。 | ||
<source lang='perl'> | <source lang='perl'> | ||
第19行: | 第22行: | ||
sub get_external($) { | sub get_external($) { | ||
my ($url) = @_; | my ($url) = @_; | ||
− | $_ = `upnpc -u $url -s | grep External`; | + | $_ = `/usr/local/bin/upnpc -u $url -s | grep External`; |
/ExternalIPAddress = ([0-9\.]+)+/; | /ExternalIPAddress = ([0-9\.]+)+/; | ||
第28行: | 第31行: | ||
sub get_fwd_list($) { | sub get_fwd_list($) { | ||
my ($url) = @_; | my ($url) = @_; | ||
− | $_ = `upnpc -u $url -l | grep '\\\->'`; | + | $_ = `/usr/local/bin/upnpc -u $url -l | grep '\\\->'`; |
− | + | ||
+ | @result = (); | ||
foreach $line(split(/\n/)) | foreach $line(split(/\n/)) | ||
第74行: | 第78行: | ||
$found = 1; | $found = 1; | ||
$good_pair = $modem_pair; | $good_pair = $modem_pair; | ||
+ | $modem_pair->{"router_pair"} = $router_pair; | ||
if ($modem_pair->{"localip"} ne $router_external) | if ($modem_pair->{"localip"} ne $router_external) | ||
{ | { | ||
第85行: | 第90行: | ||
{ | { | ||
print "... Not found!\n"; | print "... Not found!\n"; | ||
− | $ret = `upnpc -u $modem_upnp -a $router_external $extport $extport $proto`; | + | $ret = `/usr/local/bin/upnpc -u $modem_upnp -a $router_external $extport $extport $proto`; |
if ($? != 0) | if ($? != 0) | ||
{ | { | ||
第98行: | 第103行: | ||
} | } | ||
} | } | ||
+ | |||
+ | foreach $modem_pair (@modem_fwd) | ||
+ | { | ||
+ | if (not $modem_pair->{"router_pair"}) | ||
+ | { | ||
+ | $proto = $modem_pair->{'proto'}; | ||
+ | $extport = $modem_pair->{'extport'}; | ||
+ | print "Found extra modem pair: $proto $modem_external:$extport -> $modem_pair->{'localip'}:$modem_pair->{'localport'}\n"; | ||
+ | $ret = `/usr/local/bin/upnpc -u $modem_upnp -d $extport $proto`; | ||
+ | if ($? != 0) | ||
+ | { | ||
+ | print "ERROR deleting modem pair!\n"; | ||
+ | print $ret; | ||
+ | } else { | ||
+ | print "Extra pair deleted.\n"; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
</source> | </source> | ||
2011年12月4日 (日) 21:36的最新版本
upnpsync是个小脚本。主要用来同步路由器的UPnP转发信息和Cable Modem的转发信息。
最近在Time Warner的Cable Modem后面搞了个无线路由。之后又给这个路由刷了dd-wrt。 虽然一切都不错,但是对于要用UPnP进行端口转发的程序来说,因为它只会通过UPnP让路由转发,没有通知Cable Modem,导致它即使设置了端口转发,外网还是无法连接到它监听的端口。
网络结构是:
Internet <-> <74.73.xx.xx> [Time Warner Cable Modem] <192.168.0.1> <-> <192.168.0.x> [DLink Wireless Router] <192.168.1.1> <-> <192.168.1.x> [My Computer]
Time Warnar那个破Modem居然连配置都没法配,所有配置界面都锁死了,直接filter了23,80端口……
幸好它居然留着UPnP。端口扫描扫出来5555和8081俩端口,尝试了一下,http://192.168.0.1:5555/ 就是它的UPnP地址……
于是搞了个小脚本,可以根据无线路由上UPnP的端口转发信息,在Cable Modem上用UPnP自动配好对应的端口转发~
后来又加了个小功能,会自动把在本地找不到的Modem上的转发信息干掉,这样在程序结束后能自动清理。
#!/usr/bin/perl
sub get_external($) {
my ($url) = @_;
$_ = `/usr/local/bin/upnpc -u $url -s | grep External`;
/ExternalIPAddress = ([0-9\.]+)+/;
return $1;
}
sub get_fwd_list($) {
my ($url) = @_;
$_ = `/usr/local/bin/upnpc -u $url -l | grep '\\\->'`;
@result = ();
foreach $line(split(/\n/))
{
if ($line =~ m/\s*(\d+)\s+([A-Za-z]+)\s+(\d+)->([0-9\.]+):(\d+)\s+'(.*)'\s+'(.*)'/)
{
# print "No.$1 Proto:$2 Ext.Port:$3 LocalIP:$4 LocalPort:$5 Desc:$6 Note:$7\n";
$result[$1] = {"proto"=>$2, "extport"=>$3, "localip"=>$4, "localport"=>$5, "desc"=>$6, "note"=>$7};
}
}
return @result;
}
$router_ip = "192.168.1.1";
$modem_ip = "192.168.0.1";
$router_upnp = "http://192.168.1.1:1780/InternetGatewayDevice.xml";
$modem_upnp = "http://192.168.0.1:5555/";
$router_external = get_external($router_upnp);
$modem_external = get_external($modem_upnp);
@router_fwd = get_fwd_list($router_upnp);
@modem_fwd = get_fwd_list($modem_upnp);
print "Modem External IP: $modem_external\n";
print "Router External IP: $router_external\n";
foreach $router_pair (@router_fwd)
{
$proto = $router_pair->{"proto"};
$extport = $router_pair->{"extport"};
$found = 0;
$good_pair = "";
print "Router: $proto $router_external:$extport -> $router_pair->{'localip'}:$router_pair->{'localport'}";
foreach $modem_pair (@modem_fwd)
{
if ($modem_pair->{"proto"} eq $proto
and $modem_pair->{"localport"} == $extport)
{
$found = 1;
$good_pair = $modem_pair;
$modem_pair->{"router_pair"} = $router_pair;
if ($modem_pair->{"localip"} ne $router_external)
{
$modem_local = $modem_pair->{"localip"};
print "\nWarning: Modem forwarding to strange IP: $modem_local\n";
}
}
}
if (not $found)
{
print "... Not found!\n";
$ret = `/usr/local/bin/upnpc -u $modem_upnp -a $router_external $extport $extport $proto`;
if ($? != 0)
{
print "ERROR adding port forwarding pair!\n";
print $ret;
} else {
print "Added forwarding $proto $modem_external:$extport->$router_external:$extport\n";
}
} else {
print "... Found\n";
print "Modem: $good_pair->{'proto'} $modem_external:$good_pair->{'extport'} -> $good_pair->{'localip'}:$good_pair->{'localport'}\n";
}
}
foreach $modem_pair (@modem_fwd)
{
if (not $modem_pair->{"router_pair"})
{
$proto = $modem_pair->{'proto'};
$extport = $modem_pair->{'extport'};
print "Found extra modem pair: $proto $modem_external:$extport -> $modem_pair->{'localip'}:$modem_pair->{'localport'}\n";
$ret = `/usr/local/bin/upnpc -u $modem_upnp -d $extport $proto`;
if ($? != 0)
{
print "ERROR deleting modem pair!\n";
print $ret;
} else {
print "Extra pair deleted.\n";
}
}
}
这里的router_ip和modem_ip都是对内IP,应该都很清楚。
router_upnp和modem_upnp都是对应设备的UPnP地址。可以通过在计算机与该设备直连的情况下,用upnpc -l发现出来(自动发现还是不太靠谱啊……)。