Last updated: March 16, 2026

When governments restrict or completely shut down internet access, maintaining connectivity becomes critical for journalists, activists, developers, and organizations operating in high-risk environments. Satellite internet provides an independent communication channel that bypasses terrestrial infrastructure, making it an effective resilience tool against network blackouts. This guide covers the technical implementation of satellite internet as a backup connectivity solution.

Table of Contents

Prerequisites

Before you begin, make sure you have the following ready:

Step 1 - Understand Satellite Internet as a Backup Solution

Satellite internet operates by transmitting data between a dish antenna at your location and satellites orbiting the Earth. Unlike cable or fiber optic connections that depend on ground-level infrastructure, satellite connectivity only requires a clear view of the sky. This independence from local telecommunications infrastructure makes it resilient to government-ordered shutdowns that target terrestrial networks.

There are two primary categories to consider: geostationary (GEO) and low-earth orbit (LEO) satellite systems. GEO satellites sit at approximately 35,786 kilometers above the equator and provide broad coverage but with higher latency (typically 500-700ms). LEO satellite constellations, such as those operated by various providers, orbit closer to Earth (500-1,200 km) and offer significantly lower latency (20-40ms) but require more complex equipment setup.

For developers and power users, LEO-based solutions generally provide a better experience when latency matters, while GEO options may serve as cost-effective alternatives for basic connectivity needs.

Hardware Requirements

Setting up satellite internet as a backup requires specific hardware. The essential components include:

  1. Satellite antenna/disk: The physical dish or flat-panel antenna that communicates with satellites
  2. Modem or terminal: The device that converts satellite signals into usable internet data
  3. Power supply: Reliable power for the entire setup, ideally with battery backup
  4. Router: To distribute the connection to multiple devices

Many modern satellite internet providers offer integrated terminals that combine the antenna and modem into a single unit, simplifying deployment. These terminals typically connect via Ethernet or WiFi to your existing network equipment.

For portable or emergency setups, consider:

Step 2 - Network Configuration for Automatic Failover

Implementing true backup functionality requires configuring your network to automatically switch to satellite internet when your primary connection fails. This section covers the technical implementation using common tools.

Using systemd-networkd for Failover

On Linux systems, you can configure automatic failover using systemd-networkd with routing tables:

Define the primary interface (e.g., ethernet)
cat > /etc/systemd/network/50-ethernet.network << EOF
[Match]
Name=eth0

[Network]
DHCP=yes
IPv6AcceptRA=yes

[Route]
Gateway=192.168.1.1
Metric=100
EOF

Define the satellite backup interface
cat > /etc/systemd/network/60-satellite.network << EOF
[Match]
Name=wlan0

[Network]
DHCP=yes
IPv6AcceptRA=yes

[Route]
Gateway=192.168.2.1
Metric=200
EOF

The lower metric value on the primary interface ensures it gets preference. When the primary fails, traffic automatically routes through the satellite interface.

Implementing Gateway Monitoring

You should add monitoring to detect primary connection failures:

#!/bin/bash
failback-check.sh - Monitor primary gateway and fail over when needed

PRIMARY_GW="192.168.1.1"
CHECK_HOST="8.8.8.8"
SATELLITE_IF="wlan0"
PRIMARY_IF="eth0"

while true; do
    if ! ping -c 1 -W 2 "$CHECK_HOST" > /dev/null 2>&1; then
        # Primary gateway unreachable
        logger "Primary connection failed - switching to satellite"
        ip route change default dev "$SATELLITE_IF" metric 150
    else
        # Check if we should return to primary
        CURRENT_METRIC=$(ip route show default | grep "$PRIMARY_IF" | awk '{print $5}')
        if [ "$CURRENT_METRIC" -gt 100 ]; then
            logger "Primary connection restored - switching back"
            ip route change default dev "$PRIMARY_IF" metric 100
        fi
    fi
    sleep 30
done

Run this script as a systemd service for continuous monitoring:

sudo systemctl enable failback-check.service
sudo systemctl start failback-check.service

Using WireGuard Over Satellite

Satellite connections often have data caps or bandwidth limitations. Using WireGuard with compression and optimized settings improves efficiency:

/etc/wireguard/wg0.conf
[Interface]
PrivateKey = <your-private-key>
Address = 10.0.0.2/24
MTU = 1280  # Reduce MTU for satellite links
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o %i -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o %i -j MASQUERADE

[Peer]
PublicKey = <server-public-key>
Endpoint = your-vpn-server.com:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25  # Keep NAT mappings alive over satellite

Setting MTU to 1280 prevents fragmentation over satellite links where the typical path MTU is lower than Ethernet defaults.

Operational Security Considerations

When using satellite internet in potentially monitored environments, consider these security practices:

Traffic Analysis Mitigation

Satellite traffic can be distinguished from terrestrial traffic due to characteristic latencies and routing patterns. To mitigate traffic analysis:

Physical Security

The satellite dish itself can be a liability:

Data Management

Satellite connections typically have lower bandwidth and higher latency:

Step 3 - Test Your Configuration

Regular testing ensures your backup system works when needed:

  1. Disconnect your primary connection and verify automatic failover occurs
  2. Test DNS resolution over the satellite link
  3. Verify VPN connectivity works over the satellite connection
  4. Test failback when primary connection returns
  5. Measure actual bandwidth and latency to understand your operational limits
Simple bandwidth test over satellite
iperf3 -c test-server.example.com -R -V

Test with reduced MTU
iperf3 -c test-server.example.com -R -V -M 1280

Document your test results to establish baseline expectations during actual emergencies.

Step 4 - Cost and Accessibility

Satellite internet services typically operate on subscription models with varying data allowances. Some providers offer pay-as-you-go options, while others provide monthly plans with priority data. Research providers available in your region and understand their terms of service, including any restrictions that might apply during government emergencies.

For organizations, consider maintaining relationships with multiple satellite providers to ensure service availability during crisis situations when demand spikes.

Troubleshooting

Configuration changes not taking effect

Restart the relevant service or application after making changes. Some settings require a full system reboot. Verify the configuration file path is correct and the syntax is valid.

Permission denied errors

Run the command with sudo for system-level operations, or check that your user account has the necessary permissions. On macOS, you may need to grant terminal access in System Settings > Privacy & Security.

Connection or network-related failures

Check your internet connection and firewall settings. If using a VPN, try disconnecting temporarily to isolate the issue. Verify that the target server or service is accessible from your network.

Frequently Asked Questions

How long does it take to set up satellite internet as backup during government?

For a straightforward setup, expect 30 minutes to 2 hours depending on your familiarity with the tools involved. Complex configurations with custom requirements may take longer. Having your credentials and environment ready before starting saves significant time.

What are the most common mistakes to avoid?

The most frequent issues are skipping prerequisite steps, using outdated package versions, and not reading error messages carefully. Follow the steps in order, verify each one works before moving on, and check the official documentation if something behaves unexpectedly.

Do I need prior experience to follow this guide?

Basic familiarity with the relevant tools and command line is helpful but not strictly required. Each step is explained with context. If you get stuck, the official documentation for each tool covers fundamentals that may fill in knowledge gaps.

Is this approach secure enough for production?

The patterns shown here follow standard practices, but production deployments need additional hardening. Add rate limiting, input validation, proper secret management, and monitoring before going live. Consider a security review if your application handles sensitive user data.

Where can I get help if I run into issues?

Start with the official documentation for each tool mentioned. Stack Overflow and GitHub Issues are good next steps for specific error messages. Community forums and Discord servers for the relevant tools often have active members who can help with setup problems.

Advanced Redundancy - Multiple Satellite Providers

For critical resilience, organizations should maintain contracts with multiple satellite providers to prevent single-point-of-failure scenarios.

Multi-Provider Architecture

Configure multi-provider failover system
cat > /etc/systemd/network/70-satellite-primary.network << EOF
[Match]
Name=wlan0-sat1

[Network]
DHCP=yes

[Route]
Gateway=192.168.10.1
Metric=100
EOF

cat > /etc/systemd/network/70-satellite-backup.network << EOF
[Match]
Name=wlan1-sat2

[Network]
DHCP=yes

[Route]
Gateway=192.168.11.1
Metric=200
EOF

Systemd automatically uses lower metric (primary) and fails over to backup

This configuration ensures that if Provider An experiences outage or service degradation, traffic automatically routes through Provider B.

Health Monitoring Across Multiple Providers

Monitor both satellite connections independently
import asyncio
import subprocess
from datetime import datetime
from typing import Dict, List

class MultiProviderMonitor:
    def __init__(self, providers: List[Dict]):
        """
        providers: [
            {'name': 'Provider A', 'gateway': '192.168.10.1', 'interface': 'wlan0-sat1'},
            {'name': 'Provider B', 'gateway': '192.168.11.1', 'interface': 'wlan1-sat2'}
        ]
        """
        self.providers = providers
        self.health = {p['name']: {'status': 'unknown', 'last_check': None} for p in providers}
        self.latency_threshold = 200  # milliseconds
        self.packet_loss_threshold = 5  # percent

    async def health_check_loop(self):
        """Continuously monitor both providers."""
        while True:
            tasks = [self.check_provider(p) for p in self.providers]
            results = await asyncio.gather(*tasks)

            for provider, status in zip(self.providers, results):
                self.health[provider['name']] = status
                self.log_status(provider, status)

            await asyncio.sleep(30)  # Check every 30 seconds

    async def check_provider(self, provider: Dict) -> Dict:
        """Check a single provider's health."""
        try:
            # Ping latency test
            result = subprocess.run(
                ['ping', '-c', '4', '-i', '0.2', provider['gateway']],
                capture_output=True,
                text=True,
                timeout=10
            )

            # Parse ping output
            lines = result.stdout.split('\n')
            stats_line = [l for l in lines if 'min/avg' in l]

            if not stats_line:
                return {
                    'status': 'down',
                    'latency': None,
                    'packet_loss': 100,
                    'timestamp': datetime.now().isoformat()
                }

            stats = stats_line[0].split('=')[1].strip()
            avg_latency = float(stats.split('/')[1])
            packet_loss = float(stats_line[0].split(', ')[2].split('%')[0])

            status = 'up' if packet_loss < self.packet_loss_threshold else 'degraded'

            return {
                'status': status,
                'latency': avg_latency,
                'packet_loss': packet_loss,
                'timestamp': datetime.now().isoformat()
            }

        except Exception as e:
            return {
                'status': 'error',
                'error': str(e),
                'timestamp': datetime.now().isoformat()
            }

    def log_status(self, provider: Dict, status: Dict):
        """Log provider status for analysis."""
        timestamp = status['timestamp']
        print(f"[{timestamp}] {provider['name']}: {status['status']}", end='')

        if status['status'] == 'up':
            print(f" - Latency - {status['latency']:.1f}ms, Loss - {status['packet_loss']:.1f}%")
        elif status['status'] == 'degraded':
            print(f" - WARNING: High packet loss {status['packet_loss']:.1f}%")
        else:
            print(f" - Connection unavailable")

    async def trigger_failover_if_needed(self):
        """Switch to backup if primary is down."""
        primary = self.providers[0]
        backup = self.providers[1]

        primary_health = self.health[primary['name']]
        backup_health = self.health[backup['name']]

        if primary_health['status'] == 'down' and backup_health['status'] == 'up':
            print(f"FAILOVER: {primary['name']} down, switching to {backup['name']}")
            subprocess.run([
                'ip', 'route', 'change', 'default',
                'dev', backup['interface'],
                'metric', '50'
            ])

        elif primary_health['status'] == 'up' and backup_health['status'] != 'up':
            # Failback to primary
            print(f"FAILBACK: {primary['name']} recovered")
            subprocess.run([
                'ip', 'route', 'change', 'default',
                'dev', primary['interface'],
                'metric', '50'
            ])

Run monitoring
if __name__ == '__main__':
    providers = [
        {'name': 'Provider A (LEO)', 'gateway': '192.168.10.1', 'interface': 'wlan0-sat1'},
        {'name': 'Provider B (GEO)', 'gateway': '192.168.11.1', 'interface': 'wlan1-sat2'}
    ]

    monitor = MultiProviderMonitor(providers)
    loop = asyncio.get_event_loop()
    loop.run_until_complete(monitor.health_check_loop())

This system maintains awareness of both connections and can switch automatically if the primary fails.

Step 5 - Privacy-Optimized Satellite Configuration

Satellite internet creates unique privacy considerations, your terminal’s physical location and orbital position data could reveal information.

Anonymizing Satellite Terminal Location

Use VPN over satellite to mask terminal location from service provider
cat > /etc/wireguard/wg-satellite.conf << EOF
[Interface]
PrivateKey = <YOUR_PRIVATE_KEY>
Address = 10.0.0.2/24
DNS = 1.1.1.1
MTU = 1280

[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
EOF

Enable VPN on startup
systemctl enable wg-quick@wg-satellite

Verify connection is through VPN
curl ifconfig.co  # Should show VPN provider's IP, not satellite provider's

The satellite provider sees only encrypted VPN traffic, not your actual application data.

Obfuscation Against Traffic Analysis

Beyond encryption, traffic patterns can reveal information:

Use obfsproxy to disguise VPN signatures
sudo apt install -y obfsproxy

Configure WireGuard over obfsproxy
cat > /usr/local/bin/wg-obfs.sh << 'EOF'
#!/bin/bash
Run obfsproxy listener that forwards to WireGuard

obfsproxy --log-level=warning \
  scramblesuit \
  --password-file=/etc/wireguard/obfs.password \
  server 127.0.0.1:51821

In separate terminal, connect WireGuard through obfsproxy
Configure WireGuard Endpoint as 127.0.0.1:51821
EOF

chmod +x /usr/local/bin/wg-obfs.sh

This makes your satellite VPN traffic indistinguishable from normal web traffic to network analysis.

Step 6 - Offline-First Architecture for Satellite Resilience

Satellite connectivity is unreliable compared to terrestrial internet. Design applications to work offline and sync when connection is available:

// React: Offline-first application using IndexedDB
import { useEffect, useState } from 'react';
import Dexie from 'dexie';

// Define offline database
const db = new Dexie('satellite-app');
db.version(1).stores({
  documents: '++id, title',
  changes: '++id, timestamp'
});

function OfflineFirstApp() {
  const [isOnline, setIsOnline] = useState(navigator.onLine);
  const [syncStatus, setSyncStatus] = useState('synced');
  const [documents, setDocuments] = useState([]);

  useEffect(() => {
    window.addEventListener('online', () => {
      setIsOnline(true);
      syncToServer();
    });
    window.addEventListener('offline', () => setIsOnline(false));

    loadLocalDocuments();
  }, []);

  const loadLocalDocuments = async () => {
    const docs = await db.documents.toArray();
    setDocuments(docs);
  };

  const saveDocument = async (doc) => {
    // Save locally first
    await db.documents.put(doc);

    // Track changes for later sync
    await db.changes.add({
      type: 'update',
      documentId: doc.id,
      timestamp: Date.now(),
      data: doc
    });

    setDocuments(prev => [...prev.filter(d => d.id !== doc.id), doc]);

    // If online, sync immediately
    if (isOnline) {
      syncToServer();
    } else {
      setSyncStatus('pending');
    }
  };

  const syncToServer = async () => {
    setSyncStatus('syncing');

    try {
      const changes = await db.changes.toArray();

      const response = await fetch('/api/sync', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ changes })
      });

      if (response.ok) {
        // Clear synced changes
        await db.changes.clear();
        setSyncStatus('synced');
      }
    } catch (error) {
      setSyncStatus('error: ' + error.message);
    }
  };

  return (
    <div>
      <div className="status">
        Network - {isOnline ? 'online' : 'offline'}
        Sync: {syncStatus}
      </div>

      <DocumentList documents={documents} onSave={saveDocument} />
    </div>
  );
}

This architecture ensures work is never lost even during extended satellite outages, data syncs when connection resumes.

Step 7 - Long-Duration Outage Preparation

For extended internet shutdowns (days or weeks), additional preparation helps:

Critical Data Caching

Before an anticipated shutdown, pre-cache essential resources
This script downloads frequently-needed data locally

#!/bin/bash
CACHE_DIR=~/.offline-cache

mkdir -p "$CACHE_DIR"

Cache documentation
wget -r -k --directory-prefix="$CACHE_DIR/docs" https://docs.yourdomain.com
wget -r -k --directory-prefix="$CACHE_DIR/api" https://api-docs.yourdomain.com

Cache important reference materials
curl -s https://example.com/reference.pdf -o "$CACHE_DIR/reference.pdf"

Cache code repositories
git clone --mirror https://github.com/yourorg/repo.git "$CACHE_DIR/repos/repo.git"

Estimate storage used
du -sh "$CACHE_DIR"

echo "Cached $(find "$CACHE_DIR" -type f | wc -l) files"

Local Development Environment

Set up complete development environment that works offline
docker-compose -f docker-compose.offline.yml up

docker-compose.offline.yml includes:
- Local database (PostgreSQL)
- API server with pre-cached datasets
- Static documentation server
- Code IDE/editor

When satellite internet returns, push changes to remote
git push origin main

This approach enables productive work during extended outages without relying on external connectivity.

Compliance and Legal Considerations

Using satellite internet in some jurisdictions may have legal implications worth understanding:

Documentation for Compliance

Maintain records of:

Some governments track satellite terminal registrations. Understand your local requirements before installation.

Operational Security Audit

Regularly verify your satellite setup meets security and privacy standards:

#!/bin/bash
audit-satellite-setup.sh

echo "=== Satellite Internet Security Audit ==="

Check encryption
echo "VPN Status:"
wg show wg-satellite

Verify DNS privacy
echo "DNS Query Test:"
dig @8.8.8.8 google.com +short  # Should fail if only satellite DNS
dig google.com +short  # Should work through configured DNS

Check physical antenna position
echo "Antenna Position (from device logs):"
journalctl -u satellite-gps | tail -5

Verify no unsecured data flows
echo "Open Connections:"
ss -tunap | grep ESTABLISHED

Test failover functionality
echo "Testing primary connection shutdown..."
(Controlled test only in non-production)

Regular audits ensure your satellite backup maintains intended security properties.

Related Articles

Built by theluckystrike. More at zovo.one