How to Route DNS to a Specific Port Without Exposing It in the URL


12 views

When setting up a web service on a non-standard port (like 8080), you'll quickly encounter a common problem: DNS records only resolve to IP addresses, not ports. This means users must manually append the port number (e.g., http://example.org:8080), which is neither user-friendly nor professional.

DNS operates at the network layer, resolving domain names to IP addresses. Port specification happens at the transport layer (TCP/UDP), which is why you can't include ports in A or CNAME records. The solution requires application-layer routing.

1. Reverse Proxy (Recommended)

Configure a reverse proxy like Nginx or Apache to listen on port 80 and forward requests to your service on port 8080:


# Nginx configuration example
server {
    listen 80;
    server_name example.org;

    location /fetch/characters/ {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
    }
}

2. Port Forwarding

For simple cases, use iptables to forward traffic:


sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

3. Application-Level Redirect

If you control the web application, implement a redirect:


// Node.js Express example
app.get('/', (req, res) => {
    if(req.headers.host === 'example.org') {
        res.redirect(308, 'http://example.org:8080/fetch/characters/');
    }
});
  • Always use HTTP 308 (Permanent Redirect) for SEO-friendly redirects
  • For production environments, implement HTTPS termination at the proxy
  • Monitor proxy server performance under load

While not applicable for HTTP, some protocols support SRV records:


_service._proto.name. TTL class SRV priority weight port target
_sip._tcp.example.org. 86400 IN SRV 10 60 5060 sipserver.example.org.



DNS records (A, CNAME, etc.) only resolve hostnames to IP addresses - they don't handle ports. The port specification (8080 in your case) must be handled at either:
  1. Web server configuration level
  2. Application routing level
  3. Reverse proxy setup
Here are three approaches to achieve transparent port mapping:

1. Web Server Redirect (Apache/Nginx)

For Apache (httpd.conf or virtual host):
<VirtualHost *:80>
    ServerName example.org
    Redirect permanent / http://www.example.org:8080/
</VirtualHost>

For Nginx:

server {
    listen 80;
    server_name example.org;
    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
    }
}

2. Application-Level Routing

If using Node.js/Express:

const express = require('express');
const app = express();
const targetApp = require('./your_8080_app');

app.use((req, res) => {
    // Preserve original URL path
    const newUrl = http://${req.hostname}:8080${req.originalUrl};
    res.redirect(301, newUrl);
});

app.listen(80);

3. Using Reverse Proxy

The most robust solution is setting up a reverse proxy. Here's a complete Nginx example:

# /etc/nginx/sites-available/example.org
server {
    listen 80;
    server_name example.org www.example.org;

    location /fetch/characters {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
  • Always test with curl -v http://example.org/fetch/characters to verify headers
  • For production, add HTTPS termination at the proxy level
  • Monitor for infinite redirect loops
  • Consider using SRV records for non-HTTP services (though limited browser support)

Here's a Docker compose setup with Nginx proxy:

version: '3'
services:
  webapp:
    image: your-webapp-image
    ports:
      - "8080:8080"
  
  proxy:
    image: nginx:alpine
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    ports:
      - "80:80"
    depends_on:
      - webapp

With nginx.conf containing:

events {}
http {
    server {
        listen 80;
        location / {
            proxy_pass http://webapp:8080;
        }
    }
}