Personal tools
You are here: Home 资源中心 原始部落 Happy Hacking 让 Linux NAT 服务器支持 UPnP
Log in


Forgot your password?
New user?
 
Document Actions

让 Linux NAT 服务器支持 UPnP

by Xin Zhen posted on May 02, 2005 06:52 AM last modified May 05, 2005 02:17 AM —
通过 UPnP,一个希望能跨越 NAT 的应用程序或者设备,能够主动去找到一个同样支持 UPnP 协议的 NAT 路由器,并与之协商,在其帮助下将相应端口映射到自己,从而使外网能够访问到自己。这样的协商工作是程序和设备自行完成的,完全无需用户的参与配置。

什么是 NAT

NAT,即网络地址转换,是一种路由技术。通过它可以有2个用途:它可以让你在只有一个公网 IP 地址的情况下,带一整个局域网上网(即代理服务器);同时,躲在 NAT 后方的电脑,由于不直接和 Internet 相连,因而不会遭受黑客和蠕虫的攻击(即防火墙)。国内用户第一种用途居多。

NAT 带来的问题

NAT 以上的2个特征是一起来的,就是说如果你采用了 NAT 技术用一台电脑带多台上网,那么 NAT 后面的这多台电脑都与 Internet 不直接相连,因而你也无法在 NAT 后面假设一个网站或者开设个人 FTP 站点等。

即使你不当服务器,也有一些应用无法穿越 NAT, 比如:

  • MSN Messenger Audio & Video,跨越 NAT 后就不能通音频视频了
  • BT 下载,作为对等网络,如果只能让你连别人,别人不能连你,便“对等”不起来了

传统解决方案

为了解决 NAT 穿透问题,出现了许多技术。比如端口映射和 ALG, 应用级网关等。这些是“透明穿透”,即应用程序不用更改,而在路由层面上动手脚。这类方案虽有这些好处,却有缺点,即需要大量的人工配置——只有一切配置妥当,程序才能开始运行。不能自适应使得只有专业人士才能完成这项工作。

新一代解决方案:UPnP

为了减少用户的工作量,让配置自动进行,新一代解决方案 UPnP 出现了。

UPnP 是让网络上任意2个设备能够发现对方,并进行通讯的一项技术。通过这项技术,一个希望能跨越 NAT 的应用程序或者设备,能够主动去找到一个同样支持 UPnP 协议的 NAT 路由器,并与之协商,在其帮助下将相应端口映射到自己,从而使外网能够访问到自己。

这样的协商工作是程序和设备自行完成的,完全无需用户的参与配置。因而无论该用户使用什么牌子的路由器,什么上网方式,也无论内网中 IP 地址是自动分配还是手动填写,一切都将在幕后自动搞定。

但显然,这样的方案不是“透明”的,应用程序和相关设备都必须支持 UPnP 协议才行。目前,支持 UPnP 的应用有微软的 MSN Messenger 和 BT 下载软件 Azureus 等。而 LinkSys, Netgear 等设备厂商的路由器等也已开始逐渐支持 UPnP 协议了。

而 Linux 上同样出现了解决方案,而且秉承 Linux 的一贯风格,是全免费的。(感谢 Intel 公司提供的技术)

在 Linux 上安装 UPnP 支持

以下我们就往 Linux 上安装 UPnP 支持。我们假设该 Linux 使用拨号上网,外网接口是 ppp0 ,内网接口是 eth0 。它基于 Linux Kernel 2.4.x,已经启用 iptables 设定了 NAT。

  1. http://sourceforge.net/projects/upnp/ 下載UPnP SDK For Linux. 當前版本為1.04
  2. 解压缩 tar -xzf upnpsdk-1.0.4.tar.gz
  3. 修改 upnpsdk 源程序中的 src/ssdp/ssdplib.c

    將第406行 從:

        SelfAddr.sin_addr.s_addr = inet_addr(SSDP_IP);
    

    改為:

        SelfAddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    

  4. 編譯 upnpsdk:
        # make
        # make install
    
  5. http://sourceforge.net/projects/linux-igd/ 下載Linux GID 程序﹐當前版本是 0.92
  6. 解压缩 # tar -xzf linuxigd-0.92.tgz
  7. 編譯 Linux IGD:
        # cd /usr/src/linux-gid
        # make
        # make install
    
  8. 增加广播路由
        route add -net 239.0.0.0 netmask 255.0.0.0 eth0
    

    这里 eth0 是指内网的网卡

  9. 给 iptables 命令增加一个符号链接

    大多数系统的 iptables 都位于 /sbin/ ,为了让 UPnP 正常工作,需要在 /usr/sbin/ 下放一个符号链接:

        # cd /usr/sbin
        # ln -s /sbin/iptables .
    

  10. 启动 UPnP:
        upnpd ppp0 eth0
    

这里 ppp0 指的是外网接口,而 eth0 指的是内网接口。

至此,UPnP 的安装已经完成了。接下来我们来调试一下。

诊断 UPnP 的工作

现在,我们执行这样一条命令:

    # tail /var/log/messages

如果看见以下文字,就表示 UPnP 已经起来了:

    May  2 16:01:49 doorway -- MARK --
May  2 16:02:15 doorway upnpd: The Linux UPnP Internet Gateway Device Ver 0.92 by Dime (dime@gulfsales.com)
May  2 16:02:15 doorway upnpd: Special Thanks for Intel's Open Source SDK and original author Genmei Mori's work.

接下来,我们执行这样一条命令:

    # tail /var/log/debug -f

然后,我们开启 Azureus,如果你装了的话。如果 UPnP 正常,我们应该看到以下字样:

    May  2 16:56:33 doorway upnpd: AddPortMap: RemoteHost: (null) Prot: 17 ExtPort: 6881 Int: 192.168.0.10.6881 
May  2 16:56:33 doorway upnpd: AddPortMap: RemoteHost: (null) Prot: 6 ExtPort: 6881 Int: 192.168.0.10.6881 
May  2 16:56:34 doorway upnpd: AddPortMap: RemoteHost: (null) Prot: 6 ExtPort: 6969 Int: 192.168.0.10.6969 

这些文字,便是 Azureus 向 Linux UPnP 请求进行端口映射了。只要看到这样的字样,就说明 UPnP 已经完全工作起来了。看看,你的 Azureus 是不是已经显示出了表示“完全连通”的绿色图标?

参考引用

写作本文参考了以下文章:

"使用 IGD(Upnp)解決 MSN 語音聊天問題":http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=proxy&Number=375929&page=&view=&sb=&o= , by CM_MPE, from LinuxForum

UPnP on your Linux 2.4 firewall how-to , by bijl

UPNP的效率不行,大量用户时根本无法使用。

Posted by Anonymous User at Sep 06, 2005 10:36 PM
我在一个300用户的小区的接入系统服务器中使用过UPNP,一开起来该进程CUP Usage 达到了99%,更夸张的是连控制台进取都反应巨慢,根本无法使用。所以UPNP只能用于用户数量很少的情况。

这是因为一个内存泄漏bug导致的

Posted by Anonymous User at Dec 05, 2005 03:16 AM
问题可能在upnpd处理UPnP客户端获取网关状态的请求执行路径上,客户端每发一个获取状态的请求给upnpd都会导致一次内存泄漏,超过一定程度之后,内存用尽,CPU利用率会飙升。