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

Implementasi NAT tidak memerlukan sumber daya komputasi khusus; hal ini dapat ditangani oleh prosesor tujuan umum, seperti yang terdapat pada router rumahan mana pun. Pada skala operator telekomunikasi, tugas ini dapat diselesaikan menggunakan server komoditas yang menjalankan FreeBSD (ipfw/pf) atau GNU/Linux (iptables). Kita tidak akan membahas FreeBSD, karena saya sudah lama berhenti menggunakan OS tersebut, jadi mari kita 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 penuh yang dapat menyiarkan sejumlah besar alamat klien ke kumpulan alamat eksternal. Namun, kinerja solusi ini masih jauh dari memuaskan. Dalam percobaan pertama saya menggunakan GNU/Linux Untuk NAT (sekitar tahun 2013), saya mampu mendapatkan performa sekitar 7 Gbit/s pada 0.8 Mpps di satu server (Xeon E5-1650v2). Sejak saat itu, tumpukan jaringan kernel GNU/Linux Berbagai optimasi dilakukan, dan kinerja satu server pada perangkat keras yang sama meningkat hingga hampir 18-19 Gbit/s pada 1.8-1.9 Mpps (ini adalah nilai maksimum), tetapi permintaan lalu lintas yang ditangani oleh satu server tumbuh jauh lebih cepat. Pada akhirnya, skema penyeimbangan beban dikembangkan untuk server yang berbeda, tetapi semua ini meningkatkan kompleksitas pengaturan, pemeliharaan, dan menjaga 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 seberapa jauh lebih cepatnya, saya akan melampirkan tangkapan layar beban pada dua server sungguhan, dengan perangkat keras yang sama (Xeon E5-1650v2), dikonfigurasi secara identik, menggunakan inti yang sama. Linux, tetapi melakukan 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

Beli hosting yang andal untuk situs dengan perlindungan DDoS, server VPS VDS 🔥 Beli hosting website andal dengan perlindungan DDoS, server VPS VDS | ProHoster