Why can I access nginx but not a C server socket in my server at home?

1

I have a Debian server machine at home with NGINX. Right now it is only serving the default index.html that installs along with nginx. I got myself a hostname in Dynu and got TLS certificates with Let's Encrypt

I can perfectly access my default nginx website on the web browser using my hostname and everything is working fine.

But I need to implement a simple server socket in C in this Debian server listening on port 8080 and connect to it with a client socket in C from any a computer via the internet.

My problem here is that despite having already forwarded port 8080 in my home router and having added port 8888 to the Debian server firewall (sudo ufw allow 8888/tcp and sudo ufw allow 8888/udp), I still can't connect to the server socket.

If I run both server and client socket programs on the same machine, they work just fine when connecting the client to localhost so I know the code is working fine. The problem is when I run the server socket program in the Debian server and the client socket program in my laptop they don't connect whether I use the Debian local address or the dynu hostname.

When I run the client it finishes with the error Connection refused and the server socket program doesn't even blink, it just stays on Waiting for connection on port 8888.

I mentioned at the beginning the nginx, the hostname, and the certificates because I don't know if this could be conflicting with a nginx-independent c server socket, I mean, I don't know if that is a restriction of nginx. I don't think it is because I'm using a port different than the ones nginx is configured with, but I'm not sure. I have even sudo systemctl stop nginx'ed the nginx server but that doesn't help.

What am I missing?

UPDATE: ok, I ran my server socket and put it to listen, then I ran netstat -ntlp and now I can see my server socket application as:

tcp        0      0 127.0.0.1:8888          0.0.0.0:*               LISTEN      8959/socket-server/

I had to change to port 8888 because port 8080 is being used by "WWW Cache" (whatever that is), but the client still doesn't connect.

My socket server is binding to an address obtained by getaddrinfo(NULL, port, &hints, &server_info)

m4l490n

Posted 2020-02-25T13:53:36.987

Reputation: 185

Is your server binding to localhost only? What does netstat -ntlp say about port 8080? – filbranden – 2020-02-25T23:30:29.960

@filbranden holy molly! It is not there! I just ran that command and I don't see 8080. but if I run sudo ufw allow 8080 I can see it. Why could this be? – m4l490n – 2020-02-25T23:42:05.480

ufw will simply say that you have a rule allowing connections on that port... But if there's nothing listening there, you won't be able to connect. Are you sure your server is listening on that port? Is it really a TCP server? Can you use something like nc or telnet to test to connect to it locally? – filbranden – 2020-02-25T23:59:11.663

1ok, I ran my server socket and put it to listen, then I ran netstat -ntlp and now I can see my server socket application as tcp 0 0 127.0.0.1:8888 0.0.0.0:* LISTEN 8959/socket-server/. I had to change to port 8888 because port 8080 is being used by WWW Cache (whatever that is), but the client still doesn't connect – m4l490n – 2020-02-26T00:16:35.677

Answers

1

Your netstat output explains what is happening:

$ netstat -ntlp | grep 8888
tcp        0      0 127.0.0.1:8888          0.0.0.0:*               LISTEN      8959/socket-server/

The 127.0.0.1 address is the "localhost" address and what this line indicates is that your server is listening on "localhost" only!

You should reconfigure or patch your server so that it's listening on an address that can be reached outside of the machine where it's running. Typically 0.0.0.0 (which means it's reachable at "any" address attached to the local machine.)

If you have the C code for it, look at whether it's binding its socket to INADDR_LOOPBACK, that would mean the 127.0.0.1 address, in other words "localhost". You can try to change that to INADDR_ANY, which means the 0.0.0.0 address, which will be accessible through the network (assuming a connection isn't blocked by a firewall or other kind of filtering.)


UPDATE: The man page of getaddrinfo(3) explains the behavior when the passed node address is NULL:

If the AI_PASSIVE flag is specified in hints.ai_flags, and node is NULL, then the returned socket addresses will be suitable for binding a socket that will accept connections. The returned socket address will contain the "wildcard address" (INADDR_ANY for IPv4 addresses). The wildcard address is used by applications (typically servers) that intend to accept connections on any of the host's network addresses. If node is not NULL, then the AI_PASSIVE flag is ignored.

If the AI_PASSIVE flag is not set in hints.ai_flags, then the returned socket addresses will be suitable for use with connect(2), sendto(2), or sendmsg(2). If node is NULL, then the network address will be set to the loopback interface address (INADDR_LOOPBACK for IPv4 addresses); this is used by applications that intend to communicate with peers running on the same host.

While one possible way to fix your problem is to pass a "0.0.0.0" address to the function:

getaddrinfo("0.0.0.0", port, &hints, &server_info)

Another possible solution is to update hints.ai_flags to include AI_PASSIVE.

filbranden

Posted 2020-02-25T13:53:36.987

Reputation: 1 058

1Awesome!! after fixing the binding in my C code now I can connect to the server socket either with another machine on the same network or with another machine via the internet!! The problem is that I had getaddrinfo(NULL, port, &hints, &server_info) and it should be getaddrinfo("0.0.0.0", port, &hints, &server_info) – m4l490n – 2020-02-26T00:52:08.807

@m4l490n I took the liberty to edit your question with the updates from your comments. I also updated my answer to include information on getaddrinfo. You can probably also fix this by using the AI_PASSIVE flag. In any case, glad you got your answer and your problem is fixed now!!! – filbranden – 2020-02-26T02:28:02.870

1Yeah, I read that in getaddrinfo(3) but it was not clear to me what "the returned socket addresses will be suitable for binding a socket that will accept connections" means. I mean is not clear that it means it will bind to 0.0.0.0 – m4l490n – 2020-02-26T02:32:13.157

1@m4l490n "socket that will accept(2) connections" is a server socket. The INADDR_ANY part means 0.0.0.0. I'd say that's exactly what you want. – filbranden – 2020-02-26T02:35:12.827

1Ok, I got it, and yes, that's better, instead of hardcoding "0.0.0.0" I then just make hints.ai_addr = AI_PASSIVE instead of 0 that is how I had it. It works as expected too. – m4l490n – 2020-02-26T02:41:51.267

0

If it's working on the local machine with localhost then it's likely a firewall issue on the Debian server. Those ufw commands you used look like they should have worked, but maybe try sudo ufw allow 8080 instead of specifying the protocol with the /. You can always check your firewall's open ports with iptables -L to see if your commands got set properly.

Here's more data on ufw if you want to play around with different syntax. If you want a more direct approach, you can set the firewall settings directly with iptables, using a command like this:

$ sudo iptables -A INPUT -p tcp --dport 8080 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
$ sudo iptables -A OUTPUT -p tcp --sport 8080 -m conntrack --ctstate ESTABLISHED -j ACCEPT

Hope this helps.

Sam Forbis

Posted 2020-02-25T13:53:36.987

Reputation: 1 198

That's weird. I can't see port 8080 when I execute sudo iptables -L but I can see it when executing sudo ufw status. What is going on? I don't remember having this problem when adding port 4321 – m4l490n – 2020-02-25T23:47:57.690

@m4l490n Use iptables -nvL to show ports as numbers, otherwise it will show it by its "nice" name (alt-http) or something similar... – filbranden – 2020-02-26T00:03:35.383

I can't see it even with iptables -nvL but here is the thing. I ran sudo ufw app list and executed a sudo ufw app info <app> with all apps that I got as a result. I found out that WWW Cache uses port 8080. So I went ahead and change the port to 8888 that is not used and now I can see it with iptables -nvL but my client still doesn't connect. – m4l490n – 2020-02-26T00:13:01.533