connect()到外部IP无法正常工作

时间:2016-09-22 22:15:16

标签: c linux sockets unix

我正在用C编写一个简单的服务器/客户端程序。我试图在IP上打开一个可以从任何地方访问的端口。目前,除127.0.0.1(本地计算机)和0.0.0.0(我不知道)之外,我的服务器不起作用。我已经指定了IP_TRANSPARENT选项,但客户端仍然在connect失败。

服务器:

// definitions, everything
struct addrinfo hints, *res;

hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

getaddrinfo("192.168.1.1","4001",&hints,&res);

sockfd = socket(res->ai_family,res->ai_socktype,res->ai_protocol);

setsockopt(sockfd,IPPROTO_IP,IP_TRANSPARENT,(void*)&sockopt,sizeof(sockopt));

bind(sockfd,res->ai_addr,res->ai_addrlen);
listen(sockfd,0);

addr_size = sizeof(ext_addr);
extfd = accept(sockfd,(struct sockaddr *)&ext_addr,&addr_size);

write(extfd,"Success",7);
// cleanup

客户端:

// definitions, everything
struct sockaddr_in serv_addr;

sockfd = socket(AF_INET,SOCK_STREAM,0);
setsockopt(sockfd,IPPROTO_IP,IP_TRANSPARENT,(void*)&sockopt,sizeof(sockopt));

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(4001);

inet_pton(AF_INET,"192.168.1.1",&serv_addr.sin_addr);

connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));  // fails here
read(sockfd,rcvBuf,sizeof(rcvBuf)-1);

// clean up

我的问题是什么?为方便起见,我已经取出了错误检查。服务器运行正常,我很确定。客户端运行正常,127.0.0.1。

1 个答案:

答案 0 :(得分:3)

通常,您不能bind()到不属于本地计算机的IP。但是,根据IP_TRANSPARENT文档:

  

IP_TRANSPARENT(自Linux 2.6.24起)
  设置此布尔选项可在此套接字上启用透明代理。 此套接字选项允许调用应用程序绑定到非本地IP地址,并以外部地址作为本地端点作为客户端和服务器运行。注意:这要求路由的设置方式是通过TProxy框路由到外部地址的数据包(即托管使用IP_TRANSPARENT套接字选项的应用程序的系统)。启用此套接字选项需要超级用户权限(CAP_NET_ADMIN功能)。

     

使用iptables TPROXY目标的TProxy重定向还要求在重定向的套接字上设置此选项。

您是否在网络上配置了必要的代理以方便IP_TRANSPARENT

让我们暂时忽略IP_TRANSPARENT,假装它不存在,因为它不常用。

127.0.0.1是IPv4环回地址。如果将服务器绑定到此服务器,则只能连接到127.0.0.1的本地IPv4客户端才能连接。

0.0.0.0是IPv4通配符地址。如果将服务器绑定到此服务器,则套接字将侦听所有本地IPv4地址。本地计算机或网络上的任何客户端都可以连接到属于服务器计算机的任何IPv4地址。

192.168.1.1是特定的IPv4地址。如果将服务器绑定到此服务器,则套接字将仅侦听该IPv4地址。本地计算机或网络上的任何客户端都只能连接到该IPv4地址。

如果您的客户端和服务器位于同一台计算机上,则客户端可以连接到服务器绑定的任何本地IP。

如果您的客户端和服务器不在同一台计算机上,则bur位于同一网络上,如果服务器绑定到该网络可访问的IP,则客户端可以连接到服务器。这意味着绑定到0.0.0.0192.168.1.1,然后连接到192.168.1.1

如果您的客户端和服务器不在同一网络上,则仅当服务器位于具有公共IP的路由器后面时,客户端才能连接到服务器。服务器必须绑定到路由器可访问的本地网络IP,并且路由器必须配置为将其公共IP上给定端口上的入站连接转发到服务器的内部IP。这意味着将服务器绑定到0.0.0.0192.168.1.1,转发到服务器内部IP的连接,然后连接到路由器的公共IP。