Fault-tolerant IPeE network gamit ang mga improvised nga himan

Hello. Kini nagpasabot nga adunay usa ka network sa 5k kliyente. Bag-ohay lang usa ka dili kaayo nindot nga higayon ang miabut - sa sentro sa network kami adunay usa ka Brocade RX8 ug kini nagsugod sa pagpadala sa usa ka daghan sa mga wala mailhi-unicast packets, tungod kay ang network gibahin ngadto sa vlans - kini mao ang partially dili usa ka problema, PERO adunay espesyal nga mga vlan para sa puti nga mga adres, ug uban pa. ug sila gituy-od sa tanang direksyon sa network. Busa karon hunahunaa ang usa ka umaabot nga dagan sa adres sa usa ka kliyente nga wala nagtuon ingon usa ka estudyante sa utlanan ug kini nga dagan molupad padulong sa usa ka link sa radyo sa pipila (o tanan) nga baryo - ang channel nabara - ang mga kliyente nasuko - kasubo ...

Ang tumong mao ang paghimo sa usa ka bug ngadto sa usa ka bahin. Naghunahuna ko sa direksyon sa q-in-q nga adunay usa ka hingpit nga kliyente nga vlan, apan ang tanan nga mga matang sa hardware sama sa P3310, kung ang dot1q ma-enable, mohunong sa pagpasa sa DHCP, wala usab sila kahibalo kung giunsa ang pagpili sa qinq ug daghang mga lit-ag sa kanang matanga. Unsa ang ip-unnambered ug giunsa kini pagtrabaho? Kadiyot kaayo: address sa gateway + ruta sa interface. Alang sa among tahas, kinahanglan namon nga: putlon ang tighulma, pag-apod-apod sa mga adres sa mga kliyente, pagdugang mga ruta sa mga kliyente pinaagi sa pipila nga mga interface. Unsaon pagbuhat niining tanan? Shaper - lisg, dhcp - db2dhcp sa duha ka independente nga mga server, ang dhcprelay midagan sa mga access server, ang ucarp usab midagan sa mga access server - alang sa backup. Apan unsaon pagdugang mga ruta? Mahimo nimong idugang ang tanan nga daan gamit ang usa ka dako nga script - apan kini dili tinuod. Mao nga maghimo kami usa ka self-written crutch.

Pagkahuman sa usa ka bug-os nga pagpangita sa Internet, nakit-an nako ang usa ka matahum nga taas nga lebel nga librarya alang sa C ++, nga nagtugot kanimo sa matahum nga pag-sniff sa trapiko. Ang algorithm alang sa programa nga nagdugang mga ruta mao ang mga musunud - naminaw kami sa mga hangyo sa arp sa interface, kung kami adunay usa ka adres sa lo interface sa server nga gihangyo, nan kami nagdugang usa ka ruta pinaagi sa kini nga interface ug nagdugang usa ka static nga arp irekord sa kini nga ip - sa kinatibuk-an, pipila ka mga kopya-paste, usa ka gamay nga adjective ug nahuman ka

Mga tinubdan sa '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;
    }
}

script sa pag-install sa libtins

#!/bin/bash

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

Sugo sa pagtukod sa binary

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

Giunsa kini paglansad?


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

Oo - kini magtukod pag-usab sa mga lamesa base sa signal sa HUP. Ngano wala ka naggamit sa netlink? Katapulan lang ug ang Linux usa ka script sa usa ka script - mao nga maayo ang tanan. Aw, ang mga ruta kay mga ruta, unsa ang sunod? Sunod, kinahanglan namon nga ipadala ang mga ruta nga naa sa kini nga server sa utlanan - dinhi, tungod sa parehas nga karaan nga hardware, among gikuha ang dalan nga labing gamay nga pagsukol - among gihatag kini nga buluhaton sa BGP.

bgp confighostname *******
password *******
log file /var/log/bgp.log
!
Ang # AS nga numero, mga adres ug mga network dili tinuod
router bgp 12345
bgp router-id 1.2.3.4
pag-apod-apod sa konektado
ipanghatag pag-usab ang static
silingan 1.2.3.1 remote-as 12345
silingan 1.2.3.1 sunod-hop-kaugalingon
silingan 1.2.3.1 ruta-mapa walay in
silingan 1.2.3.1 ruta-mapa export out
!
access-list export permit 1.2.3.0/24
!
permiso sa pag-eksport sa ruta-mapa 10
pagpares sa ip address export
!
ruta-mapa export deny 20

Padayon ta. Aron ang server makatubag sa mga hangyo sa arp, kinahanglan nimo nga palihokon ang arp proxy.


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

Magpadayon ta - ucarp. Kami mismo ang nagsulat sa mga script sa paglansad alang niini nga milagro.

Pananglitan sa pagpadagan sa usa ka 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

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

Alang sa dhcprelay nga magtrabaho sa usa ka interface, kinahanglan kini usa ka adres. Busa, sa mga interface nga atong gigamit atong idugang ang wala nga mga adres - pananglitan 10.255.255.1/32, 10.255.255.2/32, ug uban pa. Dili ko isulti kanimo kung giunsa ang pag-configure sa relay - ang tanan yano ra.

Busa unsay naa kanato? Pag-backup sa mga ganghaan, awtomatikong pag-configure sa mga ruta, dhcp. Kini ang minimum nga set - giputos usab ni lisg ang tanan sa palibot niini ug naa na kami usa ka tighulma. Ngano nga ang tanan taas ug makalibog? Dili ba mas sayon ​​ang pagkuha sa accel-pppd ug paggamit sa pppoe sa tanan? Dili, kini dili mas simple - ang mga tawo halos dili mohaum sa usa ka patchcord sa usa ka router, wala pay labot ang pppoe. Ang accel-ppp usa ka cool nga butang - apan kini wala molihok alang kanamo - adunay daghang mga sayup sa code - kini nahugno, kini nagputol nga hiwi, ug ang labing makapasubo nga butang mao nga kung kini mosanag - nan ang mga tawo kinahanglan nga mag-reload. tanan - ang mga telepono pula - wala gyud kini molihok. Unsa ang kaayohan sa paggamit sa ucarp kaysa keepalived? Oo, sa tanan - adunay 100 nga mga ganghaan, gipadayon ug usa ka sayup sa config - ang tanan wala molihok. Ang 1 gateway dili molihok sa ucarp. Mahitungod sa seguridad, giingon nila nga ang mga wala magrehistro sa mga adres alang sa ilang kaugalingon ug gamiton kini sa bahin - aron makontrol kini nga higayon, gipahimutang namon ang dhcp-snooping + source-guard + arp inspection sa tanan nga mga switch / olts / base. Kung ang kliyente walay dhpc apan static - access-list sa pantalan.

Nganong nahimo kining tanan? Aron maguba ang dili gusto nga trapiko. Karon ang matag switch adunay kaugalingon nga vlan ug wala mailhi-unicast dili na makahadlok, tungod kay kini kinahanglan lamang nga moadto sa usa ka pantalan ug dili sa tanan ... Aw, ang mga side effect usa ka standardized equipment config, mas dako nga efficiency sa paggahin sa address space.

Giunsa ang pag-configure sa lisg usa ka lahi nga hilisgutan. Ang mga link sa mga librarya gilakip. Tingali ang sa ibabaw makatabang sa usa ka tawo sa pagkab-ot sa ilang mga tumong. Ang Bersyon 6 wala pa gipatuman sa among network - apan adunay problema - adunay mga plano nga isulat pag-usab ang lisg alang sa bersyon 6, ug kinahanglan nga matul-id ang programa nga nagdugang mga ruta.

Linux ISG
DB2DHCP
Libtins

Source: www.habr.com

Idugang sa usa ka comment