Foutverdraagsame IPeE-netwerk wat geïmproviseerde gereedskap gebruik

Hallo. Dit beteken daar is 'n netwerk van 5k kliënte. Onlangs het 'n nie baie aangename oomblik aangebreek nie - in die middel van die netwerk het ons 'n Brocade RX8 en dit het baie onbekende-unicast-pakkies begin stuur, aangesien die netwerk in vlans verdeel is - dit is gedeeltelik nie 'n probleem nie, MAAR daar is spesiale vlane vir wit adresse, ens. en hulle word in alle rigtings van die netwerk gespan. So stel jou nou 'n inkomende stroom voor na die adres van 'n kliënt wat nie as 'n grensstudent studeer nie en hierdie stroom vlieg na 'n radioskakel na een of ander (of al) dorpie - die kanaal is verstop - die kliënte is kwaad - hartseer...

Die doel is om 'n fout in 'n kenmerk te verander. Ek het gedink in die rigting van q-in-q met 'n volwaardige kliënt vlan, maar allerhande hardeware soos P3310, wanneer dot1q geaktiveer is, hou op om DHCP deur te laat, hulle weet ook nie hoe om qinq te selekteer nie en baie slaggate van daardie soort. Wat is ip-ongenommer en hoe werk dit? Baie kortliks: poortadres + roete op die koppelvlak. Vir ons taak moet ons: die shaper sny, adresse aan kliënte versprei, roetes by kliënte byvoeg deur sekere koppelvlakke. Hoe om dit alles te doen? Shaper - lisg, dhcp - db2dhcp op twee onafhanklike bedieners, dhcprelay loop op die toegangsbedieners, ucarp loop ook op die toegangsbedieners - vir rugsteun. Maar hoe om roetes by te voeg? Jy kan alles vooraf byvoeg met 'n groot skrif - maar dit is nie waar nie. So ons sal 'n selfgeskrewe kruk maak.

Na 'n deeglike soektog op die internet het ek 'n wonderlike hoëvlak-biblioteek vir C++ gevind, wat jou toelaat om verkeer pragtig te snuffel. Die algoritme vir die program wat roetes byvoeg is soos volg - ons luister na arp-versoeke op die koppelvlak, as ons 'n adres op die lo-koppelvlak op die bediener het wat versoek word, dan voeg ons 'n roete deur hierdie koppelvlak by en voeg 'n statiese arp by rekord na hierdie ip - in die algemeen, 'n paar copy-pastes, 'n bietjie byvoeglike naamwoord en jy is klaar

Bronne van die 'router'

#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 installasie script

#!/bin/bash

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

Opdrag om die binêre te bou

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

Hoe om dit te begin?


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

Ja - dit sal die tabelle herbou op grond van die HUP-sein. Hoekom het jy nie netlink gebruik nie? Dit is net luiheid en Linux is 'n script op 'n script - so alles is reg. Wel, roetes is roetes, wat is volgende? Vervolgens moet ons die roetes wat op hierdie bediener is na die grens stuur - hier, as gevolg van dieselfde verouderde hardeware, het ons die pad van die minste weerstand geneem - ons het hierdie taak aan BGP opgedra.

bgp konfigurasiegasheernaam *******
wagwoord *******
log lêer /var/log/bgp.log
!
# AS-nommer, adresse en netwerke is fiktief
router bgp 12345
bgp router-ID 1.2.3.4
herverdeel gekoppel
staties herverdeel
buurman 1.2.3.1 afstandbeheer-as 12345
buurman 1.2.3.1 volgende-hop-self
buurman 1.2.3.1 roete-kaart geen in
buurman 1.2.3.1 roete-kaart uitvoer uit
!
toegang-lys uitvoerpermit 1.2.3.0/24
!
roetekaart-uitvoerpermit 10
pas ip-adres uitvoer
!
roete-kaart uitvoer weier 20

Kom ons gaan aan. Om die bediener op arp-versoeke te laat reageer, moet jy die arp-instaanbediener aktiveer.


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

Kom ons gaan aan - ucarp. Ons skryf self die bekendstellingsskrifte vir hierdie wonderwerk.

Voorbeeld van hardloop een 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"

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

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

Vir dhcprelay om op 'n koppelvlak te werk, het dit 'n adres nodig. Daarom, op die koppelvlakke wat ons gebruik, sal ons linkeradresse byvoeg - byvoorbeeld 10.255.255.1/32, 10.255.255.2/32, ens. Ek sal jou nie vertel hoe om die aflos op te stel nie - alles is eenvoudig.

So wat het ons? Rugsteun van poorte, outo-konfigurasie van roetes, dhcp. Dit is die minimum stel - lisg vou ook alles om dit en ons het reeds 'n shaper. Hoekom is alles so lank en ingewikkeld? Is dit nie makliker om accel-pppd te neem en pppoe heeltemal te gebruik nie? Nee, dit is nie eenvoudiger nie - mense kan skaars 'n patchcord in 'n router pas, om nie eens te praat van pppoe nie. accel-ppp is 'n gawe ding - maar dit het nie vir ons gewerk nie - daar is baie foute in die kode - dit verkrummel, dit sny skeef, en die hartseerste ding is dat as dit opgehelder het - dan moet mense herlaai alles – die fone is rooi – dit het glad nie gewerk nie. Wat is die voordeel daarvan om ukarp te gebruik eerder as om in die lewe te bly? Ja, in alles - daar is 100 gateways, keepalived en een fout in die config - alles werk nie. 1 gateway werk nie met ucarp nie. Wat sekuriteit betref, sê hulle dat die linkses vir hulself adresse sal registreer en dit op die aandeel sal gebruik - om hierdie oomblik te beheer, het ons dhcp-snooping + source-guard + arp inspeksie op alle skakelaars/olts/basisse opgestel. As die kliënt nie dhpc het nie, maar staties - toegangslys op die poort.

Hoekom is dit alles gedoen? Om ongewenste verkeer te vernietig. Nou het elke skakelaar sy eie vlan en onbekende-unicast is nie meer skrikwekkend nie, aangesien dit net na een poort hoef te gaan en nie na almal nie ... Wel, die newe-effekte is 'n gestandaardiseerde toerustingkonfigurasie, groter doeltreffendheid in die toekenning van adresruimte.

Hoe om lisg op te stel is 'n aparte onderwerp. Skakels na biblioteke is aangeheg. Miskien sal bogenoemde iemand help om hul doelwitte te bereik. Weergawe 6 word nog nie op ons netwerk geïmplementeer nie - maar daar sal 'n probleem wees - daar is planne om lisg vir weergawe 6 te herskryf, en dit sal nodig wees om die program wat roetes byvoeg, reg te stel.

Linux ISG
DB2DHCP
Libtins

Bron: will.com

Voeg 'n opmerking