|
现在我的网络结构是这样的:
路由器通过DHCP自动获得外网IP地址,路由器的内网地址是:192.168.1.1
我的机器接到路由器上,地址是192.168.1.102
ifconfig命令查看的结果如下:
eth0 Link encap:Ethernet HWaddr 00:14:2A5:09:70
inet addr:192.168.1.102 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::214:2aff:fed5:970/64 Scope ink
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:94053 errors:0 dropped:0 overruns:0 frame:0
TX packets:66192 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:123236029 (117.5 MiB) TX bytes:6348095 (6.0 MiB)
Interrupt:21 Base address:0x4000
lo Link encap ocal Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:181 errors:0 dropped:0 overruns:0 frame:0
TX packets:181 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:34754 (33.9 KiB) TX bytes:34754 (33.9 KiB)
iptables -L 命令执行的结果如下:
#iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
RH-Firewall-1-INPUT all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
RH-Firewall-1-INPUT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain RH-Firewall-1-INPUT (2 references)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT icmp -- anywhere anywhere icmp any
ACCEPT esp -- anywhere anywhere
ACCEPT ah -- anywhere anywhere
ACCEPT udp -- anywhere 224.0.0.251 udp dpt:mdns
ACCEPT udp -- anywhere anywhere udp dpt:ipp
ACCEPT tcp -- anywhere anywhere tcp dpt:ipp
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
现在我要写一个程序,用UPnP的功能实现端口的自动映射,
在windows下程序我已经按照以下的步骤实现了:
(1)XP操作系统安装UPnP支持组件
(2)开启UPnP和SSDP服务
(3)设置TP-Link路由器,转发规则->UPnP设置->开启uPnP
(4) 程序加入对UPnP的支持
现在我要在linux下实现这个功能,路由器的uPnP我已经开启了,关键是如何实现操作系统对UPnP的支持, 我的操作系统信息:
# uname -a
Linux cnhnyu 2.6.20-1.2962.fc6 #1 SMP Tue Jun 19 19:27:14 EDT 2007 i686 i686 i386 GNU/Linux
我已经安装了linuxigd-1.0,upnpd这个程序也可用
我查了一些资料,要求用iptables开启NAT,然后作以下的配置:
配置
1. 增加多播路由
# route add -net 239.0.0.0 netmask 255.0.0.0 eth0
2. 为iptables建议一个软链接
# cd /usr/sbin
# ln -s /sbin/iptables ./
启动UPnP
# upnpd ppp0 eth0
诊断UPnP运行状态
# tail /var/log/messages
如果能够看到:
Dec 14 16:01:49 doorway -- MARK --
Dec 14 16:02:15 doorway upnpd:
The Linux UPnP Internet Gateway Device Ver
0.92 by Dime (dime@gulfsales.com)
Dec 14 16:02:15 doorway upnpd:
Special Thanks for Intel's Open Source SDK
and original author Genmei Mori's work.
则说明UPnP已经成功启动。
他这里用的是启动UPnP用的是以下命令:
# upnpd ppp0 eth0
这里是拨号网络,我按照这种方法试了一下,但是不行,于是我改为
# upnpd dhcp eth0
但是仍然不行,现在实在是找不到好的解决方法。
????请问我该如何正确的开启uPnP的功能以及如何用iptables来设置NAT ?
我写了一个测试程序,代码如下:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define SEARCH_TARGET ("urn:schemas-upnp-org:device:InternetGatewayDevice:1")
#define UPNPADDR 0xFAFFFFEF /* 239.255.255.250 */
#define UPNPPORT 1900
int GetIP_v4_and_v6_linux(int family, char *address, int size);
char szLocalIP[20] = {0};
int main(void)
{
char szFindMsg[256] = {0};
char buffer[10240] = {0};
int s, nLen;
struct sockaddr_in addr;
GetIP_v4_and_v6_linux(AF_INET, szLocalIP, sizeof(szLocalIP) );
printf("%s\n", szLocalIP);
sprintf(szFindMsg, "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: %d\r\nST: %s\r\n\r\n", 6, SEARCH_TARGET);
s = socket(AF_INET, SOCK_DGRAM, 0);
fcntl(s,F_SETFL, O_NONBLOCK);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(UPNPPORT);
addr.sin_addr.s_addr = UPNPADDR;
sendto(s, szFindMsg, strlen(szFindMsg), 0, (struct sockaddr *)&addr, sizeof(addr));
printf("Send SSDP Request:\n%s\n", szFindMsg);
sleep(1);
nLen = recv(s, buffer, sizeof(buffer), 0);
fprintf(stderr, "nLen = %d, %s\n", nLen, strerror(errno));
close(s);
printf("Recv SSDP Response:\n%s\n", buffer);
return 0;
}
int GetIP_v4_and_v6_linux(int family, char *address, int size)
{
struct ifaddrs *ifap0, *ifap;
char buf[NI_MAXHOST];
char *interface = "eth0";
struct sockaddr_in *addr4;
struct sockaddr_in6 *addr6;
int ret;
if( NULL == address ) {
return -1;
}
if(getifaddrs(&ifap0)) {
return -1;
}
for( ifap = ifap0; ifap != NULL; ifap=ifap->ifa_next){
if(strcmp(interface, ifap->ifa_name) != 0) continue;
if(ifap->ifa_addr==NULL) continue;
if ((ifap->ifa_flags & IFF_UP) == 0) continue;
if(family != ifap->ifa_addr->sa_family) continue;
if(AF_INET == ifap->ifa_addr->sa_family) {
addr4 = (struct sockaddr_in *)ifap->ifa_addr;
if ( NULL != inet_ntop(ifap->ifa_addr->sa_family,
(void *)&(addr4->sin_addr), buf, NI_MAXHOST) ){
if(size <= strlen(buf) ) break;
strcpy(address, buf);
freeifaddrs(ifap0);
return 0;
}
else break;
}
else if(AF_INET6 == ifap->ifa_addr->sa_family) {
addr6 = (struct sockaddr_in6 *)ifap->ifa_addr;
if(IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)){
continue;
}
if(IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)){
continue;
}
if(IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)){
continue;
}
if(IN6_IS_ADDR_UNSPECIFIED(&addr6->sin6_addr)){
continue;
}
if(IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)){
continue;
}
if ( NULL != inet_ntop(ifap->ifa_addr->sa_family,
(void *)&(addr6->sin6_addr), buf, NI_MAXHOST) ){
if(size <= strlen(buf) ) break;
strcpy(address, buf);
freeifaddrs(ifap0);
return 0;
}
else break;
}
}
freeifaddrs(ifap0);
return -1;
}
如果linux操作系统支持uPnP而且路由器开启了uPnP功能的话,那么这个程序就能收到路由器的反馈消息,但是现在消息收不到,很可能是操作系统现在还不支持uPnP,所以我现在要解决的就是上面要说的问题。
希望对uPnP, iptables以及NAT熟悉的兄弟给个建议或者解决的方法,在此先行谢过了。
原帖发在:http://bbs.chinaunix.net/viewthr ... page%3D1#pid7261137 |
|