Halo Jadi ada jaringan klien 5k. Baru-baru ini momen yang tidak begitu menyenangkan keluar - di pusat jaringan dan kami memiliki Brocade RX8 dan mulai mengirim banyak paket tidak dikenal-unicast, karena jaringan dibagi menjadi vlan - ini sebagian bukan masalah TETAPI ada vlan khusus untuk alamat putih, dll. dan mereka membentang ke segala arah jaringan. Jadi sekarang bayangkan aliran masuk ke alamat klien yang tidak belajar sebagai asrama dan aliran ini terbang menuju tautan radio ke beberapa desa (dan sebagainya semuanya) - salurannya tersumbat - pelanggan jahat - sedih ...
Tugasnya adalah mengubah bug menjadi fitur. Saya berpikir ke arah q-in-q dengan klien-vlan penuh, tetapi semua jenis besi seperti P3310 ketika saya mengaktifkan dot1q berhenti melewati DHCP, mereka masih tidak tahu bagaimana qinq selektif dan banyak kruk bawah air seperti itu. Apa itu ip-unnambered dan bagaimana cara kerjanya? Jika sangat singkat - alamat gateway + rute pada antarmuka. Untuk tugas kita, kita perlu: memotong pembentuk, mendistribusikan alamat ke klien, menambahkan rute ke klien melalui antarmuka tertentu. Bagaimana cara melakukan semua ini? Pembentuk - lisg, dhcp - db2dhcp pada dua server independen, dhcprelay berjalan pada server akses, ucarp juga berfungsi pada server akses - untuk cadangan. Tetapi bagaimana cara menambahkan rute? Anda dapat menambahkan semuanya dalam skrip besar sebelumnya - tetapi ini tidak benar. Jadi kita akan memagari kruk buatan sendiri.
Setelah mencari-cari di Internet, saya menemukan perpustakaan tingkat tinggi yang luar biasa untuk c ++ yang memungkinkan Anda mengendus lalu lintas. Algoritme program yang menambahkan rute adalah sebagai berikut - kami mendengarkan permintaan antarmuka arp, jika kami memiliki alamat server pada antarmuka yang kami minta, tambahkan rute melalui antarmuka ini dan tambahkan entri arp statis ke ip ini - secara umum, beberapa salin-tempel, lelucon kecil dan Anda selesai
Sumber 'minibus'#include <stdio.h> #include <sys/types.h> #include <ifaddrs.h> #include <netinet/in.h> #include <string.h> #include <arpa/inet.h> #include <tins/tins.h> #include <map> #include <iostream> #include <functional> #include <sstream> using std::cout; using std::endl; using std::map; using std::bind; using std::string; using std::stringstream; using namespace Tins; class arp_monitor { public: void run(Sniffer &sniffer); void reroute(); void makegws(); string iface; map <string, string> gws; private: bool callback(const PDU &pdu); map <string, string> route_map; map <string, string> mac_map; map <IPv4Address, HWAddress<6>> addresses; }; void arp_monitor::makegws() { struct ifaddrs *ifAddrStruct = NULL; struct ifaddrs *ifa = NULL; void *tmpAddrPtr = NULL; gws.clear(); getifaddrs(&ifAddrStruct); for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { if (!ifa->ifa_addr) { continue; } string ifName = ifa->ifa_name; if (ifName == "lo") { char addressBuffer[INET_ADDRSTRLEN]; if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4 // is a valid IP4 Address tmpAddrPtr = &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr; inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN); } else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6 // is a valid IP6 Address tmpAddrPtr = &((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr; inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN); } else { continue; } gws[addressBuffer] = addressBuffer; cout << "GW " << addressBuffer << " is added" << endl; } } if (ifAddrStruct != NULL) freeifaddrs(ifAddrStruct); } void arp_monitor::run(Sniffer &sniffer) { cout << "RUNNED" << endl; sniffer.sniff_loop( bind( &arp_monitor::callback, this, std::placeholders::_1 ) ); } void arp_monitor::reroute() { cout << "REROUTING" << endl; map<string, string>::iterator it; for ( it = route_map.begin(); it != route_map.end(); it++ ) { if (this->gws.count(it->second) && !this->gws.count(it->second)) { string cmd = "ip route replace "; cmd += it->first; cmd += " dev " + this->iface; cmd += " src " + it->second; cmd += " proto static"; cout << cmd << std::endl; cout << "REROUTE " << it->first << " SRC " << it->second << endl; system(cmd.c_str()); cmd = "arp -s "; cmd += it->first; cmd += " "; cmd += mac_map[it->first]; cout << cmd << endl; system(cmd.c_str()); } } for ( it = gws.begin(); it != gws.end(); it++ ) { string cmd = "arping -U -s "; cmd += it->first; cmd += " -I "; cmd += this->iface; cmd += " -b -c 1 "; cmd += it->first; system(cmd.c_str()); } cout << "REROUTED" << endl; } bool arp_monitor::callback(const PDU &pdu) { // Retrieve the ARP layer const ARP &arp = pdu.rfind_pdu<ARP>(); if (arp.opcode() == ARP::REQUEST) { string target = arp.target_ip_addr().to_string(); string sender = arp.sender_ip_addr().to_string(); this->route_map[sender] = target; this->mac_map[sender] = arp.sender_hw_addr().to_string(); cout << "save sender " << sender << ":" << this->mac_map[sender] << " want taregt " << target << endl; if (this->gws.count(target) && !this->gws.count(sender)) { string cmd = "ip route replace "; cmd += sender; cmd += " dev " + this->iface; cmd += " src " + target; cmd += " proto static"; // cout << cmd << std::endl; /* cout << "ARP REQUEST FROM " << arp.sender_ip_addr() << " for address " << arp.target_ip_addr() << " sender hw address " << arp.sender_hw_addr() << std::endl << " run cmd: " << cmd << endl;*/ system(cmd.c_str()); cmd = "arp -s "; cmd += arp.sender_ip_addr().to_string(); cmd += " "; cmd += arp.sender_hw_addr().to_string(); cout << cmd << endl; system(cmd.c_str()); } } return true; } arp_monitor monitor; void reroute(int signum) { monitor.makegws(); monitor.reroute(); } int main(int argc, char *argv[]) { string test; cout << sizeof(string) << endl; if (argc != 2) { cout << "Usage: " << *argv << " <interface>" << endl; return 1; } signal(SIGHUP, reroute); monitor.iface = argv[1]; // Sniffer configuration SnifferConfiguration config; config.set_promisc_mode(true); config.set_filter("arp"); monitor.makegws(); try { // Sniff on the provided interface in promiscuous mode Sniffer sniffer(argv[1], config); // Only capture arp packets monitor.run(sniffer); } catch (std::exception &ex) { std::cerr << "Error: " << ex.what() << std::endl; } }
Perintah untuk membangun biner g++ main.cpp -o arp-rt -O3 -std=c++11 -lpthread -ltins
Bagaimana cara menjalankannya? start-stop-daemon --start --exec /opt/ipoe/arp-routes/arp-rt -b -m -p /opt/ipoe/arp-routes/daemons/eth0.800.pid -- eth0.800
Ya - ini mengesampingkan tabel pada sinyal HUP. Kenapa tidak menggunakan netlink? Kemalasan hanya ya, dan Linux adalah skrip pada skrip - sehingga semuanya baik-baik saja. Nah rute rute, selanjutnya apa? Selanjutnya, kita perlu mengirim rute yang ada di server ini ke perbatasan - di sini, karena potongan besi yang sama, kami pergi dengan sedikit perlawanan - kami menempatkan tugas ini di BGP.
Konfigurasi Bgpnama host *******
kata sandi *******
file log /var/log/bgp.log
!
# jumlah alamat, alamat, dan jaringan yang ditemukan
router bgp 12345
bgp router-id 1.2.3.4
mendistribusikan kembali terhubung
mendistribusikan ulang statis
tetangga 1.2.3.1 remote-as 12345
tetangga 1.2.3.1 next-hop-self
tetangga 1.2.3.1 rute-peta tidak ada di
tetangga 1.2.3.1 ekspor-peta rute keluar
!
izin ekspor daftar akses 1.2.3.0/24
!
izin ekspor rute-peta 10
cocokkan ekspor alamat ip
!
ekspor rute-peta ditolak 20
Kami melanjutkan. Agar server menanggapi permintaan arp, Anda harus mengaktifkan proxy arp.
echo 1 > /proc/sys/net/ipv4/conf/eth0.800/proxy_arp
Silakan - ucarp. Skrip untuk meluncurkan keajaiban ini kami tulis sendiri
Contoh memulai daemon tunggal start-stop-daemon --start --exec /usr/sbin/ucarp -b -m -p /opt/ipoe/ucarp-gen2/daemons/$iface.$vhid.$virtualaddr.pid -- --interface=eth0.800 --srcip=1.2.3.4 --vhid=1 --pass=carpasword --addr=10.10.10.1 --upscript=/opt/ipoe/ucarp-gen2/up.sh --downscript=/opt/ipoe/ucarp-gen2/down.sh -z -k 10 -P --xparam="10.10.10.0/24"
Agar dhcprelay dapat bekerja pada sebuah antarmuka, diperlukan suatu alamat. Oleh karena itu, pada antarmuka yang kami gunakan, kami akan menambahkan alamat kiri - misalnya, 10.255.255.1/32, 10.255.255.2/32, dll. Saya tidak akan memberi tahu Anda cara mengatur relay - semuanya sederhana di sana.
Jadi apa yang kita miliki. Gerbang cadangan, rute pencarian otomatis, dhcp. Ini adalah set minimum - bahkan lisg kacau di atasnya dan kita sudah memiliki pembentuk. Mengapa semuanya begitu panjang dan keren? Bukankah lebih mudah untuk menggunakan accel-pppd dan umumnya menggunakan pppoe? Tidak, itu tidak mudah - orang tidak bisa mendorong patchcord ke router, belum lagi pppoe. accel-ppp adalah hal yang keren - tapi itu tidak berhasil bagi kita - banyak kesalahan dalam kode - itu bergulir, memotong miring, dan yang menyedihkan adalah jika itu dinyalakan, maka orang perlu me-restart semuanya - telepon berwarna merah - secara umum, itu tidak cocok. Apa nilai tambah menggunakan ucarp daripada terus hidup? Ya, dalam segala hal - ada 100 gateway, disimpan dan satu kesalahan dalam konfigurasi - semuanya tidak berfungsi. 1 gateway tidak berfungsi dengan ucarp. Mengenai keamanan, mereka mengatakan alamat akan kidal dan akan digunakan pada bola - untuk mengontrol saat ini, kami mengkonfigurasi dhcp-snooping + sumber-penjaga + inspeksi arp pada semua switch / alt / pangkalan. Jika klien tidak memiliki dhpc tetapi statika - acces-list pada port.
Mengapa ini semua dilakukan? Untuk menghancurkan traffic yang tidak kita sukai. Sekarang setiap switch memiliki vlan sendiri dan unicast yang tidak dikenal tidak lagi takut, karena hanya perlu pergi ke satu port dan tidak semuanya ... Yah, efek sampingnya adalah konfigurasi perangkat keras standar dan efisiensi tinggi alokasi ruang alamat.
Cara mengkonfigurasi lisg adalah topik yang terpisah. Tautan ke perpustakaan terlampir. Mungkin seseorang akan membantu hal di atas dalam pelaksanaan tugasnya. Kami belum memperkenalkan versi 6 di jaringan kami - tetapi akan ada masalah - ada rencana untuk menulis ulang lisg untuk versi 6 dengan baik, dan Anda perlu mengubah program, yang menambahkan rute.
Linux ISGDB2DHCPLibyaUPD
Segalanya menjadi sedikit lebih rumit ... Saya harus menulis iblis yang kurang lebih normal. Dan lakukan tanpa arp proxy. Sekarang daemon saya menjawab arp, itu juga menambah / menghapus rute pada subnet ke klien, saya juga harus belajar cara bekerja dengan netlink. Dan ternyata satu fitur - ketika Linux mengenali arp ke beberapa alamat, kemudian setelah menemukan antarmuka - ia mengambil alamat pertama yang datang dari yang terakhir - yang tidak ditanggapi oleh beberapa pelanggan - diselesaikan menggunakan arptables.
Secara umum, sudah ada opsi normal untuk tautan - di sana, omong-omong, mendengarkan perubahan rute dan alamat dan menambahkan penghapusan rute melalui netlink diterapkan (dengan yang terakhir, sakit kepala sangat mengerikan)
github