Pozdravljeni. Torej, imamo omrežje s 5 odjemalci. Pred kratkim smo naleteli na precej neprijetno situacijo: v središču omrežja imamo Brocade RX8, ki je začel pošiljati veliko neznanih unicast paketov. Ker je omrežje razdeljeno na VLAN-e, to ni problem, vendar obstajajo posebni VLAN-i za bele naslove itd., ki se raztezajo čez celotno omrežje. Predstavljajte si torej dohodni promet na naslov odjemalca, ki ga ne usposablja protokol Border, in ta promet se pošlje na radijsko povezavo do nekaterih (ali vseh) vasi. Kanal je zamašen, odjemalci so jezni in to je žalostno ...
Cilj je, da se hrošč spremeni v funkcijo. Razmišljal sem o Q-in-Q s polnopravnim VLAN odjemalcem, vendar strojna oprema, kot je P3310, preneha prenašati DHCP, ko je omogočen dot1q. Prav tako ne podpirajo selektivnega Q-in-Q in obstaja veliko drugih pasti v tej smeri. Kaj je ip-unnamed in kako deluje? Skratka, to je naslov prehoda + pot na vmesniku. Za našo nalogo moramo izrezati oblikovalce, distribuirati naslove odjemalcem in dodati poti odjemalcem prek določenih vmesnikov. Kako vse to naredimo? Oblikovalec je lisg, dhcp je db2dhcp na dveh neodvisnih strežnikih, dhcprelay teče na dostopnih strežnikih, ucarp pa teče tudi na dostopnih strežnikih za varnostno kopiranje. Kako pa dodamo poti? Vse bi lahko dodali vnaprej z veliko skripto, vendar to ni res. Zato bomo morali zgraditi domač hekerski program.
Po obsežnem iskanju po internetu sem našel čudovito visokonivojsko knjižnico za C++, ki omogoča elegantno vohanje prometa. Program za dodajanje poti deluje takole: posluša ARP zahteve na vmesniku. Če ima strežnik na LO vmesniku naslov, ki se zahteva, dodamo pot skozi ta vmesnik in dodamo statični ARP vnos za ta IP naslov. V bistvu nekaj kopiranja, malo popravljanja in končali ste.
Izvorna koda za 'marshrutchik'
#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;
}
}namestitveni skript libtins
#!/bin/bash
git clone https://github.com/mfontanini/libtins.git
cd libtins
mkdir build
cd build
cmake ../
make
make install
ldconfig
Ukaz za gradnjo binarne datoteke
g++ main.cpp -o arp-rt -O3 -std=c++11 -lpthread -ltinsKako ga zagnati?
start-stop-daemon --start --exec /opt/ipoe/arp-routes/arp-rt -b -m -p /opt/ipoe/arp-routes/daemons/eth0.800.pid -- eth0.800
Ja, obnovi tabele na podlagi HUP signala. Zakaj nisi uporabil NetLinka? Sem pač len, Linux pa je skripta znotraj skripte, zato je vse v redu. Torej, poti so poti, kaj sledi? Nato moramo poslati poti, ki obstajajo na tem strežniku, na mejo. Tukaj smo zaradi iste zastarele strojne opreme ubrali pot najmanjšega upora in to nalogo prepustili BGP-ju.
Konfiguracija BGP-jaime gostitelja *******
geslo *******
dnevniška datoteka /var/log/bgp.log
!
# Številka ICQ, naslovi in omrežja so izmišljeni.
usmerjevalnik bgp 12345
ID usmerjevalnika bgp 1.2.3.4
prerazporediti povezane
prerazporedi statiko
sosed 1.2.3.1 oddaljeni kot 12345
sosed 1.2.3.1 naslednji-skok-sebe
sosed 1.2.3.1 zemljevid poti ni v
izvoz zemljevida poti sosed 1.2.3.1
!
dovoljenje za izvoz dostopnega seznama 1.2.3.0/24
!
dovoljenje za izvoz poti in zemljevida 10
izvoz ujemajočega se IP-naslova
!
izvoz zemljevida poti zavrni 20
Nadaljujmo. Da bi strežnik lahko odgovoril na zahteve ARP, morate omogočiti proxy ARP.
echo 1 > /proc/sys/net/ipv4/conf/eth0.800/proxy_arp
Pa nadaljujmo z ucarpom. Sami bomo napisali skripte za zagon tega čudeža.
Primer zagona enega demona
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"
gor.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
dol.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
Da bi dhcprelay deloval na vmesniku, potrebuje naslov. Zato bomo na vmesnikih, ki jih uporabljamo, dodali poljubne naslove – na primer 10.255.255.1/32, 10.255.255.2/32 itd. Ne bom razlagal, kako konfigurirati rele – vse je preprosto.
Torej, kaj imamo? Varnostno kopiranje prehoda, samodejno konfiguracijo poti, DHCP. To je najnujnejše – poleg tega je dodan tudi lisg in že imamo oblikovalnik. Zakaj je vse tako dolgo in zapleteno? Ali ne bi bilo lažje uporabiti samo accel-pppd in samo PPPOE? Ne, ni lažje – ljudje komaj vtaknejo niti povezovalni kabel v usmerjevalnik, kaj šele PPPOE. accel-ppp je kul, vendar nam ni deloval – v kodi je ogromno napak – sesuje se, slabo konfigurira in najhuje je, da morajo ljudje, če sesuje, vse znova zagnati – telefoni so rdeči – preprosto ni delovalo. Kakšna je prednost uporabe ucarp pred keepalived? Je vse – obstaja 100 prehodov, keepalived in ena napaka v konfiguraciji – nič ne deluje. Z ucarp ne deluje samo en prehod. Kar zadeva varnost, bi lahko registrirali lažne naslove in jih uporabili na Shariki. Za nadzor nad tem konfiguriramo dhcp-snooping + source-guard + arp inspection na vseh stikalih/OLT-jih/bazah podatkov. Če odjemalec nima dhpc-ja, temveč statične IP-naslove, uporabimo access-list na vratih.
Zakaj je bilo vse to storjeno? Da bi odpravili neželeni promet. Zdaj ima vsako stikalo svoj VLAN in neznano unicast ni več problem, saj mora dostopati le do enih vrat namesto do vseh ... Stranski učinki pa vključujejo standardizirano konfiguracijo strojne opreme in večjo učinkovitost pri porazdelitvi naslovnega prostora.
Konfiguriranje lisg je ločena tema. Vključene so povezave do knjižnic. Morda bo zgornje komu v pomoč pri njegovih lastnih potrebah. Različica 6 še ni implementirana v našem omrežju, vendar bo prišlo do težave – načrtujemo prepis lisg za različico 6 in prilagoditi bomo morali program, ki dodaja poti.
Vir: www.habr.com
