Port forwarding to local server

8,135

Assuming that the port forwarding configuration on your router is correct, you need to ensure a few things:

  • The machine 192.168.0.4 has a running web server (OK).
  • It's listening on either 192.168.0.4:80 or 0.0.0.0:80 (OK).
  • The firewall that might be running on it allows incoming connections on port 80/tcp (UNKNOWN).

With regards to the last point - I'm not sure what your iptables rules are. Please post output of

sudo iptables -vL INPUT -n

If incoming connections on 80/tcp are indeed allowed but somehow you're unable to access your web server from outside of the network, you might want to log into the web server and use tcpdump to capture incoming traffic to see if any connection attempts are reaching it.

Use:

export ext_if=$(ip ro | awk '/^default via/ {print $5}')
sudo tcpdump -i ${ext_if} port 80

If you don't see any connections when you're trying to connect to your web server from outside of your network, you need to fix that first.

If the firewall on your machine doesn't allow incoming connections to reach port 80/tcp, fix this by running the command below and verify:

sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT

UPDATE: you also mentioned:

This is the tcpdump output after making a request to my public ip from the same machine the server is running on

This isn't likely to work. The path your request takes is:

192.168.0.4 =>
<public_ip> (doing source and destination NAT, aka port forwarding) =>
192.168.0.4

As you can see in the tcpdump output, there are 3 HTTP requests initiated by whatever tool you used to open the connection to your web server, the router rejects all connections by responding with packets with RST ("reset", i.e. "go away, close the connection") flag set.

As far as I know, many devices providing NAT won't let you initiate a request from within the network behind NAT to its public IP address and then back to the host behind the same NAT by means of port forwarding (destination NAT).

You should try making a request from outside of your network. If you don't have an external host where you can log in and use i.e. wget/curl to make the request try some of the many web based tools to do it, such as http://www.infobyip.com/httpservertest.php

If this works, and you get a result which contains at least the HTTP request status code (i.e. 200, 302, 404, etc.) and some response headers such as Server, Content-Type, this will confirm that:

  • your public IP is accessible from outside
  • the configured port forwarding works
  • the server on your network indeed receives the request and responds to it.

If you want to be able to access your webserver using its public IP from within the same network, you might either:

  • add an appropriate entry to your /etc/hosts file, pointing the server's domain name to your web server's private address (a temporary hack).
  • run a so-called split-dns server (preferred but not worth if it's just for yourself)
  • reconfigure your router to allow such connections. This can be done but it's unlikely that your home router (if that's what you have) will be able to do that.
Share:
8,135
Dominic
Author by

Dominic

Updated on September 18, 2022

Comments

  • Dominic
    Dominic over 1 year

    I want to be able to access a server which is running on my local machine via the Internet. I setup port forwarding on my router:

    Public Port Range: 80-80
    Target IP Address: 192.168.0.4
    Target Port Range: 80-80
    

    I checked if the ports are open with http://www.yougetsignal.com/tools/open-ports/ which states: Port 80 is open on ...

    I tried it with an Apache server as well with an nodeJS server on port 3000, but I never have access to the server.

    I checked if my machine is listening on those ports with netstat

    netstat -ltn | grep 80
    

    Output:

    tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
    

    What options do I have to get to the bottom of this, any other checks I could run?

    If it helps here is the Apache configuration.

    <VirtualHost *:80>
        ServerAdmin webmaster@localhost
        ServerName lebensmittel-schulung.local
    
        DocumentRoot /home/dominic/workspace/lebensmittel-schulung/public
        <Directory />
            Options FollowSymLinks
            AllowOverride None
        </Directory>
        <Directory /home/dominic/workspace/lebensmittel-schulung/public>
            Options Indexes FollowSymLinks MultiViews
            AllowOverride All
            Order allow,deny
            allow from all
            Require all granted
        </Directory>
    
    
        # Redirect www to non-www
        RewriteEngine on
        RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
        RewriteRule ^(.*)$ http://%1$1 [L,R=301]
    
        ErrorLog ${APACHE_LOG_DIR}/error.log
    
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn
    
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    
        Alias /doc/ "/usr/share/doc/"
        <Directory "/usr/share/doc/">
            Options Indexes MultiViews FollowSymLinks
            AllowOverride None
            Order deny,allow
            Deny from all
            Allow from 127.0.0.0/255.0.0.0 ::1/128
        </Directory>
    
    </VirtualHost>
    

    Also did a factory reset and reboot of my router to avoid a mis-configuration

    iptables before:

    Chain INPUT (policy ACCEPT 1330K packets, 1422M bytes)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:53
        0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:53
        0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:67
        0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:67
    

    iptables after opening port 80 manually

    Chain INPUT (policy ACCEPT 68 packets, 9825 bytes)
     pkts bytes target     prot opt in     out     source               destination         
        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80
        0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:53
        0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:53
        0     0 ACCEPT     udp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            udp dpt:67
        0     0 ACCEPT     tcp  --  virbr0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:67
    

    This is the tcpdump output after making a request to my public ip from the same machine the server is running on, though opening port 80 doesn't change anything. I think that this is the outgoing request which gets captured by tcpdump

    tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
    listening on wlan0, link-type EN10MB (Ethernet), capture size 65535 bytes
    21:46:42.402748 IP 192.168.0.4.34870 > chello080108157035.6.12.vie.surfer.at.http: Flags [S], seq 2878976956, win 29200, options [mss 1460,sackOK,TS val 4294937394 ecr 0,nop,wscale 7], length 0
    21:46:42.405078 IP chello080108157035.6.12.vie.surfer.at.http > 192.168.0.4.34870: Flags [R.], seq 0, ack 2878976957, win 0, length 0
    21:46:43.473378 IP 192.168.0.4.34871 > chello080108157035.6.12.vie.surfer.at.http: Flags [S], seq 1711479299, win 29200, options [mss 1460,sackOK,TS val 4294937661 ecr 0,nop,wscale 7], length 0
    21:46:43.473897 IP 192.168.0.4.34872 > chello080108157035.6.12.vie.surfer.at.http: Flags [S], seq 2157458117, win 29200, options [mss 1460,sackOK,TS val 4294937662 ecr 0,nop,wscale 7], length 0
    21:46:43.475335 IP chello080108157035.6.12.vie.surfer.at.http > 192.168.0.4.34871: Flags [R.], seq 0, ack 1711479300, win 0, length 0
    21:46:43.476463 IP chello080108157035.6.12.vie.surfer.at.http > 192.168.0.4.34872: Flags [R.], seq 0, ack 2157458118, win 0, length 0
    
    • Marcin Kaminski
      Marcin Kaminski about 9 years
      I've updated my answer. Also in your case the iptables command was a bit redundant, since your INPUT chain already has a default policy of ACCEPT and no DROP or REJECT rules, so effectively everything's allowed.
  • Dominic
    Dominic about 9 years
    Thanks a lot for your help. I updated the questions with the output.