Multipli siti web in diversi container su un server Proxmox 9 con un solo IP Pubblico

tratto da: https://community.ovhcloud.com/community/en/new-os-available-proxmox-virtual-environment-ve-9?id=community_question&sys_id=362f0572b1e7ae14f07803b560bfcdaf

Prerequisiti

  • OVH/Kimsufi dedicated server
  • Proxmox 9 installed by OVH
  • SSH access to the server
  • Basic understanding of Linux networking

Parte 1: Installazione iniziale

1.1 Setup utente amministratore

# SSH into server as root
ssh root@YOUR_SERVER_IP

# Create admin user
adduser utente
usermod -aG sudo utente

# Set up SSH key access
mkdir -p /home/utente/.ssh
cp /root/.ssh/authorized_keys /home/utente/.ssh/
chown -R utente: /home/utente/.ssh
chmod 700 /home/utente/.ssh
chmod 600 /home/utente/.ssh/authorized_keys

# Configure passwordless sudo
echo "utente ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/utente
chmod 440 /etc/sudoers.d/utente

1.2 Accesso Interfaccia Web

Imposto la password di root per poter accedere all’interfaccia web

passwd root

Posso ora accedere alla pagina web di Proxmox: https://YOUR_SERVER_IP:8006

Parte 2: Configurazione di rete dei container

2.1 il problema

La configurazione di default della rete dei container su OVH fallisce a causa di:

  • I container si connettono direttamente alla rete esterna vmbr0
  • Non è prevista la configurazione NAT per i container
  • Mancano le regole di FORWARD tra le reti esterne ed interne

2.2 Creo una rete Bridge interna

Modifica /etc/network/interfaces e aggiungi:

auto vmbr6
iface vmbr6 inet static
address 10.0.0.254/24
bridge-ports none
bridge-stp off
bridge-fd 0
post-up echo 1 > /proc/sys/net/ipv4/ip_forward
post-up iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o vmbr0 -j MASQUERADE
post-down iptables -t nat -D POSTROUTING -s 10.0.0.0/24 -o vmbr0 -j MASQUERADE

2.3 Attivo il bridge interno

# Bring up the new bridge
ifup vmbr6

# Verify bridge creation
ip addr show vmbr6

2.4 Configuro l’inoltro dei pacchetti:

# Enable IP forwarding permanently
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -p

# Add FORWARD rules for container-to-internet traffic
iptables -I FORWARD -i vmbr6 -o vmbr0 -j ACCEPT
iptables -I FORWARD -i vmbr0 -o vmbr6 -m state --state RELATED,ESTABLISHED -j ACCEPT

# Importo il forward dei pacchetti web
iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.100:15080
iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 443 -j DNAT --to-destination 10.0.0.100:15443
iptables -A FORWARD -p tcp -d 10.0.0.100 --dport 15080 -j ACCEPT
iptables -A FORWARD -p tcp -d 10.0.0.100 --dport 15443 -j ACCEPT

# Save iptables rules
mkdir -p /etc/iptables
iptables-save > /etc/iptables/rules.v4

Parte 3: Creazione del container di routing

3.1 Download del Template per il Container

Dall’interfaccia web di Proxmox:

  • Vai sul nodo –> local storage
  • Clicca sul tab: “CT Templates”
  • Clicca sul tasto “Templates”
  • Scarica Debian-13-standard

3.2 Crea il container dall’interfaccia web

Dal nodo proxmox premo il tasto destro e scelgo “Crea CT”

  • General tab:
    • CT ID: 100
    • Hostname: your-container-name
    • Set password
    • Add SSH public key (opzionale)
  • Template tab:
    • Select debian-13-standard
  • Root Disk tab:
    • Size: 8GB (adjust as needed)
  • CPU/Memory tabs:
    • Set as needed (1 core, 1GB RAM for basic web server)
  • Network tab:
    • CRITICAL: Change bridge from vmbr0 to vmbr6
    • Set static IP: 10.0.0.100/24 (increment for additional containers)
    • Gateway: 10.0.0.254
  • DNS tab:
    • Use host settings

3.3 Verifica e configurazione Container di routing

# Start container
pct start 100

# Enter container
pct enter 100

# Test connectivity
ping -c 3 10.0.0.254 # Gateway
ping -c 3 8.8.8.8 # Internet

# Applico gli aggiornamenti come di prassi
apt update && apt upgrade -y

# Scarico i pacchetti nginx e Let's Encrypt
apt install python3-acme python3-certbot python3-mock python3-openssl python3-pkg-resources python3-pyparsing python3-zope.interface python3-certbot-nginx nginx

# Rimuovo la configurazione per il sito di default
rm /etc/nginx/sites-enabled/default

# Creo una configurazione di routing per un primo sito web: example.com sul server locale 10.0.0.101
echo 'server {
listen 15080;
listen [::]:15080; # Also listen on IPv6
server_name example.com;

location / {
proxy_pass http://10.0.0.101:80; # Indirizzo del server di destinazione
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}' > /etc/nginx/conf.d/router.conf

# Riavvio il server NGINX
service nginx restart

3.4 Test raggiungibilità sito web

I record DNS del vostro sito “example.com” deve essere configurato con un record di tipo A che punta all’indirizzo IP del vostro server Proxmox

Puntate il vostro browser verso l’indirizzo http://example.com

Se tutto e’ andato a buon fine dovreste vedere la pagina di Welcome di NGINX

3.5 Richiesta del certificato Let’s Encrypt

certbot --nginx -d example.com -m mymail@mydomain.com --agree-tos --no-eff-email --http-01-port 15080

Certbot vi chiederà se redirigere il traffico http a https. Per ora rispondete no.

3.6 Modificate la porta per https:

sed -i 's/listen 443 ssl/listen 15443 ssl/g' /etc/nginx/conf.d/router.conf

# Riavvio NGINX
service nginx restart

Parte 4: Server Web

Potete ora creare un nuovo container per ospitare il sito example.com (potete ripetere questi passaggi per altri nuovi container):

  • General tab:
    • CT ID: 101
    • Hostname: example.com
    • Set password
    • Add SSH public key (opzionale)
  • Template tab:
    • Select debian-13-standard
  • Root Disk tab:
    • Size: 8GB (adjust as needed)
  • CPU/Memory tabs:
    • Set as needed (1 core, 1GB RAM for basic web server)
  • Network tab:
    • CRITICAL: Change bridge from vmbr0 to vmbr6
    • Set static IP: 10.0.0.101/24 (increment for additional containers)
    • Gateway: 10.0.0.254
  • DNS tab:
    • Use host settings

Nota che l’indirizzo IP 10.0.0.101 è quello indicato nel file router.conf visto sopra.

Dalla shell di proxmox:

# Start container
pct start 101

# Enter container
pct enter 101

# Test connectivity
ping -c 3 10.0.0.254 # Gateway
ping -c 3 8.8.8.8 # Internet

# Applico gli aggiornamenti come di prassi
apt update && apt upgrade -y

# Scarico, installo e configuro Caddy
wget -O /tmp/caddy.tar.gz 'https://github.com/caddyserver/caddy/releases/download/v2.7.6/caddy_2.7.6_linux_amd64.tar.gz'
tar -xzf /tmp/caddy.tar.gz -C /usr/local/bin/ caddy
chmod +x /usr/local/bin/caddy

# Verify installation
/usr/local/bin/caddy version

# Create directory structure
mkdir -p /etc/caddy /var/www/html

# Create test page
echo '<h1>Working Caddy Web Server</h1><p>Container networking successful!</p>' > /var/www/html/index.html

# Create basic Caddyfile
echo ':80 {
root * /var/www/html
file_server
}' > /etc/caddy/Caddyfile

# Start Caddy
nohup /usr/local/bin/caddy run --config /etc/caddy/Caddyfile > /var/log/caddy.log 2>&1 &

Potete ora navigare su https://example.com

Avete finito !!

Nel file /etc/nginx/conf.d/router.conf potete aggiungere la configurazione anche per altri siti o server locali modificando il nome del sito o l’indirizzo del server (10.0.0.102, 10.0.0.103 …)

Proxmox firewall e router con un solo ip pubblico

Ecco come ho impostato il server proxmox per avere un firewall e il routing tramite un unico ip pubblico.

Dal pannello di controllo web abilitare eth0 con l’ip pubblico senza bridge e vmbr0 con un ip locale:

...
auto eth0
iface eth0 inet static
         address 91.11.22.33
         netmask 255.255.255.0
         broadcast 91.11.22.255
         gateway 91.11.22.254

auto vmbr0
iface vmbr0 inet static
        address 10.254.254.254
        netmask 255.0.0.0
        broadcast 10.255.255.255
        bridge_ports none
        bridge_stp off
        bridge_fd 0

...
...

Ora install shorewall

sudo aptitude install shorewall

Creo il file /etc/shorewall/zones e ci scrivo:

#ZONE   TYPE            OPTIONS         IN                      OUT
#                                       OPTIONS                 OPTIONS
fw      firewall
net     ipv4
dmz     ipv4

Creo il file /etc/shorewall/interfaces e ci scrivo:

#ZONE   INTERFACE       BROADCAST       OPTIONS
net     eth0            detect          blacklist,nosmurfs
dmz     venet0          detect          routeback
dmz     vmbr0           detect          routeback,bridge

Creo il file /etc/shorewall/policy e ci scrivo:

#SOURCE DEST    POLICY          LOG     LIMIT:          CONNLIMIT:
#                               LEVEL   BURST           MASK

# From Firewall Policy
fw      fw      ACCEPT
fw      net     ACCEPT
fw      dmz     ACCEPT

# From DMZ Policy

dmz     dmz     ACCEPT
dmz     net     ACCEPT
dmz     fw      DROP            info

# From Net Policy
net     fw      DROP            info
net     dmz     DROP            info

# THE FOLLOWING POLICY MUST BE LAST
#
all     all     REJECT          info

Creo il file /etc/shorewall/rules e ci scrivo:

#ACTION          SOURCE     DEST       PROTO   DEST        SOURCE     ORIGINAL    RATE

# Permit access to SSH
SSH/ACCEPT       net        fw         -       -            -          -        
  6/min:5

# Permit access to Proxmox Manager and Console
ACCEPT           net        fw         tcp     443,5900:5999

# PING Rules
Ping/ACCEPT      all        all

# LAST LINE -- DO NOT REMOVE

Alla fine la cartella /etc/shorewall dovrebbe contenere i seguenti file:

drwxr-xr-x  2 root root 4096 Apr 14 15:15 .
drwxr-xr-x 77 root root 4096 Apr 14 13:15 ..
-rw-r--r--  1 root root  453 Nov  8  2007 Makefile
-rw-r--r--  1 root root  214 Apr 14 15:03 interfaces
-rw-r--r--  1 root root  494 Apr 14 15:10 policy
-rw-r--r--  1 root root  517 Apr 14 15:15 rules
-rw-r--r--  1 root root 4004 Apr 14 13:18 shorewall.conf
-rw-r--r--  1 root root  183 Apr 14 13:19 zones

Controllo ora il funzionamento di shorewall:

shorewall try /etc/shorewall 60

in questo minuto di prova posso provare se risponde il pannello di controllo web di proxmox e se riesco a loggarmi in ssh al server.

Se tutto funziona posso abilitare proxmox all’avvio automatico: modifico il file /etc/default/shorewall e cambio:

startup=0

in

startup=1

Posso ora avviare shorewall manualmente col comando

shorewall start

oppure riavviarlo al bisogno con

shorewall restart

Per permettere alle macchine virtuali di uscire in internet creo il file /etc/shorewall/masq e sccrivo:

#INTERFACE      SOURCE          ADDRESS         PROTO   PORT(S) IPSEC   MARK
eth0            10.0.0.0/8

# LAST LINE -- DO NOT REMOVE

per dirottare il traffico web (porta 80) su una macchina virtuale inserisco nel file /etc/shorewall/rules questa regola:

DNAT                    net     dmz:10.0.1.101          tcp     80

Posso anche cambiare porta di destinazione nella macchina virtuale con la regola:

DNAT                    net     dmz:10.0.1.103:8180     tcp     80

Le macchine virtuali potranno avere degli indirizzi privati del tipo 10.xxx.yyy.zzz (es 10.0.1.101) ed essere gestiti semplicemente con un’interfaccia venet.

Shorewall ha alcune opzioni comode e interessanti:

safe-restart

salva la configurazione attuale, quindi applica quella nuova e chiede conferma per mantenere le nuove regole; se la conferma non è data entro 60 secondi sono riapplicate le regole precedenti;

try configuration-directory [timeout]

riavvia shorewall utilizzando la configurazione presente nella directory specificata e se sono rilevati errori o se il timeout è raggiunto, le regole precedenti sono riapplicate;

show check

esegue la validazione sintattica della configurazione;

logwatch

simile a tail -f $LOGFILE;

ipcalc [<address> <mask> | <address/vlsm>]

dato un indirizzo di rete, mostra i corrispondenti indirizzi di network, broadcast e netmask.

(per questo post ho preso pesantemente spunto dal seguente: http://www.myatus.co.uk/2009/08/31/guide-firewall-and-router-with-proxmox/)