Perutean cepat dan NAT di Linux

Ketika alamat IPv4 habis, banyak operator telekomunikasi dihadapkan pada kebutuhan untuk menyediakan akses jaringan kepada klien mereka menggunakan terjemahan alamat. Pada artikel ini saya akan memberi tahu Anda bagaimana Anda bisa mendapatkan kinerja Carrier Grade NAT di server komoditas.

Sedikit sejarah

Topik kehabisan ruang alamat IPv4 bukan lagi hal baru. Pada titik tertentu, daftar tunggu muncul di RIPE, kemudian muncul pertukaran di mana blok alamat diperdagangkan dan kesepakatan dibuat untuk menyewakannya. Secara bertahap, operator telekomunikasi mulai menyediakan layanan akses Internet menggunakan terjemahan alamat dan port. Beberapa tidak berhasil mendapatkan alamat yang cukup untuk mengeluarkan alamat “putih” kepada setiap pelanggan, sementara yang lain mulai menghemat uang dengan menolak membeli alamat di pasar sekunder. Produsen peralatan jaringan mendukung gagasan ini karena fungsi ini biasanya memerlukan modul ekstensi atau lisensi tambahan. Misalnya, di jajaran router MX Juniper (kecuali MX104 dan MX204 terbaru), Anda dapat melakukan NAPT pada kartu layanan MS-MIC terpisah, Cisco ASR1k memerlukan lisensi CGN, Cisco ASR9k memerlukan modul A9K-ISM-100 terpisah dan lisensi A9K-CGN -LIC kepadanya. Secara umum, kesenangan itu menghabiskan banyak uang.

IPTables

Tugas melakukan NAT tidak memerlukan sumber daya komputasi khusus; tugas ini dapat diselesaikan dengan prosesor tujuan umum, yang dipasang, misalnya, di router rumah mana pun. Pada skala operator telekomunikasi, masalah ini dapat diselesaikan dengan menggunakan server komoditas yang menjalankan FreeBSD (ipfw/pf) atau GNU/Linux (iptables). Kami tidak akan mempertimbangkan FreeBSD, karena... Saya sudah lama berhenti menggunakan OS ini, jadi kami akan tetap menggunakan GNU/Linux.

Mengaktifkan terjemahan alamat sama sekali tidak sulit. Pertama, Anda perlu mendaftarkan 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 memantau semua koneksi aktif dan melakukan konversi yang diperlukan. Ada beberapa kehalusan di sini. Pertama, karena kita berbicara tentang NAT pada skala operator telekomunikasi, maka perlu untuk menyesuaikan batas waktu, karena dengan nilai default, ukuran tabel terjemahan akan dengan cepat bertambah ke 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 tabel terjemahan tidak dirancang untuk berfungsi di bawah kondisi operator telekomunikasi, maka perlu ditingkatkan:

net.netfilter.nf_conntrack_max = 3145728

Penting juga untuk menambah jumlah keranjang untuk tabel hash yang menyimpan semua siaran (ini adalah opsi dalam modul nf_conntrack):

options nf_conntrack hashsize=1572864

Setelah manipulasi sederhana ini, diperoleh desain yang berfungsi sepenuhnya yang mampu menerjemahkan sejumlah besar alamat klien ke dalam kumpulan alamat eksternal. Namun, kinerja solusi ini masih jauh dari harapan. Dalam percobaan pertama saya menggunakan GNU/Linux untuk NAT (sekitar tahun 2013), saya bisa mendapatkan kinerja sekitar 7Gbit/s pada 0.8Mpps per server (Xeon E5-1650v2). Sejak saat itu, banyak optimasi berbeda telah dilakukan pada tumpukan jaringan kernel GNU/Linux, kinerja satu server pada perangkat keras yang sama telah meningkat hingga hampir 18-19 Gbit/s pada 1.8-1.9 Mpps (ini adalah nilai maksimum) , namun permintaan volume lalu lintas yang diproses oleh satu server tumbuh jauh lebih cepat. Akibatnya, skema dikembangkan untuk menyeimbangkan beban pada server yang berbeda, namun semua ini meningkatkan kompleksitas pengaturan, pemeliharaan, dan pemeliharaan kualitas layanan yang diberikan.

NTFables

Saat ini, tren modis dalam perangkat lunak “perpindahan tas” adalah penggunaan DPDK dan XDP. Banyak artikel telah ditulis tentang topik ini, banyak pidato berbeda telah disampaikan, dan produk komersial bermunculan (misalnya, SKAT dari VasExperts). Namun mengingat terbatasnya sumber daya pemrograman dari operator telekomunikasi, membuat “produk” apa pun berdasarkan kerangka kerja ini sendiri cukup bermasalah. Akan jauh lebih sulit untuk menerapkan solusi seperti ini di masa depan; khususnya, alat diagnostik harus dikembangkan. Misalnya, tcpdump standar dengan DPDK tidak akan berfungsi begitu saja, dan tidak akan “melihat” paket yang dikirim kembali ke kabel menggunakan XDP. Di tengah semua pembicaraan tentang teknologi baru untuk meneruskan penerusan paket ke ruang pengguna, hal-hal tersebut luput dari perhatian laporan и Artikel Pablo Neira Ayuso, pengelola iptables, tentang perkembangan flow offloading di nftables. Mari kita lihat lebih dekat mekanisme ini.

Ide utamanya adalah jika router melewatkan paket dari satu sesi di kedua arah aliran (sesi TCP masuk ke status ESTABLISHED), maka paket berikutnya dari sesi ini tidak perlu diteruskan melalui semua aturan firewall, karena semua pemeriksaan ini akan tetap berakhir dengan paket yang ditransfer lebih jauh ke routing. Dan kita sebenarnya tidak perlu memilih rute - kita sudah tahu ke antarmuka mana dan ke host mana kita perlu mengirim paket dalam sesi ini. Yang tersisa hanyalah menyimpan informasi ini dan menggunakannya untuk perutean pada tahap awal pemrosesan paket. Saat melakukan NAT, perlu juga menyimpan informasi tentang perubahan alamat dan port yang diterjemahkan oleh modul nf_conntrack. Ya, tentu saja, dalam hal ini berbagai polisi dan informasi serta aturan statistik lainnya di iptables berhenti bekerja, tetapi dalam kerangka tugas NAT yang terpisah atau, misalnya, perbatasan, ini tidak begitu penting, karena layanan didistribusikan ke seluruh perangkat.

Konfigurasi

Untuk menggunakan fungsi ini kita membutuhkan:

  • Gunakan kernel segar. Terlepas dari kenyataan bahwa fungsi itu sendiri muncul di kernel 4.16, untuk waktu yang cukup lama fungsi tersebut sangat "mentah" dan sering menyebabkan kepanikan kernel. Semuanya stabil sekitar bulan 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. Bekerja persis di versi 0.9.0

Jika pada prinsipnya semuanya sudah jelas dengan poin pertama, yang utama jangan lupa menyertakan modul dalam konfigurasi selama perakitan (CONFIG_NFT_FLOW_OFFLOAD=m), maka poin kedua memerlukan penjelasan. Aturan nftables dijelaskan dengan cara yang sangat berbeda dari pada iptables. Документация mengungkapkan hampir semua poin, ada juga yang spesial konverter aturan dari iptables ke nftables. Oleh karena itu saya hanya akan memberikan contoh setting NAT dan flow offload saja. Legenda kecil misalnya: , - ini adalah antarmuka jaringan yang dilalui lalu lintas; pada kenyataannya, bisa ada lebih dari dua. , — 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
        }
}

Dengan flow offload, ini sedikit lebih rumit, tetapi cukup bisa 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;
        }
}

Faktanya, itulah keseluruhan pengaturannya. Sekarang semua lalu lintas TCP/UDP akan masuk ke tabel fastnat dan diproses lebih cepat.

Temuan

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

Perutean cepat dan NAT di Linux

Tidak ada grafik paket per detik di tangkapan layar, tetapi dalam profil beban server ini rata-rata ukuran paket adalah sekitar 800 byte, sehingga nilainya mencapai hingga 1.5Mpps. Seperti yang Anda lihat, server dengan nftables memiliki cadangan kinerja yang sangat besar. Saat ini, server ini memproses hingga 30Gbit/dtk pada 3Mpps dan jelas mampu memenuhi batasan jaringan fisik sebesar 40Gbps, sekaligus memiliki sumber daya CPU gratis.

Saya harap materi ini bermanfaat bagi para insinyur jaringan yang mencoba meningkatkan kinerja server mereka.

Sumber: www.habr.com

Tambah komentar