2

I have a web application running on my home server on a non-standard port (9177). On my local network I can access it directly as http://192.168.0.13:9177/.

However, I'd like to expose it publicly to the world. I own a domain (example.com) and I'd like to point app.example.com to my locally running application.

enter image description here

What is the best way to do this? Do I need to be running a DNS server? If so, where does that run and what tools are used to configure it?

You can assume my router has a fixed IP that doesn't change for the scope of this question. The DNS record is correctly configured to point to my router.

Thanks!

7
  • 1
    Create a DNAT rule on the router, forwarding TCP\80 to 192.168.0.13:9177. easy peasy. if you want people to be able to hit it by name, your domain needs to be registered, and your DNS server set as authoritative. you can set the DNS address for example.com and app.example.com to the same IP address. they don't need to be different or anything. – Frank Thomas Jun 10 at 22:18
  • 2
    Note, my comment is valid as long as you only need to host one app on :80 or :443 per public IP address assigned to you. if you need to host more apps than you have IPs (and don't want to get into SNI, or they are on different hosts) you will need something more intelligent. – Frank Thomas Jun 10 at 22:28
  • 1
    @FrankThomas: Worth mentioning that DNAT is sometimes referred to as "Port Forwarding", "DMZ", etc in the router settings. – psmears Jun 11 at 9:55
  • 1
    @psmears Leave out the "sometimes". Nearly always is more appropriate to most people. I've never encountered a SOHO router that called it DNAT. – Tonny Jun 11 at 10:45
  • 2
    Note that for a residential ISP connection, it's likely that your provider is blocking incoming traffic on port 80 (and various other well-known ports). If this is the case, there is no combination of DNS settings and local network stuff which will let you expose something on port 80 to the outside world. – Sneftel Jun 11 at 15:53
10

Do I need to be running a DNS server [to do this]?

No. You need to be running a reverse proxy. Apache or nginx are both web servers that can be used for this purpose.

In short, you would create either a virtual host (Apache) or server block (nginx) for app.example.com, which would then be set up to forward requests for app.example.com to e.g. http://192.168.0.13:9177.

Regarding DNS, app.example.com would point to your public IP (typically your router, which would then direct web requests to your reverse proxy).

6
  • 7
    Having a reverse proxy can be nice and all, but I'm not seeing a NEED for one. a simple DNAT rule should do it right? what am I missing about this scenario that indicates the need for more than that? – Frank Thomas Jun 10 at 22:20
  • When you say 'subdomain' in your question, are you trying to route more than one? For example do you want x.example.com to go to 192.168.x.x:8888 and y.example.com to go to 192.168.x.x:8889? In that case you do need a reverse proxy unless you don't mind people entering x.example.com:8888 and y.example.com:8889 to access. – LawrenceC Jun 10 at 22:23
  • 1
    Thanks all! @LawrenceC - yes I would like to eventually route multiple subdomains, so I'll look into the reverse proxy like Anaksunaman suggested. I'm not sure what DNAT is, trying to currently look it up. I'd appreciate any resources you could point me to! – user2490003 Jun 10 at 23:46
  • 5
    @user2490003 DNAT == Port-fowarding in most SOHO routers. Almost nobody calls it DNAT even though that is the proper teminology. – Tonny Jun 11 at 10:47
  • 1
    @FrankThomas, DNAT will only work if you've just got the one server. If you've got more than one (eg. "app.example.com" and "web.example.com"), you need the reverse proxy in order to route traffic by name. – Mark Jun 11 at 21:49
7

The other answers are all true, but I'll elaborate a bit to set some more minor details straight.

The first thing to realize is - when you type http://app.example.com/path/to/resource.jpeg in your browser, the first thing your browser does is to use the DNS system to translate from app.example.com to your external IP address (you need to set this up yourself, obviously). And then it tries to connect to that IP address.

Since no port was specified in the original URL, it will look at the protocol (http in this case) an choose the default port number for that protocol (80 for http). So then it connects to that IP and that port.

Note that you have no way to specify a different port in the DNS system. If a custom port wasn't in the URL to begin with, then the default will be used, period.

Now, since your actual web server was running behind your router on an internal IP address, and the external IP address belongs to your router, you'll need to set up port forwarding on the router. So that when someone connects to the externalIP:80 the router will then create another connection to 192.168.0.13:9177 and forward all the data back and forth between the two connections (nitpicking: it's actually a bit different, but you can think of it like that).

This is all nice and fine as long as you have only one web application. But if you want to have TWO web applications, and distinguish them by the domain - you can't do it this way. The precise domain you have requested is only transmitted once the connection is already opened, but the router needs to make the port-forwarding decision BEFORE the connection is opened. It doesn't know which domain the incoming request is for until it's already too late.

In this case you need the reverse-proxy. The reverse proxy is like another web application, but what it does is simply accept HTTP requests, check out what domain was requested, open another connection depending on that and then forward all the data between them. It's a bit more involved than just blindly forwarding binary data (what the router does for its port forwarding), since the reverse proxy needs to understand (and likely modify) the contents of the HTTP request.

The reverse proxy might be installed on your router, or on your home server next to the web applications, or on a separate machine. That's up to you.

Oh, and if your web-applications all use the same webserver anyway (like Apache Httpd or Nginx), then they support "virtual hosts" by themselves, and you don't need an additional reverse proxy at all.

P.S. Slightly out of scope, but consider also setting up HTTPS. With free (as in beer) certificates available from Let's Encrypt, it's really a good idea. Your reverse proxy can also handle this part, meaning no changes need to be made to the web application.

5
  • Good answer! Though one minor semantic quibble: your router doesn't create a new "connection" (in the proper TCP sense of the word) to your internal PC. It just rewrites the destination address and port number of the packets as they come in according to its network address translation (NAT) table. Only one TCP connection exists directly between the internal PC (server) and the external client, just the addresses in the packet headers get rewritten as they transit the NAT router. – reirab Jun 11 at 15:45
  • 1
    @reirab - Well, yeah, that's true. Though I think it's easier to visualize as two separate connections and the router passing data back and forth. The rewriting explanation then requires more in-depth knowledge of the network stack (like, how does the router then know how to properly rewrite the packets going the opposite direction?) – Vilx- Jun 11 at 15:51
  • Thanks for the answer @Vilx-. You mention runniing a reverse proxy on the router itself - is that even possible? I assume nginix is a bit heavier and needs access to the router OS to be installable. – user2490003 Jun 12 at 3:30
  • @user2490003 - I don't know. Depends on the router. What do you have? But you can also easily run it on your home server, no need to complicate things. And, as I said - does your web app already use a separate webserver (apache/nginx/iis/whathaveyou)? If so, then you don't even need a reverse proxy. Same thing if you don't want to run multiple apps. For a single app you don't need to care about the domain at all - just let it handle whatever comes its way. – Vilx- Jun 12 at 8:39
  • Thanks, I was just curious about the router install that's all. I ended up installing NGINX on my server and it works perfectly. This can also scale to handle any other web apps I add over time. – user2490003 Jun 12 at 21:08
1

Some providers won't allow you to modify the router connected to their service to forward incoming packets to a particular internal IP:PORT.

AT&T does this on their fixed wireless, for example and last I looked Cox did the same kind of thing.

If they do, then it depends on the router and what s/ware it's running. If it has a DMZ setting you should be able to simply configure in there with the source port being 80 (or 443) and the destination being your internal IP and Port.

If it's some form of linux distro being used as a router then you will probably just need to configure firewalld or iptables (you'll have to do a search, I have not done this in a while)

2
  • Thanks! I do have a "port forwarding" rule set up in my router that forwards SSH requests on port 22 to my local server port 22. I can also forward requests on 9177 the same way (from incoming 443 for example, but I don't see an obvious way to restrict it to only my desired subdomain (app.example.com). I'm assuming port forwarding blindly forwards all incoming requests – user2490003 Jun 10 at 23:50
  • If you're using httpS, the whole certificate stuff should prevent anybody from not using the subdomain accidentially. But you can't really prevent anybody from connecting to the IP, ignoring the certificate, and sending a fake SNI and/or Host: header. If you have more than one web app, on different subdomains, and want only one of them accessible, a reverse proxy that reads the Host: header is the way to go. – Guntram Blohm Jun 11 at 7:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.