Rangkaian IPeE tahan kerosakan menggunakan alat yang diubahsuai

Hello. Jadi, kami mempunyai rangkaian 5 pelanggan. Baru-baru ini, kami menghadapi situasi yang agak tidak menyenangkan: kami mempunyai Brocade RX8 di tengah rangkaian, dan ia mula menghantar banyak paket unicast yang tidak diketahui. Memandangkan rangkaian dibahagikan kepada VLAN, ini tidak menjadi masalah, tetapi terdapat VLAN khas untuk alamat putih, dsb., dan ia merentangi seluruh rangkaian. Jadi, bayangkan trafik masuk ke alamat pelanggan yang tidak dilatih oleh protokol sempadan, dan trafik ini dihantar ke pautan radio ke beberapa (atau semua) kampung. Saluran tersumbat, pelanggan marah, dan sedih...

Matlamatnya adalah untuk mengubah pepijat menjadi ciri. Saya sedang mempertimbangkan Q-in-Q dengan klien VLAN yang lengkap, tetapi perkakasan seperti P3310 berhenti menghantar DHCP apabila dot1q didayakan. Mereka juga tidak menyokong Q-in-Q terpilih, dan terdapat banyak perangkap lain di sepanjang baris tersebut. Apakah ip-unnamed dan bagaimana ia berfungsi? Ringkasnya, ia adalah alamat get laluan + laluan pada antara muka. Untuk tugas kami, kami perlu memotong pembentuk, mengedarkan alamat kepada pelanggan dan menambah laluan kepada pelanggan melalui antara muka tertentu. Bagaimana kita melakukan semua ini? Pembentuk adalah lisg, dhcp adalah db2dhcp pada dua pelayan bebas, dhcprelay berjalan pada pelayan akses, dan ucarp juga berjalan pada pelayan akses untuk sandaran. Tetapi bagaimana kita menambah laluan? Kami boleh menambah segala-galanya terlebih dahulu dengan skrip besar, tetapi itu tidak benar. Jadi kita perlu membina hack buatan sendiri.

Selepas beberapa carian internet yang meluas, saya menemui perpustakaan peringkat tinggi yang menarik untuk C++ yang membolehkan penghidu trafik yang elegan. Program penambahan laluan berfungsi seperti berikut: dengar permintaan ARP pada antara muka. Jika pelayan mempunyai alamat pada antara muka LO yang diminta, kami menambah laluan melalui antara muka itu dan menambah entri ARP statik untuk alamat IP tersebut. Pada asasnya, beberapa salinan pasta, sedikit mengutak-atik, dan anda sudah selesai.

Kod sumber untuk 'marshrutchik'

#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;
    }
}

skrip pemasangan libtins

#!/bin/bash

git clone https://github.com/mfontanini/libtins.git
cd libtins
mkdir build
cd build
cmake ../
make
make install
ldconfig

Perintah untuk membina binari

g++ main.cpp -o arp-rt -O3 -std=c++11 -lpthread -ltins

Bagaimana untuk melancarkannya?


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, ia membina semula jadual pada isyarat HUP. Mengapa anda tidak menggunakan NetLink? Saya hanya malas, dan Linux ialah skrip dalam skrip, jadi semuanya baik-baik saja. Jadi, laluan adalah laluan, apa seterusnya? Seterusnya, kita perlu menghantar laluan yang wujud pada pelayan ini ke sempadan. Di sini, disebabkan perkakasan lapuk yang sama, kami mengambil jalan dengan rintangan paling sedikit dan menyerahkan tugas ini kepada BGP.

Konfigurasi BGPnama hos *******
kata laluan *******
fail log /var/log/bgp.log
!
# Nombor ICQ, alamat dan rangkaian adalah rekaan.
penghala bgp 12345
bgp router-id 1.2.3.4
mengagihkan semula bersambung
mengagihkan semula statik
jiran 1.2.3.1 jauh-sebagai 12345
jiran 1.2.3.1 seterusnya-hop-diri
jiran 1.2.3.1 peta laluan tiada masuk
jiran 1.2.3.1 eksport keluar peta laluan
!
permit eksport senarai akses 1.2.3.0/24
!
permit eksport peta laluan 10
sepadan dengan eksport alamat IP
!
eksport peta laluan menafikan 20

Jom sambung. Untuk membolehkan pelayan membalas permintaan ARP, anda perlu mendayakan proksi ARP.


echo 1 > /proc/sys/net/ipv4/conf/eth0.800/proxy_arp

Mari kita beralih kepada ucarp. Kami sendiri akan menulis skrip pelancaran untuk keajaiban ini.

Contoh menjalankan satu daemon


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"

atas.sh


#!/bin/bash

iface=$1
addr=$2
gw=$3

vlan=`echo $1 | sed "s/eth0.//"`


ip ad ad $addr/32 dev lo
ip ro add blackhole $gw
echo 1 > /proc/sys/net/ipv4/conf/$iface/proxy_arp

killall -9 dhcrelay
/etc/init.d/dhcrelay zap
/etc/init.d/dhcrelay start


killall -HUP arp-rt

turun.sh


#!/bin/bash

iface=$1
addr=$2
gw=$3

ip ad d $addr/32 dev lo
ip ro de blackhole $gw
echo 0 > /proc/sys/net/ipv4/conf/$iface/proxy_arp


killall -9 dhcrelay
/etc/init.d/dhcrelay zap
/etc/init.d/dhcrelay start

Untuk dhcprelay berfungsi pada antara muka, ia memerlukan alamat. Oleh itu, pada antara muka yang kami gunakan, kami akan menambah alamat sewenang-wenangnya—contohnya, 10.255.255.1/32, 10.255.255.2/32, dsb. Saya tidak akan menerangkan cara mengkonfigurasi geganti—semuanya mudah.

Jadi, apa yang kita ada? Sandaran gerbang, konfigurasi laluan automatik, DHCP. Itulah jumlah minimum—lisg turut ditambah di atasnya dan kami sudah mempunyai pembentuk. Kenapa semuanya panjang dan rumit? Bukankah lebih mudah untuk hanya menggunakan accel-pppd dan hanya menggunakan PPPOE? Tidak, ia bukan lebih mudah—orang hampir tidak boleh memasukkan tali tampal ke dalam penghala, apatah lagi PPPOE. accel-ppp memang bagus, tetapi ia tidak berfungsi untuk kami—terdapat banyak ralat dalam kod—ia ranap, konfigurasi tidak betul, dan perkara yang paling teruk ialah jika ranap, orang perlu but semula semuanya—telefon berwarna merah—ia tidak berfungsi. Apakah kelebihan menggunakan ucarp berbanding keepalived? Ini segala-galanya—terdapat 100 get laluan, keepalived dan satu ralat dalam konfigurasi—semuanya tidak berfungsi. Dengan ucarp, hanya satu pintu masuk tidak berfungsi. Mengenai keselamatan, mereka mungkin mendaftarkan alamat palsu dan menggunakannya di Sharika. Untuk mengawal ini, kami mengkonfigurasi dhcp-snooping + source-guard + arp inspection pada semua suis/OLT/pangkalan data. Jika pelanggan tidak mempunyai dhpc tetapi alamat IP statik, gunakan senarai akses pada port.

Mengapa semua ini dilakukan? Untuk menghapuskan lalu lintas yang tidak diingini. Kini setiap suis mempunyai VLAN sendiri, dan unicast yang tidak diketahui tidak lagi menjadi masalah, kerana ia hanya perlu mengakses satu port dan bukannya kesemuanya... Dan kesan sampingan termasuk konfigurasi perkakasan piawai dan kecekapan yang lebih besar dalam pengagihan ruang alamat.

Mengkonfigurasi lisg ialah topik yang berasingan. Pautan ke perpustakaan disertakan. Mungkin perkara di atas akan membantu seseorang dengan keperluan mereka sendiri. Versi 6 belum lagi dilaksanakan dalam rangkaian kami, tetapi akan ada masalah—kami merancang untuk menulis semula lisg untuk versi 6, dan kami perlu melaraskan atur cara yang menambah laluan.

Linux ISG
DB2DHCP
Libtins

Sumber: www.habr.com

Beli pengehosan yang boleh dipercayai untuk tapak dengan perlindungan DDoS, pelayan VPS VDS 🔥 Beli pengehosan laman web yang boleh dipercayai dengan perlindungan DDoS, pelayan VPS VDS | ProHoster