Per farla breve, quell'ACK è stato inviato quando il socket non apparteneva a nessuno. Invece di consentire i pacchetti che riguardano un socket che appartiene all'utente x
, consente i pacchetti che riguardano una connessione avviata da un socket dell'utente x
.
La storia più lunga.
Per comprendere il problema, è utile capire come wget
e le richieste HTTP funzionano in generale.
Dentro
wget http://cachefly.cachefly.net/10mb.test
wget
stabilisce una connessione TCP a cachefly.cachefly.net
, e una volta stabilito invia una richiesta nel protocollo HTTP che dice:"Per favore, inviami il contenuto di /10mb.test
(GET /10mb.test HTTP/1.1
) e a proposito, potresti per favore non chiudere la connessione dopo aver finito (Connection: Keep-alive
). Il motivo per cui lo fa è perché nel caso in cui il server risponda con un reindirizzamento per un URL sullo stesso indirizzo IP, può riutilizzare la connessione.
Ora il server può rispondere con "ecco i dati che hai richiesto, attenzione è grande 10 MB (Content-Length: 10485760
), e sì OK, lascerò la connessione aperta". Oppure, se non conosce la dimensione dei dati, "Ecco i dati, mi dispiace non posso lasciare la connessione aperta ma ti dirò quando puoi interrompere il download dei dati chiudendo la mia estremità della connessione".
Nell'URL qui sopra, siamo nel primo caso.
Quindi, non appena wget
ha ottenuto le intestazioni per la risposta, sa che il suo lavoro è terminato dopo aver scaricato 10 MB di dati.
Fondamentalmente, cosa wget
non è leggere i dati fino a quando non sono stati ricevuti 10 MB e uscire. Ma a quel punto, c'è altro da fare. E il server? È stato detto di lasciare aperta la connessione.
Prima di uscire, wget
chiude (close
chiamata di sistema) il descrittore di file per il socket. Su, il close
, il sistema finisce di riconoscere i dati inviati dal server e invia un FIN
per dire:"Non invierò più dati". A quel punto close
restituisce e wget
esce. Non c'è più alcun socket associato alla connessione TCP (almeno non uno di proprietà di nessun utente). Tuttavia non è ancora finito. Dopo aver ricevuto quel FIN
, il server HTTP vede la fine del file durante la lettura della richiesta successiva dal client. In HTTP, ciò significa "niente più richieste, chiuderò la mia fine". Quindi invia anche il suo FIN, per dire "Neanche io invierò nulla, quella connessione sta andando via".
Dopo aver ricevuto quel FIN, il client invia un "ACK". Ma, a quel punto, wget
è sparito da tempo, quindi l'ACK non proviene da nessun utente. Ecco perché è bloccato dal tuo firewall. Poiché il server non riceve l'ACK, invierà il FIN più e più volte finché non si arrende e vedrai più ACK persi. Ciò significa anche che eliminando quegli ACK, stai utilizzando inutilmente le risorse del server (che deve mantenere un socket nello stato LAST-ACK) per un bel po' di tempo.
Il comportamento sarebbe stato diverso se il client non avesse richiesto "Keep-alive" o il server non avesse risposto con "Keep-alive".
Come già accennato, se stai usando il connection tracker, quello che vuoi fare è far passare ogni pacchetto negli stati ESTABLISHED e RELATED e preoccuparti solo di NEW
pacchetti.
Se consenti NEW
pacchetti dall'utente x
ma non i pacchetti dall'utente y
, quindi altri pacchetti per le connessioni stabilite dall'utente x
passerà e perché non possono essere stabilite connessioni dall'utente y
(dal momento che stiamo bloccando il NEW
pacchetti che stabilirebbero la connessione), non ci sarà alcun pacchetto per l'utente y
connessioni in corso.
Ciò consente l'uscita della porta 80 solo per l'account "useraccount"
— beh, almeno le regole che hai mostrato non implicano questo, in realtà.
C'è anche spazio per i consigli:non controllare gli utenti sui flussi ESTABLISHED, fallo solo controllando su NEW. Inoltre, non vedo un punto nel controllare la porta di origine quando si controlla ESTABLISHED in entrata, qual è la differenza quale porta fosse, è già nello stato ESTABLISHED dal PoV di conntrack. Il firewall dovrebbe essere il più semplice possibile ma efficiente, quindi l'approccio rasoio di Occam è la soluzione migliore.