Tere. Oleme vĂ”rgu 5k kliendiga. Hiljuti ilmus ebasoodne hetk â meie vĂ”rgu keskuses on Brocade RX8 ja see hakkas saatma palju unknown-unicast pakette, kuna vĂ”rk on jagatud VLAN-ideks â see ei ole osaliselt probleem, kuid on spetsiaalsed VLAN-id valgete aadresside jaoks jne, ja need on laiali ĂŒle kogu vĂ”rgu. Kujutage nĂŒĂŒd ette sissetulevat liiklust kliendi aadressile, mida piiraja ei Ă”pi, ja see liiklus suundub mingi (ja seetĂ”ttu kĂ”ikide) kĂŒlasse â kanal on ummistunud â kliendid on pahased â kurb...
Ălesanne â muuta viga omaduseks. MĂ”tlesin q-in-q suunal, kus oleks tĂ€ielik kliendi-VLAN, kuid igasugused seadmed nagu P3310 lakkavad dot1q sisse lĂŒlitamisel DHCP-d edastamast, nad ei oska ka selective qinq ja palju allpoolse tiibadega vahepealseid lahendusi. Mis on ip-unumbered ja kuidas see töötab? Kui vĂ€ga lĂŒhidalt â saadetava vĂ€rava aadress + marsruut liidese peal. Meie ĂŒlesande jaoks on vajalik: kĂ€rpida ĆĄeiperi, jagada aadresse klientidele, lisada marsruute klientidele lĂ€bi teatud liideste. Mida kĂ”ik sellega teha? Ć eiper â lisg, dhcp â db2dhcp kahel sĂ”ltumatul serveril, juurdepÀÀsuserverites töötab dhcprelay, samuti töötab juurdepÀÀsuserverites ucarp â varukoopiaks. Aga kuidas marsruute lisada? Suure skriptiga saab kĂ”ik ette Ă€ra lisada â aga see ei ole tĂ”ene. Seega hakkame ise lahendama.
PĂ”hjalikult internetis uurides leidsin suurepĂ€rase kĂ”rgema taseme raamatukogu c++ jaoks, mis vĂ”imaldab ilusasti liiklust nuuskida. Programm, mis marsruute lisab, töötab jĂ€rgmiselt: kuulame liidese peal arp pĂ€ringuid, kui meil on serveris aadress liidese lo peal, mida kĂŒsitakse, siis lisame marsruudi selle liidese kaudu ja lisame selle ip kohta staatilise arp kirje â ĂŒldiselt paar copy-paste, natuke oma mĂ”tteid ja asi valmis.
Marsuuri 'marsruutija' lÀhtekoodid
#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 installimise skript
#!/bin/bash
git clone https://github.com/mfontanini/libtins.git
cd libtins
mkdir build
cd build
cmake ../
make
make install
ldconfig
KĂ€sk binaari kompileerimiseks
g++ main.cpp -o arp-rt -O3 -std=c++11 -lpthread -ltinsKuidas seda kÀivitada?
start-stop-daemon --start --exec /opt/ipoe/arp-routes/arp-rt -b -m -p /opt/ipoe/arp-routes/daemons/eth0.800.pid -- eth0.800
Jah â ta konfigureerib HUP signaaliga tabelid. Miks ei kasutanud netlinki? Lihtsalt laiskus ja Linux on script kĂ”ige peal â nii et kĂ”ik on normaalne. Noh, marsruudid on marsruutideks, mis edasi? Edasi peame saatma piiril marsruudid, mis on sellel serveril â siin, arvestades samu vanu riistu, lĂ€ksime lihtsamat teed â panime selle ĂŒlesande BGP-le.
bgp konfihostname *******
password *******
log file /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 permit 1.2.3.0/24
!
route-map export permit 10
match ip address export
!
route-map export deny 20
JĂ€tkame. Selleks, et server vastaks ARP pĂ€ringutele, tuleb sisse lĂŒlitada proxy ARP.
echo 1 > /proc/sys/net/ipv4/conf/eth0.800/proxy_arp
Edasi â ucarp. Kirjutame ise selle imelise skripti kĂ€ivitamiseks skriptid
NĂ€ide ĂŒhe daemon'i kĂ€ivitamisest
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
Kuna dhcprelay töötab liideses â tal on vajalik aadress. SeetĂ”ttu lisame liidestele, mida kasutame, valeadresse â nĂ€iteks 10.255.255.1/32, 10.255.255.2/32 jne. Kuidas seadistada releed, ei hakka rÀÀkima â seal on kĂ”ik lihtne.
Nii, mida me omame. Kaitse vĂ€ravatele, automaatne marsruutide seadistamine, dhcp. See on minimaalne komplekt â erinevalt sellest lisame lisaks lisg'i ning meil on juba olemas ka shaper. Miks kĂ”ik on nii pikk ja keeruline? Kas poleks lihtsam vĂ”tta accel-pppd ja kasutada ĂŒldse pppoe? Ei, see pole lihtsam â inimesed ei suuda isegi patche kasti ruuterisse suruda, rÀÀkimata pppoe'st. accel-ppp on Ă€ge asi â aga meie jaoks ei sobinud â palju vigu koodis â kukuvad kokku, lĂ”ikavad valesti, ja kĂ”ige kurvem on see, et kui see kokku kukub â peavad inimesed kĂ”ik uuesti kĂ€ivitama â telefonid punased â igal juhul ei sobinud. Miks valida ucarp mitte keepalived? Jah, kĂ”iges â on 100 vĂ€ravat, keepalived ja ĂŒks viga konfis â kĂ”ik ei tööta. Ucarp-nĂ€idikuga ei tööta 1 vĂ€rav. Mis puudutab turvalisust, et nad kirjutavad endale vale aadresse ja kasutavad neid â selle kontrollimiseks seadistame kĂ”igis switchides / oltdes / andmebaasides dhcp-snooping + source-guard + arp inspection. Kui kliendil pole dhcp-d, vaid staatika â access-list sadamates.
Miks see kĂ”ik tehti? Ebaausate liiklusvoogude hĂ€vitamiseks. NĂŒĂŒd on igal lĂŒlitil oma VLAN ja unknown-unicast ei ole enam hirmutav, kuna see peab minema ainult ĂŒhte porti, mitte kĂ”ikidesse⊠Veelgi enam, kĂ”rvalmĂ”jud â standardiseeritud seadme konfiguratsioon, suurem aadressiruumi jaotamise tĂ”husus.
Kuidas konfigureerida lisg â see on eraldi teema. Raamatukogude lingid on lisatud. VĂ”ib-olla aitab see kellelegi ĂŒlesannete lahendamisel. Versioon 6 ei ole meil veel vĂ”rgus rakendatud â kuid seal on probleem â plaanis on kirjutada lisg versioon 6 jaoks ĂŒmber ning tuleb ka programmi, mis marsruute lisab, veidi kohendada.
Allikas: habr.com
