Doğaçlama alətlərindən istifadə edərək xətaya davamlı IPeE şəbəkəsi

Salam. Bu o deməkdir ki, 5k müştəri şəbəkəsi var. Bu yaxınlarda o qədər də xoş olmayan bir məqam ortaya çıxdı - şəbəkənin mərkəzində Brocade RX8 var və o, çoxlu naməlum-unicast paketlər göndərməyə başladı, çünki şəbəkə vlanlara bölünür - bu qismən problem deyil, lakin xüsusi proqramlar var. ağ ünvanlar üçün vlanlar və s. və onlar şəbəkənin bütün istiqamətlərində uzanır. İndi sərhəd tələbəsi kimi təhsil almayan müştərinin ünvanına gələn axını təsəvvür edin və bu axın hansısa (yaxud hamısı) kəndə radio bağlantısına doğru uçur - kanal tıxanıb - müştərilər qəzəblənir - kədər...

Məqsəd bir səhvi xüsusiyyətə çevirməkdir. Mən tam hüquqlu bir müştəri vlan ilə q-in-q istiqamətində düşünürdüm, lakin P3310 kimi hər cür avadanlıq, dot1q aktiv olduqda, DHCP keçməyi dayandırır, onlar da seçici qinq və bir çox tələləri bilmirlər. o cür. IP-unnambered nədir və necə işləyir? Çox qısaca: şlüz ünvanı + interfeysdə marşrut. Tapşırığımız üçün bizə lazımdır: formalaşdırıcını kəsin, müştərilərə ünvanları paylayın, müəyyən interfeyslər vasitəsilə müştərilərə marşrutlar əlavə edin. Bütün bunları necə etmək olar? Shaper - lisg, dhcp - db2dhcp iki müstəqil serverdə, dhcprelay giriş serverlərində, ucarp da giriş serverlərində işləyir - ehtiyat üçün. Bəs marşrutları necə əlavə etmək olar? Böyük bir skript ilə hər şeyi əvvəlcədən əlavə edə bilərsiniz - lakin bu doğru deyil. Beləliklə, öz-özünə yazılmış qoltuqağacı düzəldəcəyik.

İnternetdə hərtərəfli axtarışdan sonra mən C++ üçün gözəl yüksək səviyyəli kitabxana tapdım ki, bu da sizə trafiki gözəl şəkildə iyləmək imkanı verir. Marşrutları əlavə edən proqramın alqoritmi belədir - interfeysdə arp sorğularını dinləyirik, əgər tələb olunan serverdə lo interfeysində ünvanımız varsa, o zaman bu interfeys vasitəsilə marşrut əlavə edirik və statik arp əlavə edirik. bu ip-ə yazın - ümumiyyətlə, bir neçə copy-paste, bir az sifət və işiniz bitdi

'Router'in mənbələri

#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 quraşdırma skripti

#!/bin/bash

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

Binar qurmaq əmri

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

Onu necə işə salmaq olar?


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

Bəli - HUP siqnalı əsasında cədvəlləri yenidən quracaq. Niyə netlinkdən istifadə etmədin? Bu, sadəcə tənbəllikdir və Linux bir skript üzərində bir skriptdir - buna görə də hər şey yaxşıdır. Yaxşı, marşrutlar marşrutlardır, bundan sonra nə var? Sonra, bu serverdə olan marşrutları sərhədə göndərməliyik - burada eyni köhnəlmiş aparat sayəsində ən az müqavimət yolunu tutduq - bu tapşırığı BGP-yə təyin etdik.

bgp konfiqurasiyasıhost adı *******
parol *******
log faylı /var/log/bgp.log
!
# AS nömrəsi, ünvanlar və şəbəkələr uydurmadır
Router bgp 12345
bgp router-id 1.2.3.4
yenidən paylayın
statiki yenidən paylayın
qonşu 1.2.3.1 uzaqdan-12345 kimi
qonşu 1.2.3.1 Next-hop-self
qonşu 1.2.3.1 marşrut xəritəsi heç biri
qonşu 1.2.3.1 marşrut-xəritə ixracı
!
giriş siyahısı ixrac icazəsi 1.2.3.0/24
!
marşrut xəritəsi ixracına icazə 10
uyğun ip ünvan ixracı
!
marşrut xəritəsinin ixracını rədd etmək 20

Davam edək. Serverin arp sorğularına cavab verməsi üçün arp proxy-ni aktivləşdirməlisiniz.


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

Davam edək - ucarp. Bu möcüzənin başlanğıc ssenarilərini özümüz yazırıq.

Bir demonu idarə etməyə nümunə


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

aşağı.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 interfeysdə işləməsi üçün ona ünvan lazımdır. Buna görə də, istifadə etdiyimiz interfeyslərə sol ünvanları əlavə edəcəyik - məsələn, 10.255.255.1/32, 10.255.255.2/32 və s. Röleyi necə konfiqurasiya edəcəyinizi sizə deməyəcəyəm - hər şey sadədir.

Bəs bizdə nə var? Şlüzlərin ehtiyat nüsxəsi, marşrutların avtomatik konfiqurasiyası, dhcp. Bu, minimum dəstdir - lisg də onun ətrafına hər şeyi bükür və bizdə artıq formalaşdırıcı var. Niyə hər şey bu qədər uzun və mürəkkəbdir? Accel-pppd-i götürüb pppoe-ni ümumilikdə istifadə etmək daha asan deyilmi? Xeyr, bu, daha sadə deyil - insanlar pppoe-ni qeyd etmədən, marşrutlaşdırıcıya bir patchcord sığdıra bilmirlər. accel-ppp gözəl bir şeydir - amma bizim üçün işləmədi - kodda çoxlu səhvlər var - çökür, əyri şəkildə kəsilir və ən kədərlisi odur ki, işıqlandısa - insanlar yenidən yükləməlidirlər hər şey - telefonlar qırmızıdır - heç işləmirdi. Keepalived əvəzinə ucarp istifadə etməyin üstünlüyü nədir? Bəli, hər şeydə - 100 şlüz var, saxlanılır və konfiqurasiyada bir səhv var - hər şey işləmir. 1 gateway ucarp ilə işləmir. Təhlükəsizliyə gəlincə, deyirlər ki, sollar ünvanları özləri üçün qeydiyyatdan keçirəcək və onlardan paylaşımda istifadə edəcəklər - bu anı idarə etmək üçün bütün açarlarda/olts/bazalarda dhcp-snooping + source-guard + arp yoxlama qurduq. Müştərinin dhpc yoxdur, lakin statik varsa - portda acces-list.

Bütün bunlar niyə edildi? İstənməyən trafiki məhv etmək üçün. İndi hər bir keçidin öz vlanı var və naməlum-unicast artıq qorxulu deyil, çünki o, yalnız bir porta getməlidir və hamısına deyil... Yaxşı, yan təsirlər standartlaşdırılmış avadanlıq konfiqurasiyasıdır, ünvan sahəsinin ayrılması üçün daha yüksək effektivlikdir.

Lisg-i necə konfiqurasiya etmək ayrı bir mövzudur. Kitabxanalara keçidlər əlavə olunur. Yəqin ki, yuxarıda göstərilənlər kiməsə məqsədlərinə çatmaqda kömək edəcək. Şəbəkəmizdə hələ 6-cı versiya tətbiq edilmir - lakin problem olacaq - 6-cı versiya üçün lisg-in yenidən yazılması planları var və marşrutları əlavə edən proqramı düzəltmək lazım olacaq.

Linux ISG
DB2DHCP
Libtinlər

Mənbə: www.habr.com

Добавить комментарий