Penghalaan pantas dan NAT dalam Linux

Apabila alamat IPv4 semakin berkurangan, banyak pengendali telekom berhadapan dengan keperluan untuk menyediakan pelanggan mereka akses rangkaian menggunakan terjemahan alamat. Dalam artikel ini saya akan memberitahu anda bagaimana anda boleh mendapatkan prestasi NAT Gred Pembawa pada pelayan komoditi.

Sedikit sejarah

Topik keletihan ruang alamat IPv4 bukan lagi baharu. Pada satu ketika, senarai menunggu muncul dalam RIPE, kemudian pertukaran muncul di mana blok alamat didagangkan dan tawaran dibuat untuk memajaknya. Secara beransur-ansur, operator telekomunikasi mula menyediakan perkhidmatan akses Internet menggunakan terjemahan alamat dan pelabuhan. Ada yang tidak berjaya mendapatkan alamat yang mencukupi untuk mengeluarkan alamat "putih" kepada setiap pelanggan, sementara yang lain mula menjimatkan wang dengan enggan membeli alamat di pasaran sekunder. Pengeluar peralatan rangkaian menyokong idea ini, kerana fungsi ini biasanya memerlukan modul atau lesen sambungan tambahan. Sebagai contoh, dalam barisan penghala MX Juniper (kecuali MX104 dan MX204 terkini), anda boleh melakukan NAPT pada kad perkhidmatan MS-MIC yang berasingan, Cisco ASR1k memerlukan lesen CGN, Cisco ASR9k memerlukan modul A9K-ISM-100 yang berasingan dan lesen A9K-CGN -LIC kepadanya. Secara umum, keseronokan itu memerlukan banyak wang.

IPTables

Tugas melaksanakan NAT tidak memerlukan sumber pengkomputeran khusus; ia boleh diselesaikan oleh pemproses tujuan umum, yang dipasang, sebagai contoh, dalam mana-mana penghala rumah. Pada skala pengendali telekomunikasi, masalah ini boleh diselesaikan menggunakan pelayan komoditi yang menjalankan FreeBSD (ipfw/pf) atau GNU/Linux (iptables). Kami tidak akan mempertimbangkan FreeBSD, kerana... Saya berhenti menggunakan OS ini agak lama dahulu, jadi kami akan berpegang pada GNU/Linux.

Mendayakan terjemahan alamat tidak sukar sama sekali. Mula-mula anda perlu mendaftarkan peraturan dalam iptables dalam jadual nat:

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

Sistem pengendalian akan memuatkan modul nf_conntrack, yang akan memantau semua sambungan aktif dan melakukan penukaran yang diperlukan. Terdapat beberapa kehalusan di sini. Pertama, kerana kita bercakap tentang NAT pada skala pengendali telekomunikasi, adalah perlu untuk melaraskan tamat masa, kerana dengan nilai lalai saiz jadual terjemahan akan cepat berkembang menjadi nilai bencana. Di bawah ialah contoh tetapan yang saya gunakan pada pelayan 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, kerana saiz lalai jadual terjemahan tidak direka bentuk untuk berfungsi di bawah syarat pengendali telekomunikasi, ia perlu ditingkatkan:

net.netfilter.nf_conntrack_max = 3145728

Ia juga perlu menambah bilangan baldi untuk jadual cincang yang menyimpan semua siaran (ini adalah pilihan dalam modul nf_conntrack):

options nf_conntrack hashsize=1572864

Selepas manipulasi mudah ini, reka bentuk yang berfungsi sepenuhnya diperolehi yang boleh menterjemahkan sejumlah besar alamat pelanggan ke dalam kumpulan alamat luar. Walau bagaimanapun, prestasi penyelesaian ini meninggalkan banyak yang diingini. Dalam percubaan pertama saya menggunakan GNU/Linux untuk NAT (sekitar 2013), saya dapat memperoleh prestasi sekitar 7Gbit/s pada 0.8Mpps setiap pelayan (Xeon E5-1650v2). Sejak masa itu, banyak pengoptimuman berbeza telah dibuat dalam susunan rangkaian kernel GNU/Linux, prestasi satu pelayan pada perkakasan yang sama telah meningkat kepada hampir 18-19 Gbit/s pada 1.8-1.9 Mpps (ini adalah maksimum values), tetapi permintaan untuk volum trafik, yang diproses oleh satu pelayan meningkat dengan lebih pantas. Akibatnya, skim telah dibangunkan untuk mengimbangi beban pada pelayan yang berbeza, tetapi semua ini meningkatkan kerumitan untuk menyediakan, mengekalkan dan mengekalkan kualiti perkhidmatan yang disediakan.

Jadual NF

Pada masa kini, trend bergaya dalam perisian "beg beralih" ialah penggunaan DPDK dan XDP. Banyak artikel telah ditulis mengenai topik ini, banyak ucapan berbeza telah dibuat, dan produk komersial muncul (contohnya, SKAT daripada VasExperts). Tetapi memandangkan sumber pengaturcaraan yang terhad bagi pengendali telekomunikasi, agak bermasalah untuk mencipta sebarang "produk" berdasarkan rangka kerja ini sendiri. Ia akan menjadi lebih sukar untuk mengendalikan penyelesaian sedemikian pada masa hadapan; khususnya, alat diagnostik perlu dibangunkan. Sebagai contoh, tcpdump standard dengan DPDK tidak akan berfungsi begitu sahaja, dan ia tidak akan "melihat" paket yang dihantar semula ke wayar menggunakan XDP. Di tengah-tengah semua perbincangan tentang teknologi baharu untuk mengeluarkan pemajuan paket ke ruang pengguna, mereka tidak disedari laporan ΠΈ Perkara Pablo Neira Ayuso, penyelenggara iptables, tentang pembangunan pemunggahan aliran dalam nftables. Mari kita lihat lebih dekat mekanisme ini.

Idea utama ialah jika penghala melepasi paket dari satu sesi dalam kedua-dua arah aliran (sesi TCP masuk ke keadaan ESTABLISHED), maka tidak ada keperluan untuk lulus paket berikutnya sesi ini melalui semua peraturan firewall, kerana semua semakan ini masih akan berakhir dengan paket dipindahkan lebih jauh ke penghalaan. Dan kami sebenarnya tidak perlu memilih laluan - kami sudah tahu ke antara muka dan ke hos mana kami perlu menghantar paket dalam sesi ini. Yang tinggal hanyalah menyimpan maklumat ini dan menggunakannya untuk penghalaan pada peringkat awal pemprosesan paket. Apabila melaksanakan NAT, adalah perlu untuk menyimpan maklumat tambahan tentang perubahan dalam alamat dan port yang diterjemahkan oleh modul nf_conntrack. Ya, sudah tentu, dalam kes ini pelbagai polis dan maklumat lain dan peraturan statistik dalam iptables berhenti bekerja, tetapi dalam rangka tugas NAT berdiri yang berasingan atau, sebagai contoh, sempadan, ini tidak begitu penting, kerana perkhidmatan diedarkan merentasi peranti.

Konfigurasi

Untuk menggunakan fungsi ini kita perlukan:

  • Gunakan kernel segar. Walaupun fakta bahawa fungsi itu sendiri muncul dalam kernel 4.16, untuk masa yang agak lama ia sangat "mentah" dan kerap menyebabkan panik kernel. Semuanya stabil sekitar Disember 2019, apabila kernel LTS 4.19.90 dan 5.4.5 dikeluarkan.
  • Tulis semula peraturan iptables dalam format nftables menggunakan versi nftables yang agak terkini. Berfungsi betul-betul dalam versi 0.9.0

Sekiranya semuanya pada dasarnya jelas dengan titik pertama, perkara utama adalah jangan lupa memasukkan modul dalam konfigurasi semasa pemasangan (CONFIG_NFT_FLOW_OFFLOAD=m), maka titik kedua memerlukan penjelasan. Peraturan nftables diterangkan secara berbeza daripada dalam iptables. Dokumentasi mendedahkan hampir semua mata, ada juga yang istimewa penukar peraturan daripada iptables kepada nftables. Oleh itu, saya hanya akan memberikan contoh penyediaan NAT dan aliran offload. Legenda kecil contohnya: , - ini adalah antara muka rangkaian yang dilalui trafik; sebenarnya boleh terdapat lebih daripada dua daripadanya. , β€” alamat permulaan dan penamat bagi julat alamat β€œputih”.

Konfigurasi NAT sangat mudah:

#! /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 offload aliran ia adalah sedikit lebih rumit, tetapi agak boleh difahami:

#! /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, sebenarnya, adalah keseluruhan persediaan. Kini semua trafik TCP/UDP akan jatuh ke dalam jadual fastnat dan diproses dengan lebih pantas.

Penemuan

Untuk menjelaskan betapa "lebih pantas" ini, saya akan melampirkan tangkapan skrin beban pada dua pelayan sebenar, dengan perkakasan yang sama (Xeon E5-1650v2), dikonfigurasikan secara identik, menggunakan kernel Linux yang sama, tetapi melaksanakan NAT dalam iptables (NAT4) dan dalam nftables (NAT5).

Penghalaan pantas dan NAT dalam Linux

Tiada graf paket sesaat dalam tangkapan skrin, tetapi dalam profil pemuatan pelayan ini purata saiz paket adalah sekitar 800 bait, jadi nilainya mencapai sehingga 1.5Mpps. Seperti yang anda lihat, pelayan dengan nftables mempunyai rizab prestasi yang besar. Pada masa ini, pelayan ini memproses sehingga 30Gbit/s pada 3Mpps dan jelas mampu memenuhi had rangkaian fizikal 40Gbps, sambil mempunyai sumber CPU percuma.

Saya berharap bahan ini berguna kepada jurutera rangkaian yang cuba meningkatkan prestasi pelayan mereka.

Sumber: www.habr.com

Tambah komen