Dalam skrip iptables saya, saya telah bereksperimen dengan menulis aturan sebanyak mungkin. Saya membatasi pengguna mana yang diizinkan untuk menggunakan layanan mana, sebagian untuk keamanan dan sebagian sebagai latihan pembelajaran.
Menggunakan iptables v1.4.16.2 pada Debian 6.0.6 yang menjalankan kernel 3.6.2.
Namun saya telah menemukan masalah yang belum saya mengerti ...
port keluar untuk semua pengguna
Ini berfungsi dengan baik. Saya tidak memiliki aturan pelacakan keadaan umum.
## Port keluar 81 $ IPTABLES-OUTPUT -p tcp --dport 81 -m conntrack --ctstate NEW, ESTABLISHED -j ACCEPT $ IPTABLES -A INPUT -p tcp --sport 81 -s $ MYIP -m conntrack --ctstate ESTABLISHED -j ACCEPT
port keluar dengan pencocokan pengguna
## port keluar 80 untuk akun pengguna $ IPTABLES - OUTPUT - pemilik pencocokan - pemilik cairan penggunaaccount -p tcp --port 80 -m conntrack --ctstate NEW, ESTABLISHED --sport 1024: 65535 -j ACCEPT $ IPTABLES -A INPUT -p tcp --sport 80 --dport 1024: 65535 -d $ MYIP -m conntrack --ctstate ESTABLISHED -j ACCEPT
Ini memungkinkan port 80 hanya untuk akun "useraccount", tetapi aturan seperti ini untuk lalu lintas TCP memiliki masalah.
## Log keluar + aturan blok default $ IPTABLES - OUTPUT -j LOG --log-awalan "BAD OUTGOING" --log-ip-options --log-tcp-options --log-uid $ IPTABLES-OUTPUT -J DROP
Masalah
Di atas berfungsi, "useraccount" pengguna bisa mendapatkan file dengan sangat baik. Tidak ada pengguna lain di sistem yang dapat membuat koneksi keluar ke port 80.
useraccount @ host: $ wget http://cachefly.cachefly.net/10mb.test
Tetapi wget di atas membuat x7 menjatuhkan entri di syslog saya:
18 Okt 02:00:35 xxxx kernel: BAD OUTGOING IN = OUT = eth0 SRC = xx.xx.xx.xx DST = 205.234.175.175 LEN = 40 TOS = 0x00 PREC = 0x00 TTL = 64 ID = 12170 DF PROTO = TCP SPT = 37792 DPT = 80 SEQ = 164520678 ACK = 3997126942 WINDOW = 979 RES = 0x00 ACK URGP = 0
Saya tidak mendapatkan tetes ini untuk aturan yang sama dengan lalu lintas UDP. Saya sudah memiliki aturan yang membatasi pengguna mana yang dapat membuat permintaan DNS.
Paket ACK keluar yang keluar sepertinya berasal dari akun root (URGP = 0) yang saya tidak mengerti. Bahkan ketika saya menukar akun pengguna dengan root.
Saya percaya bahwa paket ACK dikategorikan sebagai baru karena conntrack mulai melacak koneksi setelah langkah ke-3 dari jabat tangan 3 arah, tetapi mengapa dropnya?
Bisakah tetes ini diabaikan dengan aman?
Edit
Jadi saya sering melihat aturan seperti ini, yang berfungsi dengan baik untuk saya:
$ IPTABLES-OUTPUT -s $ MYIP -p tcp -m tcp --dport 80 -m state --state NEW, ESTABLISHED -j ACCEPT $ IPTABLES -A INPUT -p tcp -m tcp --sport 80 -d $ MYIP -m state --state ESTABLISHED -j ACCEPT
Saya bertukar "-m state --state" untuk "-m conntrack --ctstate" karena pertandingan negara tampaknya sudah usang.
Apakah praktik terbaik untuk memiliki aturan pelacakan keadaan umum? Apakah aturan di atas dianggap tidak benar?
Untuk kontrol yang ketat atas koneksi pengguna keluar apakah ini akan lebih baik?
$ IPTABLES -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT $ IPTABLES-OUTPUT -m conntrack --ststate ESTABLISHED -j ACCEPT $ IPTABLES - OUTPUT -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate NEW -m owner --uid-owner useraccount -j ACCEPT $ IPTABLES - OUTPUT -p tcp --dport 80 -s $ SERVER_IP_TUNNEL -m conntrack --ctstate BARU -m pemilik - cairan-pemilik otheraccount -j MENERIMA
Jawaban:
Singkatnya, ACK dikirim ketika soket itu bukan milik siapa pun. Alih-alih mengizinkan paket yang berkaitan dengan soket yang menjadi milik pengguna
x
, izinkan paket yang berkaitan dengan koneksi yang diprakarsai oleh soket dari penggunax
.Cerita yang lebih panjang.
Untuk memahami masalah ini, ada baiknya Anda memahami cara
wget
dan permintaan HTTP berfungsi secara umum.Di
wget
membuat koneksi TCP kecachefly.cachefly.net
, dan setelah didirikan mengirim permintaan dalam protokol HTTP yang mengatakan: "Tolong kirimkan saya isi/10mb.test
(GET /10mb.test HTTP/1.1
) dan omong-omong, bisakah Anda tidak menutup koneksi setelah Anda selesai (Connection: Keep-alive
). Alasannya hal itu terjadi karena seandainya server membalas dengan pengalihan untuk URL pada alamat IP yang sama, itu dapat menggunakan kembali koneksi.Sekarang server dapat menjawab dengan baik, "ini dia data yang Anda minta, berhati-hatilah ukurannya 10MB (
Content-Length: 10485760
), dan ya OK, saya akan membiarkan koneksi terbuka". Atau jika tidak mengetahui ukuran data, "Ini datanya, maaf saya tidak bisa membiarkan koneksi terbuka tetapi saya akan memberi tahu kapan Anda bisa berhenti mengunduh data dengan menutup ujung koneksi saya".Dalam URL di atas, kami berada dalam kasus pertama.
Jadi, segera setelah
wget
mendapatkan tajuk untuk respons, ia tahu tugasnya selesai setelah mengunduh 10MB data.Pada dasarnya, apa yang
wget
dilakukan adalah membaca data sampai 10MB telah diterima dan keluar. Tetapi pada saat itu, masih banyak yang harus dilakukan. Bagaimana dengan server? Sudah diperintahkan untuk membiarkan koneksi terbuka.Sebelum keluar,
wget
tutup (close
panggilan sistem) deskriptor file untuk soket. Setelah ituclose
, sistem selesai mengakui data yang dikirim oleh server dan mengirimFIN
untuk mengatakan: "Saya tidak akan mengirim data lagi". Pada saat ituclose
kembali danwget
keluar. Tidak ada soket yang terkait dengan koneksi TCP lagi (setidaknya tidak ada yang dimiliki oleh pengguna mana pun). Namun itu belum selesai. Setelah menerima ituFIN
, server HTTP melihat end-of-file saat membaca permintaan berikutnya dari klien. Dalam HTTP, itu berarti "tidak ada lagi permintaan, saya akan menutup akhir saya". Jadi ia mengirimkan FIN-nya juga, untuk mengatakan, "Saya juga tidak akan mengirim apa-apa, koneksi itu akan hilang".Setelah menerima FIN itu, klien mengirim "ACK". Tetapi, pada saat itu,
wget
sudah lama berlalu, sehingga ACK bukan dari pengguna mana pun. Karena itulah ia diblokir oleh firewall Anda. Karena server tidak menerima ACK, ia akan mengirim FIN berulang-ulang sampai menyerah dan Anda akan melihat lebih banyak ACK yang jatuh. Itu juga berarti bahwa dengan menjatuhkan 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-live" atau server tidak menjawab dengan "Keep-Live".
Seperti yang telah disebutkan, jika Anda menggunakan pelacak koneksi, yang ingin Anda lakukan adalah membiarkan setiap paket dalam status ESTABLISHED dan TERKAIT melalui dan hanya khawatir tentang
NEW
paket.Jika Anda mengizinkan
NEW
paket dari penggunax
tetapi bukan paket dari penggunay
, maka paket lain untuk koneksi yang dibuat oleh penggunax
akan melalui, dan karena tidak ada koneksi yang dibuat oleh penggunay
(karena kami memblokirNEW
paket yang akan membuat koneksi), tidak akan ada paket untuky
koneksi pengguna yang melalui.sumber
- yah, setidaknya aturan yang Anda tunjukkan tidak menyiratkan ini, sebenarnya.
Ada juga ruang untuk saran - jangan lakukan pengguna memeriksa aliran ESTABLISHED, lakukan saja memeriksa BARU. Saya juga tidak melihat titik dalam memeriksa port sumber saat memeriksa Incoming ESTABLISHED, apa bedanya port mana, itu sudah dalam keadaan ESTABLISHED dari conntrack's PoV. Firewall harus sesederhana mungkin tetapi belum efisien, sehingga pendekatan pisau cukur Occam paling cocok.
sumber