Singkatnya, ACK itu dikirim ketika soket itu bukan milik siapa pun. Alih-alih mengizinkan paket yang berhubungan dengan soket milik pengguna x
, izinkan paket yang berkaitan dengan koneksi yang dimulai oleh soket dari pengguna x
.
Semakin panjang ceritanya.
Untuk memahami masalahnya, ada baiknya untuk memahami bagaimana wget
dan permintaan HTTP berfungsi secara umum.
Di
wget http://cachefly.cachefly.net/10mb.test
wget
membuat koneksi TCP ke cachefly.cachefly.net
, dan setelah dibuat mengirimkan permintaan dalam protokol HTTP yang mengatakan:"Tolong kirimi saya konten /10mb.test
(GET /10mb.test HTTP/1.1
) dan omong-omong, bisakah Anda tidak menutup koneksi setelah selesai (Connection: Keep-alive
). Alasannya karena jika server membalas dengan pengalihan untuk URL pada alamat IP yang sama, itu dapat menggunakan kembali koneksi.
Sekarang server dapat membalas dengan, "Ini dia data yang Anda minta, hati-hati ukurannya 10MB (Content-Length: 10485760
), dan ya OK, saya biarkan koneksinya terbuka". berhenti mengunduh data dengan menutup akhir koneksi saya".
Di URL di atas, kita berada di kasus pertama.
Jadi, segera setelah wget
telah memperoleh tajuk untuk respons, ia mengetahui tugasnya selesai setelah mengunduh 10 MB data.
Pada dasarnya, apa wget
yang dilakukan adalah membaca data hingga 10MB telah diterima dan keluar. Tetapi pada saat itu, masih banyak yang harus dilakukan. Bagaimana dengan servernya? Telah diberitahu untuk membiarkan koneksi tetap terbuka.
Sebelum keluar, wget
tutup (close
system call) deskriptor file untuk soket. Setelah, close
, sistem selesai mengakui data yang dikirim oleh server dan mengirimkan FIN
untuk mengatakan:"Saya tidak akan mengirimkan data lagi". Pada saat itu close
mengembalikan dan wget
keluar. Tidak ada lagi soket yang terkait dengan koneksi TCP (setidaknya tidak ada yang dimiliki oleh pengguna mana pun). Namun itu belum selesai. Setelah menerima FIN
itu , server HTTP melihat akhir file saat membaca permintaan berikutnya dari klien. Dalam HTTP, itu berarti "tidak ada permintaan lagi, saya akan menutup akhir saya". Jadi itu mengirimkan FIN-nya juga, untuk mengatakan, "Saya juga tidak akan mengirim apa pun, koneksi itu terputus".
Setelah menerima FIN itu, klien mengirimkan "ACK". Tapi, pada saat itu, wget
sudah lama hilang, sehingga ACK bukan dari pengguna mana pun. Itulah sebabnya itu diblokir oleh firewall Anda. Karena server tidak menerima ACK, itu akan mengirimkan FIN berulang kali sampai menyerah dan Anda akan melihat lebih banyak ACK yang dijatuhkan. Itu juga berarti bahwa dengan menghapus ACK tersebut, Anda tidak perlu menggunakan sumber daya server (yang perlu mempertahankan soket dalam status LAST-ACK) untuk beberapa waktu.
Perilaku akan berbeda jika klien tidak meminta "Keep-alive" atau server tidak menjawab dengan "Keep-alive".
Seperti yang telah disebutkan, jika Anda menggunakan pelacak koneksi, yang ingin Anda lakukan adalah membiarkan setiap paket dalam status ESTABLISHED dan RELATED melewatinya dan hanya mengkhawatirkan NEW
paket.
Jika Anda mengizinkan NEW
paket dari pengguna x
tetapi bukan paket dari pengguna y
, lalu paket lain untuk koneksi yang dibuat oleh pengguna x
akan melalui, dan karena tidak dapat dibuat koneksi oleh pengguna y
(karena kami memblokir NEW
paket yang akan membuat koneksi), tidak akan ada paket untuk pengguna y
koneksi melalui.
Ini memungkinkan port 80 keluar hanya untuk akun "useraccount"
— yah, setidaknya aturan yang Anda tunjukkan sebenarnya tidak menyiratkan hal ini.
Ada juga ruang untuk saran - jangan lakukan pemeriksaan pengguna pada aliran ESTABLISHED, lakukan saja pemeriksaan BARU. Saya juga tidak melihat gunanya memeriksa port sumber saat memeriksa Masuk ESTABLISHED, apa bedanya port mana itu, itu sudah dalam keadaan ESTABLISHED dari PoV conntrack. Firewall harus sesederhana mungkin namun tetap efisien, jadi pendekatan silet Occam adalah yang paling cocok.