Halo. Janten, urang gaduh jaringan 5 klien. Nembe waé, urang mendakan kaayaan anu rada teu pikaresepeun: urang gaduh Brocade RX8 di tengah jaringan, sareng éta mimiti ngirim seueur pakét unicast anu teu dikenal. Kusabab jaringan dibagi kana VLAN, ieu sanés masalah, tapi aya VLAN khusus pikeun alamat bodas, jsb., sareng éta manjang ka sakumna jaringan. Janten, bayangkeun lalu lintas anu lebet ka alamat klien anu henteu dilatih ku protokol wates, sareng lalu lintas ieu dikirim ka tautan radio ka sababaraha (atanapi sadaya) désa. Saluranna macét, klien ambek, sareng éta sedih...
Tujuanana nyaéta pikeun ngarobah bug jadi fitur. Abdi keur mikirkeun Q-in-Q nganggo klien VLAN anu lengkep, tapi perangkat keras sapertos P3310 lirén ngirimkeun DHCP nalika dot1q diaktipkeun. Éta ogé henteu ngadukung Q-in-Q selektif, sareng aya seueur jebakan sanés sapertos kitu. Naon ari ip-unnamed sareng kumaha cara kerjana? Singkatna, éta alamat gateway + rute dina antarmuka. Pikeun tugas urang, urang kedah motong shaper, nyebarkeun alamat ka klien, sareng nambihan rute ka klien ngalangkungan antarmuka khusus. Kumaha urang ngalakukeun sadayana ieu? Shaper nyaéta lisg, dhcp nyaéta db2dhcp dina dua server mandiri, dhcprelay dijalankeun dina server aksés, sareng ucarp ogé dijalankeun dina server aksés pikeun cadangan. Tapi kumaha urang nambihan rute? Urang tiasa nambihan sadayana sateuacanna nganggo skrip ageung, tapi éta henteu leres. Janten urang kedah ngawangun hack buatan bumi.
Saatos sababaraha panéangan internét anu éksténsif, kuring mendakan pustaka tingkat luhur anu saé pikeun C++ anu ngamungkinkeun pikeun ngintip lalu lintas anu elegan. Program panambahan rute jalanna sapertos kieu: déngékeun pamundut ARP dina antarmuka. Upami server gaduh alamat dina antarmuka LO anu dipénta, urang nambihan rute ngalangkungan antarmuka éta sareng nambihan éntri ARP statis pikeun alamat IP éta. Intina mah, sababaraha copy-pasta, sakedik ngotak-atik, sareng anjeun parantos réngsé.
Kode sumber pikeun '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;
}
}skrip pamasangan libtins
#!/bin/bash
git clone https://github.com/mfontanini/libtins.git
cd libtins
mkdir build
cd build
cmake ../
make
make install
ldconfig
Paréntah pikeun ngawangun binér
g++ main.cpp -o arp-rt -O3 -std=c++11 -lpthread -ltinsKumaha cara ngaluncurkeunana?
start-stop-daemon --start --exec /opt/ipoe/arp-routes/arp-rt -b -m -p /opt/ipoe/arp-routes/daemons/eth0.800.pid -- eth0.800
Muhun, éta ngawangun deui tabel dina sinyal HUP. Naha anjeun henteu nganggo NetLink? Abdi ngan saukur males, sareng Linux mangrupikeun skrip dina skrip, janten sadayana saé. Janten, rute tetep rute, kumaha salajengna? Salajengna, urang kedah ngirim rute anu aya dina server ieu ka wates. Di dieu, kusabab perangkat keras anu sami sareng lami, urang nyandak jalur anu paling gampang sareng masrahkeun tugas ieu ka BGP.
Konfigurasi BGPngaran host *******
kecap akses *******
file log /var/log/bgp.log
!
# Nomer ICQ, alamat, sareng jaringan éta ngan ukur fiktif.
router bgp 12345
id router bgp 1.2.3.4
nyebarkeun deui anu nyambung
nyebarkeun deui statis
tatangga 1.2.3.1 jauh-sakumaha 12345
tatangga 1.2.3.1 salajengna-luncat-diri
peta rute tatangga 1.2.3.1 teu aya di jerona
ékspor peta rute tatangga 1.2.3.1 kaluar
!
idin ékspor daptar aksés 1.2.3.0/24
!
idin ékspor peta rute 10
cocogkeun ékspor alamat IP
!
ékspor peta rute nolak 20
Hayu urang teraskeun. Supados server tiasa ngaréspon pamundut ARP, anjeun kedah ngaktipkeun proxy ARP.
echo 1 > /proc/sys/net/ipv4/conf/eth0.800/proxy_arp
Hayu urang teraskeun ka ucapan. Urang bakal nyerat skrip peluncuran pikeun mujijat ieu nyalira.
Conto ngajalankeun hiji 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"
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
Supados dhcprelay tiasa dianggo dina hiji antarmuka, éta peryogi alamat. Ku kituna, dina antarmuka anu urang anggo, urang bakal nambihan alamat anu teu tangtu—contona, 10.255.255.1/32, 10.255.255.2/32, jsb. Abdi moal ngajelaskeun kumaha ngonpigurasikeun relay—sadayana saderhana.
Janten, naon anu urang gaduh? Cadangan gateway, konfigurasi rute otomatis, DHCP. Éta minimumna—lisg ogé ditambahkeun di luhurna, sareng urang parantos gaduh shaper. Naha sadayana panjang sareng rumit? Naha moal langkung gampang nganggo accel-pppd sareng ngan ukur nganggo PPPOE? Henteu, éta henteu langkung gampang—jalma-jalma ampir teu tiasa ngalebetkeun patchcord kana router, apalagi PPPOE. accel-ppp keren, tapi éta henteu tiasa dianggo pikeun urang—aya seueur kasalahan dina kode—éta nabrak, konfigurasina goréng, sareng anu paling parah nyaéta upami nabrak, jalma kedah ngabalikan deui sadayana—telepon beureum—éta henteu tiasa dianggo. Naon kaunggulan nganggo ucarp tibatan keepalived? Éta sadayana—aya 100 gateway, keepalived, sareng hiji kasalahan dina konfigurasi—sadayana henteu tiasa dianggo. Sareng ucarp, ngan hiji gateway anu henteu tiasa dianggo. Ngeunaan kaamanan, aranjeunna tiasa ngadaptarkeun alamat palsu sareng nganggo éta dina Sharika. Pikeun ngontrol ieu, urang ngonpigurasikeun dhcp-snooping + source-guard + arp inspection dina sadaya switch/OLT/database. Upami klien henteu gaduh alamat IP dhpc tapi statis, anggo access-list dina port.
Naha ieu sadayana dilakukeun? Pikeun ngaleungitkeun lalu lintas anu teu dihoyongkeun. Ayeuna unggal switch gaduh VLAN nyalira, sareng unicast anu teu dikenal sanés masalah deui, kumargi ngan ukur kedah ngaksés hiji port tinimbang sadayana... Sareng efek sampingna kalebet konfigurasi perangkat keras standar sareng efisiensi anu langkung ageung dina distribusi rohangan alamat.
Ngonpigurasikeun lisg mangrupikeun topik anu misah. Tautan ka perpustakaan kalebet. Panginten anu di luhur bakal ngabantosan batur pikeun kabutuhanana nyalira. Versi 6 tacan diimplementasikeun dina jaringan kami, tapi bakal aya masalah — kami ngarencanakeun pikeun nyerat ulang lisg pikeun versi 6, sareng kami kedah nyaluyukeun program anu nambihan rute.
sumber: www.habr.com
