Understanding Incoming vs. Outgoing HTTP Traffic: Firewall Rules Explained for Web Servers


1 views

In networking, incoming traffic refers to data packets arriving at your server from external sources, while outgoing traffic consists of packets leaving your server destined for other systems. For HTTP/HTTPS services, this translates to:

# Incoming: Port 80/443 traffic FROM clients TO your server
# Outgoing: Port 80/443 traffic FROM your server TO other systems

A standard web server primarily needs incoming ports 80/443 open to:

  • Accept HTTP/HTTPS requests from browsers
  • Receive API calls from client applications
  • Handle file uploads through web forms

However, outgoing rules become necessary when your server needs to:

# Example: Server needs to make external API calls
curl -X GET https://api.example.com/data

# Or when acting as reverse proxy
ProxyPass /external http://other-service.com

For a basic web server using iptables:

# Allow incoming HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Allow outgoing responses (established connections)
iptables -A OUTPUT -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT

# Allow new outgoing HTTP/HTTPS connections (if needed)
iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT

Security-conscious setups might block outgoing HTTP/HTTPS except to specific trusted destinations:

# Only allow outgoing HTTPS to payment processor
iptables -A OUTPUT -p tcp -d api.stripe.com --dport 443 -j ACCEPT

# Block all other outgoing web traffic
iptables -A OUTPUT -p tcp --dport 80 -j DROP
iptables -A OUTPUT -p tcp --dport 443 -j DROP

Some applications require both:

  • Load balancers making health checks to backend servers
  • Microservices architectures with bidirectional HTTP calls
  • Webhook implementations where servers initiate connections

For a Node.js server making outbound API calls while serving web pages:

const express = require('express');
const axios = require('axios');

const app = express();

// Incoming traffic (normal web server)
app.get('/', (req, res) => {
    // Outgoing traffic (API call)
    axios.get('https://api.example.com/data')
        .then(response => res.send(response.data));
});

app.listen(3000);

In network security, traffic direction is defined relative to your server:

  • Incoming traffic (ingress): Packets arriving at your server's network interface
  • Outgoing traffic (egress): Packets leaving your server's interface

A typical web request involves both directions:

Client (port 54321) → [INCOMING] Server:80 → Processing → [OUTGOING] Server:443 → Client

For a functional web server, you generally need:

# iptables example for HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT   # Incoming HTTP
iptables -A INPUT -p tcp --dport 443 -j ACCEPT  # Incoming HTTPS
iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT  # Outgoing HTTP responses
iptables -A OUTPUT -p tcp --sport 443 -j ACCEPT # Outgoing HTTPS responses

Security-conscious configurations might limit outbound traffic:

# Only allow outbound HTTP/HTTPS to specific IPs
iptables -A OUTPUT -p tcp --dport 80 -d 203.0.113.45 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -d 198.51.100.10 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 80 -j DROP
iptables -A OUTPUT -p tcp --dport 443 -j DROP

Many admins don't realize that:

  • Responses to client requests still count as outbound traffic
  • Server-initiated API calls (e.g., webhooks) require outbound rules
  • Port numbering conventions apply differently to each direction

Test your configuration with these commands:

# Check incoming connectivity
telnet yourserver.com 80

# Verify outbound requests
curl -v http://example.com

# Monitor active connections
netstat -tulnp