Akatsen aurrean IPeE sarea inprobisatutako tresnak erabiliz

Kaixo. Horrek esan nahi du 5k bezeroz osatutako sarea dagoela. Duela gutxi momentu ez oso atsegina gertatu zen - sarearen erdian Brocade RX8 bat dugu eta unicast pakete ezezagun asko bidaltzen hasi zen, sarea vlanetan banatuta dagoenez - hori ez da neurri batean arazo bat, BAINA badaude. helbide zurietarako vlan bereziak, etab. eta sarearen norabide guztietan luzatzen dira. Beraz, orain imajinatu mugako ikasle gisa ikasten ari ez den bezero baten helbidera sartzen den fluxu bat eta fluxu hori herrixka batera (edo guztietara) irrati-esteka batera doa hegan - kanala trabatuta dago - bezeroak haserre - tristura...

Helburua akats bat ezaugarri bihurtzea da. Q-in-q-ren norabidean pentsatzen ari nintzen bezero vlan oso batekin, baina P3310 bezalako hardware mota guztiak, dot1q gaituta dagoenean, DHCP pasatzen uzteari uzten dio, ez dakite qinq eta asko nola hautatu. mota horretako zuloak. Zer da ip-unnambered eta nola funtzionatzen du? Oso labur: atebidearen helbidea + ibilbidea interfazean. Gure zereginerako, honako hauek behar ditugu: moldagailua moztu, bezeroei helbideak banatu, bezeroei ibilbideak gehitu zenbait interfazeren bidez. Nola egin hau guztia? Shaper - lisg, dhcp - db2dhcp bi zerbitzari independenteetan, dhcprelay sarbide zerbitzarietan exekutatzen da, ucarp sarbide zerbitzarietan ere exekutatzen da - babeskopiak egiteko. Baina nola gehitu ibilbideak? Dena aldez aurretik gehi dezakezu script handi batekin, baina hori ez da egia. Beraz, norberak idatzitako makulu bat egingo dugu.

Interneten bilaketa sakon bat egin ondoren, C++-rako goi-mailako liburutegi zoragarri bat aurkitu dut, trafikoa ederki usaintzeko aukera ematen duena. Ibilbideak gehitzen dituen programaren algoritmoa honakoa da: interfazean arp eskaerak entzuten ditugu, eskatzen den zerbitzarian lo interfazean helbide bat badugu, interfaze honen bidez ibilbide bat gehitzen dugu eta arp estatiko bat gehitzen dugu. grabatu ip honetan - oro har, kopiatu-itsatsi batzuk, adjektibo apur bat eta listo

'Routerraren' iturriak

#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 instalazio scripta

#!/bin/bash

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

Bitarra eraikitzeko komandoa

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

Nola abiarazi?


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

Bai - HUP seinalean oinarritutako taulak berreraikiko ditu. Zergatik ez duzu netlink erabili? Alferkeria besterik ez da eta Linux script baten script bat da, beraz, dena ondo dago. Tira, ibilbideak ibilbideak dira, zer da hurrengoa? Jarraian, zerbitzari honetan dauden bideak mugara bidali behar ditugu -hemen, hardware zaharkitu bera dela eta, erresistentzia txikieneko bidea hartu genuen- BGPri esleitu genion zeregin hori.

bgp konfigurazioaostalari izena ******
pasahitza ******
/var/log/bgp.log log fitxategia
!
# AS zenbakia, helbideak eta sareak fikziozkoak dira
bgp 12345 bideratzailea
bgp router-id 1.2.3.4
birbanatu konektatuta
birbanatu estatikoa
bizilaguna 1.2.3.1 urruneko 12345 gisa
bizilaguna 1.2.3.1 next-hop-self
bizilaguna 1.2.3.1 ibilbide-mapa bat ere ez
bizilaguna 1.2.3.1 ibilbide-mapa esportatu kanpora
!
sarbide-zerrenda esportatzeko baimena 1.2.3.0/24
!
ibilbide-mapa esportatzeko baimena 10
bat datorren ip helbidea esportatzea
!
ibilbide-mapa esportatzea ukatu 20

Jarrai dezagun. Zerbitzariak arp eskaerei erantzuteko, arp proxya gaitu behar duzu.


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

Goazen aurrera - ucarp. Mirari honen abiarazte-gidoiak guk geuk idazten ditugu.

Deabru bat exekutatzeko adibidea


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"

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

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

dhcprelay-k interfaze batean lan egiteko, helbide bat behar du. Beraz, erabiltzen ditugun interfazeetan ezkerreko helbideak gehituko ditugu - adibidez 10.255.255.1/32, 10.255.255.2/32, etab. Ez dizut esango errelea nola konfiguratu - dena erraza da.

Beraz, zer daukagu? Atebideen babeskopia, ibilbideen autokonfigurazioa, dhcp. Hau da gutxieneko multzoa - lisg-ek bere inguruan guztia biltzen du eta dagoeneko badugu moldagailu bat. Zergatik da dena hain luzea eta nahasia? Ez al da errazagoa accel-pppd hartu eta pppoe guztiz erabiltzea? Ez, ez da sinpleagoa - jendeak nekez sartzen du bideratzaile batean adabaki-kable bat, pppoe ahaztu gabe. accel-ppp gauza polita da - baina ez digu funtzionatu - akats asko daude kodean - hondatzen da, oker mozten da, eta tristeena da alaitzen bada - orduan jendeak berriro kargatu behar duela da. dena - telefonoak gorriak dira - ez zuen batere funtzionatu. Zein abantaila du ucarpa erabiltzeak mantendu baino gehiago? Bai, denetan - 100 ate daude, keepalived eta akats bat konfigurazioan - dena ez dabil. 1 atebideak ez du funtzionatzen ucarp-ekin. Segurtasunari dagokionez, ezkerrekoek euren kabuz helbideak erregistratuko dituztela eta share-an erabiliko dituztela esaten dute - une hau kontrolatzeko, dhcp-snooping + source-guard + arp inspection ezarri dugu switch/olts/base guztietan. Bezeroak ez badu dhpc baina estatikoa - access-list atakan.

Zergatik egin zen hau guztia? Nahi ez den trafikoa suntsitzeko. Orain etengailu bakoitzak bere vlan propioa du eta ezezaguna-unicast jada ez da beldurgarria, ataka batera bakarrik joan behar baita eta ez guztietara... Beno, bigarren mailako efektuak ekipamenduaren konfigurazio estandarizatua dira, helbide-espazioa esleitzean eraginkortasun handiagoa.

Lisg nola konfiguratu aparteko gaia da. Liburutegietarako estekak erantsita daude. Beharbada, goikoak norbaiti bere helburuak lortzen lagunduko dio. 6. bertsioa ez da gure sarean ezartzen oraindik - baina arazo bat egongo da - 6. bertsiorako lisg berridazteko asmoa dago, eta ibilbideak gehitzen dituen programa zuzendu beharko da.

Linux ISG
DB2DHCP
Libitinak

Iturria: www.habr.com

Gehitu iruzkin berria