connect() to external IP not working - c

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.

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.

Related

C socket Client communicate with Server outside LAN without knowing IP address

I write a small game using socket in which multiple clients join the game, everything works in the LAN. Now I want to extend to clients outside LAN, what I wonder is: if I don't know the IP address of the client then will the program work?
Inside LAN I use:
char *ip = "127.0.0.1";
The client needs to know the server's IP in order to connect to it.
If the client and server run on the same machine, the server can listen on 127.0.0.1 and the client can connect to that IP.
If the client and server run on the same LAN, the server needs to listen on the NIC that is connected to the LAN, and the client can connect to the server's LAN IP.
If the client is running on a different network and wants to connect to the server over the Internet, the client must connect to the server's public Internet IP, as assigned by the server's ISP. And if the server is running behind a NAT router, the public IP is assigned to the router and not the server directly, so the router must have port forwarding configured to route incoming connections to the server machine on the router's LAN.
If the client doesn't know the IP to connect to, the server will need to publish its IP somewhere that the client can query it, such as via DNS, a website, a central public server that all clients connect to for relaying, etc.

Access to server without writing port after address

I'm creating my custom http server in C. sockaddr_in looks like this:
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(8080);
my_addr.sin_addr.s_addr = htol(INADDR_ANY);
And my question is how I can send my request without writing port after address.
For example 192.168.1.100 instead of 192.168.1.100:8080 or mydomain.loc instead of mydomain.loc:8080
how I can send my [HTTP] request without writing port after address[?]
You cannot communicate with a TCP endpoint without designating a specific port. Various kinds of services have conventional (default) ports, however, and oftentimes client software will use a service's conventional port if the user does not explicitly specify one.
The conventional port for the HTTP protocol is 80. If your server runs on that port, then it is likely that HTTP user agents such as web browsers will not require you to specify that port; instead they will silently insert it for you. You will need root / administrator privilege on the server machine to run the server software on port 80, or on any other port less than 1024.
If you want to access your custom server with any web browser then you must have to specify the listening port of your custom server because every browser will consider a server listening on port 80 on the address (URL) you provided.
how I can send my [HTTP] request without writing port after address[?]
And if you want to provide only the host IP address and using the 8080 port as default listening port of your server, you can make a simple custom client. Pass the host URL i.e. 192.168.1.100 to that client. In the body of client, connect the socket to 192.168.1.100 and 8080 address. Client will send query to your custom server and will save the reply in .html file. You can then open this file with browser.

Get IP address of the client in C sockets

How can I get the ip address of the client of which my server is connected to?
Here is how I accept incoming clients:
newsockfd = accept(sockfd, (struct sockaddr*)&clt_addr, &addrlen);
I tried the following:
printf("ip is: %s\n", inet_ntoa(clt_addr.sin_addr));
But I am getting 127.0.0.1 which is not my ip address. Could it have something to do with me using localhost to test my client and server?
Could it have something to do with me using localhost to test my client and server?
Yes. If you connect to a server on localhost the client will also be localhost. This connection is not happening over the Internet, there is no network hardware involved, the client packets will come from localhost. This is known as loopback and occurs entirely in software.
If the client were to connect to the server using the server's external IP address it will have to do a connection via external routing and thus require a routable IP address. For example, I can connect to a server on localhost, but I cannot using my routable IP address because my router blocks incoming connections.

how to assign a local port number to a socket?

I create a server at port 1234 of localhost. In the client code, I initiated a struct sockaddr_in server_addr and filled it with the server's IP address and port number. When I try to connect a client to the server, I get "Address already in use":
bind(client_sockfd, server_addr, sizeof server_addr)
So the OS thinks that I was trying to create another server socket with the same address and port number. In this case, how can I tell the OS that server_addr is the other endpoint I want to connect to and that it finds another port number for the client's socket?
You need to use bind() only for the server and in the client use
int connect(int socket, const struct sockaddr *address,
socklen_t address_len);.
See this tutorial for information about sockets in Linux:
http://www.linuxhowtos.org/C_C++/socket.htm
you use connect(client_sockfd, server_addr, sizeof(..)) to tell OS that my client socket should connect to this server address.
If it is UDP socket, you can also use sendto(client_sockfd, ... server_addr) call to specify that the packet should go to this server address.

I am getting error in IPv6 socket connection

My server is creating a IPV6 socket.
On client I am creating a IPV4 socket.
Now, In the connect API on client side I am passing the socket descriptor of IPV4 and IPV6 address structure.
INET_connect( sock,(SocketAddress *)in6_addr,(int)sizeof( sockaddr_in6 ) ) == 0 )
where
struct sockaddr_in6 in6_addr;
I am getting error in connection. Is it due to this or some other reason ?
Please note that my server is IPV6(having an IPV6 address)
You must use an IPV6 socket to connect to an IPV6 address, or use a tunneling service which will translate traffic from IPV4 addresses to and from IPV6 addresses.
On client I am creating a IPV4 socket
Why? Don't do that. If your client program creates an AF_INET socket (or is running on ip4-only OS) then there is nothing you can do on the client side to make such connection happen.
If you just have to do so - then it is the server that should be adapted to handle IPv4 clients.
Server might be able to accept a connection request from ip4 client - but it can only happen if server side disables IPV6_V6ONLY socket option and, obviously, if server's OS allows that. In this case ip6 server will see the ip4 client via ipv4-mapped ipv6 address.

Resources