MD XF MD XF - 21 days ago 6
Linux Question

connect() to external IP not working

I'm writing a simple server/client program in C. I'm trying to open a port on an IP that can be accessed from anywhere. Currently, my server does not work for anything but

127.0.0.1
(local machine) and
0.0.0.0
(I don't know). I've specified the
IP_TRANSPARENT
option and all that but the client still fails at
connect
.

server:

// 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


client:

// 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


What's my issue? I have taken out the error checking for the sake of convenience. The server runs fine, I am sure of that. The client runs fine with 127.0.0.1.

Answer

Typically, you cannot bind() to an IP that does not belong to the local machine. However, per the IP_TRANSPARENT documentation:

IP_TRANSPARENT (since Linux 2.6.24)
Setting this boolean option enables transparent proxying on this socket. This socket option allows the calling application to bind to a nonlocal IP address and operate both as a client and a server with the foreign address as the local endpoint. NOTE: this requires that routing be set up in a way that packets going to the foreign address are routed through the TProxy box (i.e., the system hosting the application that employs the IP_TRANSPARENT socket option). Enabling this socket option requires superuser privileges (the CAP_NET_ADMIN capability).

TProxy redirection with the iptables TPROXY target also requires that this option be set on the redirected socket.

Have you configured the necessary proxying on your network to facilitate IP_TRANSPARENT?

Let's ignore IP_TRANSPARENT for a moment, pretend it does not exist, as it is not commonly used.

127.0.0.1 is the IPv4 loopback address. If you bind your server to this, only local IPv4 clients that connect to 127.0.0.1 will be able to connect.

0.0.0.0 is an IPv4 wildcard address. If you bind your server to this, the socket will listen on all local IPv4 addresses. Any client on the local machine or network can connect to any IPv4 address that belongs to the server machine.

192.168.1.1 is a specific IPv4 address. If you bind your server to this, the socket will listen on that IPv4 address only. Any client on the local machine or network can connect to only that IPv4 address.

If your client and server are on the same machine, the client can connect to any local IP that the server is bound to.

If your client and server are not on the same machine, bur are on the same network, the client can connect to the server if the server is bound to an IP that is accessible to that network. That means binding to 0.0.0.0 or 192.168.1.1, and then connecting to 192.168.1.1.

If your client and server are not on the same network, the client can connect to the server only if the server is behind a router with a public IP. The server must be bound to a local network IP that is accessible to the router, and the router must be configured to forward inbound connections on a given port on its public IP to the server's internal IP. That means binding the server to 0.0.0.0 or 192.168.1.1, forwarding connections to the server's internal IP, and then connecting to the router's public IP.