Introduction
L'idée de ce projet vient du fait que mon Assciation Héberge
un mirroir officiel des signatures de Clamav (http://clamav.kazar.net/),
ce qui engendre des consommations réseau astronomiques.
Ayant mon AS, quelques full-view BGP et aussi... un point de peering
avec le Panap (en autres), j'ai eu l'idée de faire du shapping
intelligent afin de ne pas pénaliser les peering locaux et limiter
les dégats en terme de facture pour le transit internationnal.
Logiciels nécessaires et utilisés
Un OS supportant :
- OpenBSD PF
- Altq intégré dans PF
- OpenBSD OpenBGPd : Dans ce cas il y a soit OpenBSD, soit FreeBSD 6.1+ (6.2 conseillé, le
support de ALTQ avec PF n'existe pas sur FreeBSD 5.x).
Il vous faut aussi :
- PF
- OpenBGPd
et le plus important
- Un routeur faisant du BGP avec les bonnes routes qui sont a locales
(eg celles qui viennent d'un peering local). Ce routeur peut être
software ou hardware, le principal c'est qu'il fasse du BGP.
Ne pas oublier aussi de savoir quel type de traffic vous allez
shapper et limiter ... Ici ca sera du http sur une ip précise.
Préparation de PF
Configurez votre firewall PF comme d'usage, par exemple ma conf est :
ext_if="fxp1" # Interface externe avec les ip publiques (jails, etc...)
# Cette interface a plusieurs IP : xxx.xxx.xxx.150 (main,
# xxx.xxx.xxx.9 (mirroir clamav a shapper)
int_if="fxp0" # Interface interne
# Table des ip d'admin de clamav
table <sshclamav> { 10.0.1.1, 192.168.0.0/27 }
# Table des IP prioritaires qui seront écrasées par openbgpd
table <bgp> { 172.31.0.0/24, 10.0.1.1 }
# Options: tune the behavior of pf, default values are given.
set timeout { interval 10, frag 30 }
set timeout { tcp.first 120, tcp.opening 30, tcp.established 86400 }
set timeout { tcp.closing 900, tcp.finwait 45, tcp.closed 90 }
set timeout { udp.first 60, udp.single 30, udp.multiple 60 }
set timeout { icmp.first 20, icmp.error 10 }
set timeout { other.first 60, other.single 30, other.multiple 60 }
set timeout { adaptive.start 0, adaptive.end 0 }
set limit { states 10000, frags 5000 }
set loginterface fxp1
set optimization normal
set block-policy drop
set require-order yes
set fingerprints "/etc/pf.os"
set skip on fxp0
set skip on lo0
# Normalization: reassemble fragments and resolve or reduce traffic
ambiguities.
scrub in all
## QUEUES - ALTQ rules
## J'ai que 100Mbps...
altq on $ext_if cbq bandwidth 100Mb queue { q_def, q_pri, q_misc, q_web, q_dns, q_smtp }
queue q_def bandwidth 25Mb priority 1 cbq(borrow default red ecn)
queue q_misc bandwidth 5Mb priority 0 cbq(red ecn)
queue q_web bandwidth 40Mb priority 4 cbq(borrow)
queue q_dns bandwidth 3Mb priority 5 cbq(borrow)
queue q_smtp bandwidth 2Mb priority 6 cbq(borrow)
queue q_pri bandwidth 25Mb priority 7 cbq(borrow)
# Filtering: the implicit first two rules are
pass in all
pass out all
# block all incoming packets but allow ssh, pass all outgoing tcp and
udp
# connections and keep state, logging blocked packets.
block in log on $ext_if all
# SSH admin de la babasse
pass in on $ext_if proto tcp from any to $ext_if port 2202 keep
state queue q_pri
# SMTP
pass in on $ext_if proto tcp from any to $ext_if port 25 keep state
queue q_smtp
# LDAP Services
pass in on $ext_if proto tcp from 172.31.0.0/27 to $ext_if port 389
keep state queue q_pri
# MySQL Services
pass in on $ext_if proto tcp from 172.31.0.0/27 to $ext_if port 3306 keep state queue q_pri
# DNS cache
pass in on $ext_if proto { tcp, udp } from any to xxx.xxx.xxx.160 port 53 keep state queue q_dns
# ICEcast
pass in on $ext_if proto tcp from any to xxx.xxx.xxx.150 port 80 keep state queue q_web
pass in on $ext_if proto tcp from any to xxx.xxx.xxx.150 port 8000 keep state queue q_web
pass out on $ext_if proto tcp from xxx.xxx.xxx.150 port 80 to any keep state queue q_web
# ping
pass in on $ext_if proto icmp from any to $ext_if
# SSH pour clamav (prioritaire et pas shappé)
pass in on $ext_if proto tcp from <sshclamav> to xxx.xxx.xxx.9 port 22 keep state queue q_pri
# Queue mirroir Clamav
# On passe en "quick" ce qui est prioritaire
pass in quick on $ext_if proto tcp from <bgp> to xxx.xxx.xxx.9 port 80 keep state queue q_web
pass out quick on $ext_if proto tcp from xxx.xxx.xxx.9 port 80 to <bgp> keep state queue q_web
# Et le reste est dans la bonne queue qui va bien :p
pass in on $ext_if proto tcp from any to xxx.xxx.xxx.9 port 80 keep state queue q_misc
pass out on $ext_if proto tcp from xxx.xxx.xxx.9 port 80 to any keep state queue q_misc
# Last rule
pass out on $ext_if proto { tcp, udp, icmp } all keep state
Préparation de openbgpd
La conf est assez simple :
AS 65530
holdtime 180
holdtime min 3
fib-update no
listen on xxx.xxx.xxx.150
neighbor xxx.xxx.xxx.xxx {
descr "routeurs"
announce none
remote-as 35189
}
# Ne pas accepter une route par défaut sinon le shapping sert a rien
deny quick from any prefix 0.0.0.0/0
# Garder que des subnet propres... par > 24.
# le routeur "routeurs" devra évidement annoncer les ip locales... sinon
# le shapping sera valable pour vous aussi.
allow from any prefixlen 8 - 24
# On balance vers PF
allow from any set pftable "bgp"
Lancement du bordel
D'abord lancer PF (attention au shoot in the foot), et voir que le
service tourne...
Un pfctl -t bgp -T show permettra de voir les bonnes ips que vous
avez mis par défaut.
Après un lancement de openbgpd (/usr/local/etc/rc.d/openbgpd start)
permettra de voir
si vous avez monté la session bgp correctement ou pas...
# bgpctl s
Neighbor AS MsgRcvd MsgSent OutQ Up/Down State/PrefixRcvd
routeurs 35189 15666 9783 0 6d19h02m 1514
Pour voir les routes annoncées a notre altq :
# bgpctl sh ip bgp
flags: * = Valid, > = Selected, I = via IBGP, A = Announced
origin: i = IGP, e = EGP, ? = Incomplete
flags destination gateway lpref med aspath origin
*> 62.4.16.0/21 xxx.xxx.xxx.xxx 100 0 35189 13193 i
*> 62.8.0.0/19 xxx.xxx.xxx.xxx 100 0 35189 15557 3305 3305 i
....
permet de donner un exemple concret de routes whitelistées

Après un pfctl -t bgp -T show doit vous donner la même chose...
Comment tester ?
Simple : balancer du traffic.
Problèmes connus :
Un /etc/rc.d/pfctl reload; vide la table bgp. Un bgpctl nei routeurs
clear la recharge
En production...
Et bien ça fait 3 mois que je gère le mirroir de clamav avec cette
méthode, ce m'as
permis de calmer la facture de transit tout en permettant un traffic
soutenus lors que
l'équipe de clamav mets a jours ses signature et génére beaucoup de
traffic.
Exemple la dernière mise a jour de main.cvd a généré sur cette
machine plus 70Mbps de traffic
en continu pendant 5 à 6 heures, avec moins de 5% CPU système utilisé sur
PIII 1GHz avec 512Mo de RAM
et plus de 1000 / 2000 FD connectés en moyenne.... Le serveur web est
un thttpd ....
OpenBGP ne consomme pas trop de mémoire (moins de 128Mo suffisent
pour les 200K routes actuelles) :
# bgpctl show rib memory
RDE memory statistics
1515 IPv4 network entries using 48480B of memory
3029 prefix entries using 96928B of memory
2054 BGP path attribute entries using 156104B of memory
471 BGP AS-PATH attribute entries using 13523B of memory,
and holding 2054 references
37 BGP attributes entries using 888B of memory
and holding 277 references
36 BGP attributes using 216B of memory
RIB using 316139B of memory
J'utilise aussi cette méthode pour shapper la bande passante du
mirroir ftp.oav.net
Avec un peu de pfstat on peut voir les utilisations de différentes queues :


Contrib
Pour les patches, les erreurs de frappes, et du peering pour Kazar,
écrivez moi sur les commentaires
License
Ce document est sous double license : GPL et Offrez moi un biere(tm)