Rrjeti IPeE i qëndrueshëm nga burime të dorës së parë

PĂ«rshĂ«ndetje. KĂ«shtu qĂ« kemi njĂ« rrjet prej 5k klientĂ«sh. KohĂ«t e fundit doli njĂ« moment jo shumĂ« i kĂ«ndshĂ«m — nĂ« qendĂ«r tĂ« rrjetit dhe ne kemi njĂ« Brocade RX8 dhe ai ka filluar tĂ« dĂ«rgojĂ« shumĂ« paketa unknown-unicast, pasi rrjeti Ă«shtĂ« i ndarĂ« nĂ« VLAN-e - kĂ«shtu qĂ« pjesĂ«risht kjo nuk Ă«shtĂ« problem, POR ka VLAN-e speciale pĂ«r adresat e bardha etj. dhe ato janĂ« tĂ« shtrira nĂ« tĂ« gjitha anĂ«t e rrjetit. Tani pĂ«rfshihni fluksin e hyrĂ«s nĂ« adresĂ«n e klientit, e cila nuk mĂ«sohet nga bordi dhe ky fluks shkon nĂ« drejtim tĂ« lidhjes radio nĂ« njĂ« (apo tĂ« gjithĂ«) fshat — kanali Ă«shtĂ« i mbushur — klientĂ«t janĂ« tĂ« zinj — trishtim


Detyra — ta kthejmĂ« defektin nĂ« veçori. Mendoja pĂ«r q-in-q me njĂ« VLAN klienti tĂ« plotĂ«, por tĂ« gjitha copa si P3310, kur aktivizojnĂ« dot1q, ndalojnĂ« tĂ« kalojnĂ« DHCP, gjithashtu ata nuk e dinĂ« qinq selektiv dhe shumĂ« nga kĂ«to ngĂ«rçet nĂ« kĂ«tĂ« drejtim. ÇfarĂ« Ă«shtĂ« ip-unnambered dhe si funksionon? NĂ«se jemi shumĂ« tĂ« pĂ«rciptĂ« — adresa e portĂ«s + rrugĂ« nĂ« ndĂ«rfaqe. PĂ«r detyrĂ«n tonĂ« na nevojitet: tĂ« presim shaper-in, t'u japim adresa klientĂ«ve, tĂ« shtojmĂ« rrugĂ« pĂ«r klientĂ«t pĂ«rmes ndĂ«rfaqeve tĂ« caktuara. Me çfarĂ« do ta bĂ«jmĂ« kĂ«tĂ«? Shaper — lisg, dhcp — db2dhcp nĂ« dy servers tĂ« pavarur, nĂ« serverĂ«t e aksesit funksionon dhcprelay, gjithashtu nĂ« serverĂ«t e aksesit punon ucarp — pĂ«r backup. Si do tĂ« shtojmĂ« rrugĂ«t? Mund ta shtojmĂ« tĂ« gjitha me njĂ« skript tĂ« madh paraprakisht — por kjo nuk Ă«shtĂ« e vĂ«rtetĂ«. KĂ«shtu qĂ« do tĂ« krijojmĂ« njĂ« qerthull tĂ« vetĂ«shkruar.

Pas njĂ« kĂ«rkimi tĂ« thellĂ« nĂ« internet, gjetĂ«m njĂ« bibliotekĂ« tĂ« shkĂ«lqyer tĂ« nivelit tĂ« lartĂ« pĂ«r c++, e cila lejon snifimin e trafikut nĂ« mĂ«nyrĂ« tĂ« bukur. Algoritmi i funksionit tĂ« programit qĂ« shton rrugĂ« Ă«shtĂ« si mĂ« poshtĂ« — dĂ«gjojmĂ« kĂ«rkesat ARP nĂ« ndĂ«rfaqe, nĂ«se ne kemi njĂ« adresĂ« nĂ« serverin tonĂ« nĂ« ndĂ«rfaqen lo qĂ« kĂ«rkohet, atĂ«herĂ« ne shtojmĂ« njĂ« rrugĂ« pĂ«rmes kĂ«saj ndĂ«rfaqe dhe shtojmĂ« njĂ« regjistrim statik ARP pĂ«r kĂ«tĂ« ip — nĂ« pĂ«rgjithĂ«si disa kopipasta, pak nga ideja ime dhe e gatshme.

Burimet e 'rrugëzuesit'

#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;
    }
}

Skripti i instalimit libtins

#!/bin/bash

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

Komanda për ndërtimin e binarit

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

Si ta nisim atë?


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

Po — ai se i ristrukturon tabelat me sinjalin HUP. Pse nuk pĂ«rdorej netlink? Thjesht nuk mĂ« pĂ«lqen dhe linux-i Ă«shtĂ« njĂ« skenar mbi skenar — kĂ«shtu qĂ« gjithçka Ă«shtĂ« nĂ« rregull. Tani, pĂ«rsa i pĂ«rket rrugĂ«ve, çfarĂ« mĂ« pas? MĂ« pas na duhet tĂ« dĂ«rgojmĂ« nĂ« kufirin rrugĂ«t qĂ« ekzistojnĂ« nĂ« kĂ«tĂ« server — kĂ«tu, pĂ«r shkak tĂ« atij hardueri tĂ« vjetruar, ne shkuam me rrugĂ«n e rezistencĂ«s mĂ« tĂ« vogĂ«l — e vendosĂ«m kĂ«tĂ« detyrĂ« nĂ« BGP.

Konfiguro bgpemri-pajisjes *******
fjalëkalimi *******
skeda e regjistrimit /var/log/bgp.log
!
# ĐœĐŸĐŒĐ”Ń€ ас-ĐșĐž, аЎрДса Đž сДтО ĐČŃ‹ĐŽŃƒĐŒĐ°ĐœŃ‹
router bgp 12345
bgp router-id 1.2.3.4
redistribute connected
redistribute static
neighbor 1.2.3.1 remote-as 12345
neighbor 1.2.3.1 next-hop-self
neighbor 1.2.3.1 route-map none in
neighbor 1.2.3.1 route-map export out
!
access-list export lejo 1.2.3.0/24
!
route-map export lejo 10
match ip address export
!
route-map export ndalo 20

Vazhdojmë. Për të bërë që serveri të përgjigjet në kërkesat ARP, duhet të aktivizojmë proxy ARP.


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

TĂ« shkojmĂ« pĂ«rpara — ucarp. Skripthet e nisjes pĂ«r kĂ«tĂ« mrekulli i shkruajmĂ« vetĂ«.

Shembulli i nisjes së një demonësh


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

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

PĂ«r tĂ« punuar dhcprelay nĂ« ndĂ«rfaqe — i nevojitet njĂ« adresĂ«. Prandaj, nĂ« ndĂ«rfaqet qĂ« pĂ«rdorim do tĂ« shtojmĂ« adresa tĂ« rreme — pĂ«r shembull 10.255.255.1/32, 10.255.255.2/32 etj. Si ta konfigurojmĂ« rrelen nuk do ta tregoj — aty Ă«shtĂ« gjithçka e thjeshtĂ«.

Pra, çfarĂ« kemi. Backup tĂ« portave, konfigurim automatik tĂ« rrugĂ«ve, dhcp. Ky Ă«shtĂ« njĂ« grup minimal — pĂ«rveç kĂ«saj, e gjitha bĂ«het me lisg dhe ne tashmĂ« kemi edhe shaperin. Pse gjithĂ« kjo Ă«shtĂ« kaq e gjatĂ« dhe e komplikuar? A nuk Ă«shtĂ« mĂ« e lehtĂ« tĂ« marrim accel-pppd dhe thjesht tĂ« pĂ«rdorim pppoe? Jo, nuk Ă«shtĂ« mĂ« e lehtĂ« — njerĂ«zit me vĂ«shtirĂ«si mund tĂ« hyjnĂ« nĂ« router, pa folur mĂ« pĂ«r pppoe. accel-ppp Ă«shtĂ« njĂ« gjĂ« e shkĂ«lqyer — por nuk na u lejua — shumĂ« gabime nĂ« kod — shembull dhe prerĂ« keq, dhe ajo qĂ« Ă«shtĂ« mĂ« e keqe Ă«shtĂ« se nĂ«se ai shkatĂ«rrohet — atĂ«herĂ« njerĂ«zit duhet tĂ« rifillojnĂ« gjithçka — telefonat janĂ« tĂ« kuq — nĂ« pĂ«rgjithĂ«si nuk na pĂ«rkasĂ«. ÇfarĂ« Ă«shtĂ« pĂ«rfitimi i pĂ«rdorimit tĂ« ucarp nĂ« vend tĂ« keepalived? Po nĂ« gjithçka — ka 100 porta, keepalived dhe njĂ« gabim nĂ« konfigurim — gjithçka nuk funksionon. Me ucarp nuk punon 1 portĂ«. PĂ«rsa i pĂ«rket sigurisĂ«, qĂ« njerĂ«zit tĂ« shkruajnĂ« adresa tĂ« rreme dhe tĂ« pĂ«rdorin nĂ« grup — pĂ«r kontrollimin e kĂ«saj çështjeje nĂ« tĂ« gjitha switch/olt/bazat konfiguroni dhcp-snooping + source-guard + arp inspection. NĂ«se klienti nuk ka dhcp por statikĂ« — acces-list nĂ« port.

Pse bĂ«hej tĂ«rĂ« kjo? PĂ«r tĂ« shkatĂ«rruar trafikun qĂ« nuk na pĂ«lqen. Tani çdo switch ka VLAN-in e tij dhe unknown-unicast nuk Ă«shtĂ« mĂ« njĂ« shqetĂ«sim, pasi tani Ă«shtĂ« vetĂ«m njĂ« port ku kalon e jo tĂ« gjithë  Po ashtu, efektet anĂ«sore — konfigurim standard tĂ« pajisjeve, efikasitet mĂ« i madh nĂ« shpĂ«rndarjen e hapĂ«sirĂ«s adresuese.

Si tĂ« konfigurosh lisg — Ă«shtĂ« njĂ« temĂ« e veçantĂ«. Lidhjet me bibliotekat janĂ« tĂ« bashkangjitura. Ndoshta ndihmon atij qĂ« ka nevojĂ« pĂ«r informacionin e paraqitur mĂ« lart pĂ«r realizimin e detyrave tĂ« tij. Versionin 6 nuk e kemi implementuar ende nĂ« rrjet — por aty do tĂ« kemi njĂ« problem — nĂ« planet Ă«shtĂ« tĂ« riprogramojmĂ« lisg pĂ«r versionin 6 dhe gjithashtu do tĂ« duhet tĂ« modifikojmĂ« programin qĂ« shton rrugĂ«t.

Linux ISG
DB2DHCP
Libtins

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster