Perutean cepat dan NAT di Linux

Karena alamat IPv4 habis, banyak operator telekomunikasi dihadapkan dengan kebutuhan untuk mengatur akses klien mereka ke jaringan menggunakan terjemahan alamat. Pada artikel ini saya akan memberi tahu Anda cara mendapatkan kinerja tingkat NAT Carrier Grade di server komoditas.

Sedikit sejarah


Topik kehabisan ruang alamat IPv4 tidak lagi baru. Pada titik tertentu, daftar tunggu muncul di RIPE, kemudian ada pertukaran di mana mereka berdagang blok alamat dan menyimpulkan transaksi untuk sewa mereka. Secara bertahap, operator telekomunikasi mulai menyediakan layanan akses Internet melalui terjemahan alamat dan porta. Seseorang tidak berhasil mendapatkan alamat yang cukup untuk memberikan alamat "putih" kepada setiap pelanggan, sementara seseorang mulai menabung dengan menolak membeli alamat di pasar sekunder. Produsen peralatan jaringan mendukung gagasan ini, seperti fungsi ini biasanya memerlukan modul ekspansi atau lisensi tambahan. Misalnya, dengan Juniper di jajaran router MX (kecuali untuk MX104 dan MX204 terbaru), NAPT dapat dilakukan pada kartu layanan MS-MIC yang terpisah, Cisco ASR1k memerlukan lisensi GN,pada Cisco ASR9k, modul A9K-ISM-100 yang terpisah dan lisensi A9K-CGN-LIC untuknya. Secara umum, kesenangan menghabiskan banyak uang.

Iptables


Tugas melakukan NAT tidak memerlukan sumber daya komputasi khusus, prosesor tujuan umum yang diinstal, misalnya, di router rumah apa pun, dapat menyelesaikannya. Pada skala operator, masalah ini dapat diselesaikan dengan menggunakan server komoditas yang menjalankan FreeBSD (ipfw / pf) atau GNU / Linux (iptables). Kami tidak akan mempertimbangkan FreeBSD, karena Saya menolak untuk menggunakan OS ini untuk waktu yang lama, jadi mari kita fokus pada GNU / Linux.

Mengaktifkan terjemahan alamat sama sekali tidak sulit. Pertama, Anda perlu menulis aturan di iptables di tabel nat:

iptables -t nat -A POSTROUTING -s 100.64.0.0/10 -j SNAT --to <pool_start_addr>-<pool_end_addr> --persistent

Sistem operasi akan memuat modul nf_conntrack, yang akan memonitor semua koneksi aktif dan melakukan konversi yang diperlukan. Ada beberapa kehalusan. Pertama, karena kita berbicara tentang NAT pada skala pembawa, perlu untuk memperketat batas waktu, karena dengan nilai-nilai default, ukuran tabel terjemahan akan dengan cepat tumbuh menjadi nilai-nilai bencana. Di bawah ini adalah contoh pengaturan yang saya gunakan di server saya:

net.ipv4.ip_forward = 1
net.ipv4.ip_local_port_range = 8192 65535

net.netfilter.nf_conntrack_generic_timeout = 300
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 60
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
net.netfilter.nf_conntrack_tcp_timeout_established = 600
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 45
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_udp_timeout_stream = 60
net.netfilter.nf_conntrack_icmpv6_timeout = 30
net.netfilter.nf_conntrack_icmp_timeout = 30
net.netfilter.nf_conntrack_events_retry_timeout = 15
net.netfilter.nf_conntrack_checksum=0

Dan kedua, karena ukuran default dari tabel terjemahan tidak dirancang untuk bekerja dalam kondisi operator telekomunikasi, itu harus ditingkatkan:

net.netfilter.nf_conntrack_max = 3145728

Anda juga perlu menambah jumlah bucket untuk tabel hash yang menyimpan semua terjemahan (ini merupakan opsi dari modul nf_conntrack):

options nf_conntrack hashsize=1572864

Setelah manipulasi sederhana ini, konstruksi yang berfungsi sepenuhnya diperoleh, yang dapat menerjemahkan sejumlah besar alamat klien ke kumpulan eksternal. Namun, kinerja solusi ini buruk. Dalam upaya pertama saya untuk menggunakan GNU / Linux untuk NAT (sekitar 2013), saya bisa mendapatkan kinerja sekitar 7Gbit / s pada 0,8Mpps per server (Xeon E5-1650v2). Sejak saat itu, banyak optimasi yang berbeda telah dibuat dalam tumpukan jaringan kernel GNU / Linux, kinerja satu server pada perangkat keras yang sama telah tumbuh hampir menjadi 18-19 Gbit / s pada 1,8-1,9 Mpps (ini adalah nilai batas), tetapi kebutuhan untuk volume lalu lintas, diproses oleh satu server, tumbuh lebih cepat. Akibatnya, skema load balancing untuk berbagai server dikembangkan, tetapi semua ini meningkatkan kompleksitas pengaturan,melayani dan menjaga kualitas layanan yang diberikan.

Nftables


Saat ini, penggunaan DPDK dan XDP adalah arah yang modis dalam perangkat lunak "transfer paket". Banyak artikel telah ditulis mengenai hal ini, banyak presentasi berbeda telah dibuat, produk komersial muncul (misalnya, SKAT dari VasExperts). Tetapi dalam kondisi sumber daya yang terbatas dari pemrogram dari operator telekomunikasi, itu cukup bermasalah untuk memotong semacam "berbagi" berdasarkan kerangka kerja ini. Untuk mengoperasikan solusi semacam itu di masa depan akan jauh lebih sulit, khususnya, akan diperlukan untuk mengembangkan alat diagnostik. Misalnya, tcpdump reguler dengan DPDK tidak berfungsi, dan itu tidak akan โ€œmelihatโ€ paket yang dikirim kembali ke kabel menggunakan XDP. Di tengah semua pembicaraan tentang teknologi baru untuk mengirimkan penerusan paket ke ruang pengguna, laporan dan artikel tidak diperhatikanPablo Neira Ayuso, pengelola iptables, mengembangkan aliran offloading di nftables. Mari kita lihat mekanisme ini secara lebih rinci.

Gagasan utama adalah bahwa jika router melewati paket satu sesi di kedua sisi aliran (sesi TCP masuk ke keadaan ESTABLISHED), maka tidak perlu untuk melewati paket berikutnya dari sesi ini melalui semua aturan firewall, karena semua cek ini akan berakhir dengan mentransfer paket lebih jauh ke routing. Ya, dan sebenarnya pilihan rute tidak perlu dilakukan - kita sudah tahu antarmuka mana dan tuan rumah mana yang harus meneruskan paket dalam sesi ini. Tetap hanya untuk menyimpan informasi ini dan menggunakannya untuk routing pada tahap awal pemrosesan paket. Saat melakukan NAT, perlu juga menyimpan informasi tentang perubahan alamat dan port yang dikonversi oleh modul nf_conntrack. Ya, tentu saja, dalam hal ini berbagai poliser dan aturan statistik informasi lainnya di iptables berhenti berfungsi,tetapi sebagai bagian dari tugas NAT berdiri terpisah atau, misalnya, perbatasan, ini tidak begitu penting, karena layanan didistribusikan di seluruh perangkat.

Konfigurasi


Untuk menggunakan fungsi ini kita perlu:

  • Gunakan kernel baru. Terlepas dari kenyataan bahwa fungsi itu sendiri muncul di kernel 4,16, untuk beberapa saat itu sangat "mentah" dan secara teratur disebut panik kernel. Semuanya stabil sekitar Desember 2019, ketika kernel LTS 4.19.90 dan 5.4.5 dirilis.
  • Tulis ulang aturan iptables dalam format nftables menggunakan versi nftables yang cukup baru. Berfungsi dengan baik dalam versi 0.9.0

Jika semuanya jelas pada prinsipnya dengan paragraf pertama, hal utama adalah jangan lupa untuk menyertakan modul dalam konfigurasi selama perakitan (CONFIG_NFT_FLOW_OFFLOAD = m), maka paragraf kedua membutuhkan penjelasan. Aturan nftables dijelaskan sangat berbeda dari pada iptables. Dokumentasi mengungkapkan hampir semua poin, ada juga konverter aturan khusus dari iptables ke nftables. Karena itu, saya hanya akan memberikan contoh pengaturan NAT dan aliran offload. Legenda kecil sebagai contoh: <i_if>, <o_if> adalah antarmuka jaringan yang dilaluinya lalu lintas, pada kenyataannya bisa lebih dari dua. <pool_addr_start>, <pool_addr_end> - alamat awal dan akhir dari rentang alamat "putih".

Konfigurasi NAT sangat sederhana:

#! /usr/sbin/nft -f

table nat {
        chain postrouting {
                type nat hook postrouting priority 100;
                oif <o_if> snat to <pool_addr_start>-<pool_addr_end> persistent
        }
}

Flow offload sedikit lebih rumit, tetapi dapat dimengerti:
#! /usr/sbin/nft -f

table inet filter {
        flowtable fastnat {
                hook ingress priority 0
                devices = { <i_if>, <o_if> }
        }

        chain forward {
                type filter hook forward priority 0; policy accept;
                ip protocol { tcp , udp } flow offload @fastnat;
        }
}

Itu, pada kenyataannya, adalah seluruh pengaturan. Sekarang semua lalu lintas TCP / UDP akan pergi ke tabel fastnat dan akan diproses lebih cepat.

hasil


Untuk memperjelas seberapa โ€œlebih cepatโ€ ini, saya akan melampirkan tangkapan layar dari beban pada dua server nyata dengan perangkat keras yang sama (Xeon E5-1650v2), yang dikonfigurasi secara sama, menggunakan kernel Linux yang sama, tetapi menjalankan NAT di iptables (NAT4) dan di nftables (NAT5).



Tidak ada grafik paket per detik di tangkapan layar, tetapi di profil beban server ini ukuran paket rata-rata adalah sekitar 800 byte, sehingga nilainya naik hingga 1,5Mpps. Seperti yang Anda lihat, margin kinerja server dengan nftables sangat besar. Saat ini, server ini memproses hingga 30Gbit / s pada 3Mpps dan jelas dapat mengalami keterbatasan fisik jaringan 40Gbps, sambil memiliki sumber daya CPU gratis.

Saya berharap materi ini akan bermanfaat bagi para insinyur jaringan yang berusaha meningkatkan kinerja server mereka.

All Articles