Jaringan IPeE sing tahan kesalahan nggunakake alat improvisasi

Halo. Iki tegese ana jaringan 5k klien. Bubar ana wayahe sing ora nyenengake - ing tengah jaringan kita duwe Brocade RX8 lan wiwit ngirim akeh paket unicast sing ora dingerteni, amarga jaringan kasebut dipérang dadi vlan - iki ora dadi masalah, nanging ana vlan khusus kanggo alamat putih, etc. lan padha digawe dowo ing kabeh arah saka jaringan. Dadi saiki mbayangno aliran mlebu menyang alamat klien sing ora sinau minangka siswa perbatasan lan aliran iki mabur menyang link radio menyang sawetara (utawa kabeh) desa - saluran kasebut macet - klien nesu - sedih ...

Tujuane kanggo ngowahi bug dadi fitur. Aku iki mikir ing arah q-in-q karo vlan klien lengkap, nanging kabeh limo hardware kaya P3310, nalika dot1q diaktifake, mandheg supaya DHCP liwat, padha uga ora ngerti carane milih qinq lan akeh. pitfalls saka jinis sing. Apa ip-unnambered lan kepiye cara kerjane? Sedhela banget: alamat gateway + rute ing antarmuka. Kanggo tugas kita, kita kudu: Cut shaper, disebaraké alamat kanggo klien, nambah rute kanggo klien liwat antarmuka tartamtu. Kepiye carane nindakake kabeh iki? Shaper - lisg, dhcp - db2dhcp ing rong server independen, dhcprelay mlaku ing server akses, ucarp uga mbukak ing server akses - kanggo serep. Nanging carane nambah rute? Sampeyan bisa nambah kabeh ing advance karo script gedhe - nanging iki ora bener. Dadi kita bakal nggawe kruk sing ditulis dhewe.

Sawise telusuran lengkap ing Internet, aku nemokake perpustakaan tingkat dhuwur sing apik kanggo C ++, sing ngidini sampeyan ngobati lalu lintas kanthi apik. Algoritma kanggo program sing nambah rute kaya ing ngisor iki - kita ngrungokake panjalukan arp ing antarmuka, yen kita duwe alamat ing antarmuka lo ing server sing dijaluk, banjur kita nambah rute liwat antarmuka iki lan nambah arp statis. ngrekam menyang ip iki - ing umum, sawetara salinan-tempel, adjective sethitik lan sampeyan wis rampung

Sumber saka '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;
    }
}

skrip instalasi libtins

#!/bin/bash

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

Prentah kanggo mbangun binar

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

Carane miwiti?


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

Ya - bakal mbangun maneh tabel adhedhasar sinyal HUP. Apa sampeyan ora nggunakake netlink? Iku mung kesed lan Linux minangka script ing script - supaya kabeh iku nggoleki. Inggih, rute punika rute, apa sabanjuré? Sabanjure, kita kudu ngirim rute sing ana ing server iki menyang tapel wates - kene, amarga hardware lawas sing padha, kita njupuk dalan sing paling ora tahan - kita menehi tugas iki menyang BGP.

bgp konfigurasijeneng host *****
sandi *****
file log /var/log/bgp.log
!
# Nomer AS, alamat lan jaringan iku fiktif
router bgp 12345 kab
bgp router-id 1.2.3.4
mbagekke disambungake
mbagekke statis
pepadhamu 1.2.3.1 remot-minangka 12345
pepadhamu 1.2.3.1 sabanjuré-hop-dhewe
pepadhamu 1.2.3.1 route-map ora ana ing
pepadhamu 1.2.3.1 route-map ekspor metu
!
akses-dhaftar ijin ekspor 1.2.3.0/24
!
Izin ekspor peta rute 10
cocog ekspor alamat ip
!
rute-peta ekspor ditolak 20

Ayo diterusake. Supaya server bisa nanggapi panjalukan arp, sampeyan kudu ngaktifake proxy arp.


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

Ayo nerusake - ucarp. Kita dhewe nulis skrip peluncuran kanggo keajaiban iki.

Conto mlaku siji 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"

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

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

Kanggo dhcprelay bisa ing antarmuka, iku perlu alamat. Mulane, ing antarmuka sing digunakake kita bakal nambah alamat kiwa - contone 10.255.255.1/32, 10.255.255.2/32, etc. Aku ora bakal pitutur marang kowe carane ngatur relay - kabeh iku prasaja.

Dadi apa sing kita duwe? Gawe serep gateway, konfigurasi otomatis rute, dhcp. Iki minangka set minimal - lisg uga mbungkus kabeh lan kita wis duwe shaper. Apa kabeh dadi dawa lan bingung? Apa ora luwih gampang kanggo njupuk accel-pppd lan nggunakake pppoe kabeh? Ora, iku ora luwih prasaja - wong meh ora bisa masang patchcord menyang router, ora kanggo sebutno pppoe. accel-ppp iku apik banget - nanging ora bisa digunakake kanggo kita - ana akeh kesalahan ing kode - crumbles, ngethok crookedly, lan sing paling sedhih yaiku yen padhang - banjur wong kudu ngisi maneh. kabeh - telpon abang - ora bisa digunakake. Apa keuntungan nggunakake ucarp tinimbang keepalived? Ya, ing kabeh - ana 100 gateways, keepalived lan siji kesalahan ing config - kabeh ora bisa. 1 gateway ora bisa digunakake karo ucarp. Babagan keamanan, padha ngomong sing kiwa bakal ndhaftar alamat kanggo awake dhewe lan bakal digunakake ing nuduhake - kanggo kontrol wayahe iki, kita nyiyapake dhcp-snooping + sumber-jaga + pengawasan arp ing kabeh ngalih / olts / basis. Yen klien ora duwe dhpc nanging statis - acces-list ing port.

Yagene kabeh iki ditindakake? Kanggo ngrusak lalu lintas sing ora dikarepake. Saiki saben ngalih wis vlan dhewe lan dingerteni-unicast ora medeni maneh, awit iku mung perlu kanggo pindhah menyang siji port lan ora kanggo kabeh ... Inggih, efek sisih config peralatan standar, efficiency luwih ing allocating papan alamat.

Carane ngatur lisg topik kapisah. Link menyang perpustakaan ditempelake. Mbokmenawa ing ndhuwur bakal mbantu wong kanggo nggayuh tujuane. Versi 6 durung dileksanakake ing jaringan kita - nanging bakal ana masalah - ana rencana kanggo nulis ulang lisg kanggo versi 6, lan bakal perlu kanggo mbenerake program sing nambah rute.

Linux ISG
DB2DHCP
Libtins

Source: www.habr.com

Add a comment