Hibatűrő IPeE hálózat rögtönzött eszközökkel

Helló. Ez azt jelenti, hogy van egy 5 ezer ügyfélből álló hálózat. Nemrég jött egy nem túl kellemes pillanat - a hálózat közepén van egy Brocade RX8-unk és rengeteg ismeretlen-unicast csomagot kezdett küldeni, mivel a hálózat vlanokra van osztva - ez részben nem probléma, DE vannak speciális vlanok fehér címekhez stb. és a hálózat minden irányába ki vannak feszítve. Tehát most képzeljünk el egy bejövő áramlást egy olyan ügyfél címére, aki nem határon túli diákként tanul, és ez az áramlás egy (vagy az összes) falu rádiókapcsolata felé repül - eltömődött a csatorna - dühösek az ügyfelek - szomorúság...

A cél az, hogy egy hibát funkcióvá alakítsunk. A q-in-q irányába gondoltam egy teljes értékű kliens vlan-nel, de mindenféle hardver, mint a P3310, amikor a dot1q be van kapcsolva, nem engedi át a DHCP-t, nem tudják, hogyan kell szelektív qinq-t és sok buktatót. az a fajta. Mi az a névtelen ip és hogyan működik? Nagyon röviden: átjáró címe + útvonal a felületen. Feladatunkhoz szükségünk van: vágni a formálót, címeket kiosztani a klienseknek, útvonalakat adni a kliensekhez bizonyos interfészeken keresztül. Hogyan kell mindezt megtenni? Shaper - lisg, dhcp - db2dhcp két független szerveren, a dhcprelay fut a hozzáférési szervereken, az ucarp is fut a hozzáférési szervereken - biztonsági mentés céljából. De hogyan lehet útvonalakat hozzáadni? Egy nagy szkripttel mindent előre hozzá lehet adni – de ez nem igaz. Tehát készítünk egy saját írású mankót.

Alapos keresgélés után az interneten találtam egy csodálatos C++ magas szintű könyvtárat, amivel gyönyörűen le lehet szippantani a forgalmat. Az útvonalakat hozzáadó program algoritmusa a következő - meghallgatjuk az arp kéréseket a felületen, ha a szerveren van egy címünk a lo interfészen, akkor ezen az interfészen keresztül hozzáadunk egy útvonalat és hozzáadunk egy statikus arp-ot rekord erre az IP-re - általában néhány copy-paste, egy kis melléknév és kész

A 'router' forrásai

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

libtins telepítő szkript

#!/bin/bash

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

Parancs a bináris felépítéséhez

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

Hogyan kell elindítani?


start-stop-daemon --start --exec  /opt/ipoe/arp-routes/arp-rt -b -m -p /opt/ipoe/arp-routes/daemons/eth0.800.pid -- eth0.800

Igen – a HUP jel alapján újraépíti a táblázatokat. Miért nem használtad a netlinket? Ez csak lustaság, és a Linux egy szkript a szkripten – szóval minden rendben van. Nos, az útvonalak útvonalak, mi lesz ezután? Ezután a határra kell küldenünk azokat az útvonalakat, amelyek ezen a szerveren vannak - itt ugyanaz az elavult hardver miatt a legkisebb ellenállás útját választottuk - ezt a feladatot a BGP-hez rendeltük.

bgp konfiggépnév *******
Jelszó *******
naplófájl /var/log/bgp.log
!
# AS szám, cím és hálózat fiktív
router bgp 12345
bgp router-id 1.2.3.4
újraelosztás csatlakoztatva
statikus újraelosztása
szomszéd 1.2.3.1 távoli-as 12345
szomszéd 1.2.3.1 next-hop-self
szomszéd 1.2.3.1 útvonal-térkép nincs benne
szomszéd 1.2.3.1 útvonal-térkép export ki
!
hozzáférési lista kiviteli engedély 1.2.3.0/24
!
útvonaltérkép kiviteli engedély 10
egyezik az ip cím exportálása
!
útvonal-térkép export megtagadása 20

Folytassuk. Ahhoz, hogy a szerver válaszoljon az arp kérésekre, engedélyeznie kell az arp proxyt.


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

Menjünk tovább – ucarp. Ennek a csodának az indító forgatókönyveit mi magunk írjuk.

Példa egy démon futtatására


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"

fel.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

le.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

Ahhoz, hogy a dhcprelay működjön egy interfészen, szüksége van egy címre. Ezért az általunk használt felületeken bal oldali címeket adunk hozzá - például 10.255.255.1/32, 10.255.255.2/32 stb. Nem mondom el, hogyan kell konfigurálni a relét - minden egyszerű.

Szóval mi van? Átjárók biztonsági mentése, útvonalak automatikus konfigurálása, dhcp. Ez a minimum készlet - a lisg is mindent köré teker és máris van formálónk. Miért olyan hosszú és zavaros minden? Nem egyszerűbb az accel-pppd használata és a pppoe használata? Nem, nem egyszerűbb – az emberek aligha tudnak patchcordot egy routerbe illeszteni, a pppoe-ról nem is beszélve. az accel-ppp klassz dolog - de nekünk nem ment - sok hiba van a kódban - omlik, ferdén vág, és a legszomorúbb, hogy ha felvilágosodott - akkor újra kell tölteni az embereket minden – pirosak a telefonok – egyáltalán nem működött. Mi az előnye az ucarp használatának az életben maradás helyett? Igen, mindenben - 100 átjáró van, Keepalived és egy hiba a konfigurációban - minden nem működik. 1 átjáró nem működik ucarp-pal. A biztonsággal kapcsolatban azt mondják, hogy a baloldaliak regisztrálnak maguknak címeket és használják a megosztáson - ennek a pillanatnak a kontrollálására minden switchen/oltson/base-on beállítjuk a dhcp-snooping + source-guard + arp ellenőrzést. Ha a kliensnek nincs dhpc, hanem statikus - acces-listja a porton.

Miért történt mindez? A nem kívánt forgalom elpusztítására. Most már minden kapcsolónak megvan a saját vlan-je, és az ismeretlen-unicast már nem ijesztő, hiszen csak egy portra kell mennie, és nem az összesre... Nos, a mellékhatások egy szabványos berendezéskonfiguráció, nagyobb hatékonyság a címterület kiosztásában.

Az lisg konfigurálása egy külön téma. A könyvtárak linkjei mellékelve. Talán a fentiek segítenek valakinek céljai elérésében. A 6-os verzió még nem kerül bevezetésre a hálózatunkon - de lesz egy probléma -, a 6-os verzióra tervezik átírni az lisg-t, és szükség lesz az útvonalakat hozzáadó program javítására.

Linux ISG
DB2DHCP
Libtins

Forrás: will.com

Hozzászólás