Sysctl est un outil extrêmement pratique au sein de FreeBSD. En effet, avec le bit suid convenable il nous permet de verifier ou de manipuler l'etat du kernel à chaud ou on the fly (ca fait hype). Les informations sont stockées et affichées à travers une Management Information Base ou MIB selon le même modèle que SNMP. Par exemple pour afficher une liste des differentes variables d'etat kernel, il vous suffit d'effectuer un simple

huyhuy# sysctl -a

de la même manière que vous utiliseriez un ls. Notez que vous pouvez preciser l'entrée de la MIB si vous la connaissez juste apres l'option afin de n'afficher qu'elle. Suivant le principe des MIB, vous pouvez reduire l'affichage en precisant un champ de la MIB. Par exemple pour afficher toutes les entrées en rapport avec IP

huyhuy# sysctl net.inet.ip.*

Notez aussi que certaines variables ne sont pas modifiables et que certaines entrées de la MIB sont sous forme de tableaux utilisés à l'occasion par ps, netsat ou systat. Enfin pour obtenir une liste des variables sysctl que vous pouvez modifier, consultez la page de manuel de sysctl.

L'une des fonctionnalités interessantes de FreeBSD - et donc par extension de sysctl en kernel tuning dynamique - consiste en l'établissement de secure level au sein du systeme. Il existe ainsi 4 levels de securité au sein de FreeBSD qui peuvent etre augmentes uniquement par un processus root mais qu'aucun processus ne peut diminuer, une modification a la baisse necessitera donc la configuration de la ligne suivante dans rc.conf

kern_securelevel_enable="YES"
kern_securelevel="N"

Ou N represente l'entier correspondant au securelevel que vous desirez. Il existe donc 4 niveaux de securite qui instaurent principalement des options appelees file flags permettant de definir certains droits par default et recursivement :

Ces 2 derniers levels sont vraiment paranoid et uniquement adaptes dans le cas d'une configuration de tres haute securite avec une utilisation statique.

Pour entrer le secure level qui correspond a votre utilisation, entrez la ligne

#huyhuy sysctl -w kern.securelevel=N

Ou N correspond au securelevel desiré.

Directement lie a l'option securelevel, on trouve la commande chflags qui permet de modifier les flags qui ont ete actives par les securelevels. Les flags sont les suivants :

Ils s'utilisent tous avec la syntaxe suivante :

huyhuy# chflags -RH sappnd /bin
huyhuy# chflags -RH sappnd /sbin
huyhuy# chflags -RH sappnd /usr/libexec
huyhuy# chflags -RH sappnd /usr/lib
huyhuy# chflags -RH sappnd /usr/share/lib
huyhuy# chflags -RH sappnd /boot
huyhuy# chflags sappnd /kernel

Notez qu'en effectuant un man chflags, vous decouvrez les quelques options -notamment la recursivité - que propose cette commande. Pour retirer un file flag ce sont les mêmes options avec le prefix no tel que nosappnd. Les file flags sont interessants a placer sur certains fichiers sensibles precis ou alors carrement sur un repertoire dont vous souhaitez vous assurez de l'integrite et qui sera rarement modifie tel que dans l'exemple ou R et H permettent de suivre les liens symboliques et ce recursivement. Cependant, les restrictions que requierent les securelevel sont rebutantes dans la configuration d'une workstation necessitant par exemple l'utilisation d'un serveur X (qui ecrit dans /dev/kmem) ou des compilations ou recompilations regulieres. Une idée à utiliser de pair avec les securelevel consisterait à placer dans votre kernel l'option NO_LKM afin de se préserver du patching à chaud abusif.

Dernier detail qui n'a pas grand chose à voir avec sysctl mais qui importe beaucoup dans la gestion des droits et des fichiers. Vous avez le loisir de modifier la fstab afin de monter vos diverses partitions avec certaines options. Sous FreeBSD, au lieu de ne creer qu'une unique partition root /, le systeme cree simultanement une partition /usr et /var. Vous pouvez definir dans votre fstab pour l'ensemble de vos file systems :

huyhuy# edit /etc/fstab 
#device 	mountpoint	fs	options 	 dump	pass
/dev/ad0s2b	none		swap	sw		 0	0
/dev/ad0s2a	/		ufs	rw,nosuid	 2	2
/dev/ad0s2f	/usr		ufs	rw		 2	2
/dev/ad0s2c	/home		ufs	rw,nosuid,userquota 2	1
/dev/ad0s2e	/var		ufs	rw,noexec,nosuid 2	2
/dev/acd0c	/cdrom		cd9660	ro,noauto	 0

Nous limitons ici l'exécution dans les fichiers tmp et var afin d'éviter qu'un intrus tente d'y placer des répertoires ou des binaires et nous limitons également la presence de binaire de bit de privilège root.

Sysctl peut également nous apporter une aide précieuse dans la configuration systeme et réseau à des fins de performances élevées. Il va ainsi nous permettre d'activer certaines capacités reseau que supporte parfaitement la pile TCP/IP BSD - qui est cela dit en passant certainement la plus stable, la plus performante et la plus standard des piles TCP/IP - mais qui ne sont pas activées par defaut.

La première entrée intéressante est l'option log_in_vain qui va loguer à travers une simple entrée dans le fichier de log correspondant de syslogd, toute tentative d'accès à un service même si aucun service n'est à l'écoute sur le port de la tentative d'accès. Ceci peut nous permettre dans un environnement securisé, allié de préference avec un outil d'analyse de log tel que logcheck ou ASAX, de réperer des tentatives de network mapping même si nous avons un minimum de services disponibles et qui plus est un firewall. Cependant je ferai remarquer 2 difficultés : tout d'abord log_in_vain ne logue en réalité que les paquets avec un flags SYN, ce qui n'est pas assez pour réellement détecter un scan. Et d'autre part, dans un environnement “chaud” comme une machine servant de passerelle ou un serveur au sein d'une DMZ, l'utilisation de log_in_vain peu entrainer une quantité de log assez impressionante et capable d'occuper un analyste ou un administrateur sans outils d'analyse pendant des semaines. Mais au sein d'un réseau d'ores et deja securisé ou sur une machine critique, cette capacité de log peut etre intéressante. Pour l'activer il vous suffit de saisir:

huyhuy# sysctl -w net.inet.tcp.log_in_vain=1
huyhuy# sysctl -w net.inet.udp.log_in_vain=1

Les astuces suivantes sont intéressantes si votre machine doit servir de passerelle, de filtre ou de load balancer pour d'autres machines. La commande suivante vous offre la possibilité d'activer le forwarding IP et donc de transformer notre machine en gateway ce qui s'avérera utile pour le partage de connexion ou le deploiement d'une jail

huyhuy# sysctl -w net.inet.ip.forwarding=1

L'entrée suivante est particulierement utile dans le cadre d'un serveur qui necessité une haute disponibilité ou une grande fiabilité. En effet, nous allons apporter à notre machine le support des extensions TCP pour hautes performances. Ces extensions sont decrites dans la RFC 1323 que je vous recommande d'étudier. Elles sont constituées de 3 extensions. La première est le champ Window Scale qui est un facteur appliqué au champ Window Size et utile sur les Large Fat Network (LFN) afin d'optimiser le flux de donnees sur ces grands reseaux et d'apporter un meilleur controle en multipliant la Window Size. Nous trouvons ensuite 2 options extrêmement utiles dans le cas d'utilisation de load balancing en fournissant des informations aux algorithmes de repartition de charge. Le Round-Trip Time Mesurement (RTTM) et le Protection Against Wrapper Sequence Numbers (PAWS) se basent tous les 2 sur l'adjonction d'une option de timestamp aux segments TCP. Avec de simples verifications de timestamp on peut ainsi calculer le temps d'aller retour entre 2 ACK et ainsi optimiser le flux ou modifier la route. On peut egalement se prevenir du hijacking, de l'overlapping et surtout du rejeu en effectuant une double vérification sur le numero de sequence et le timestamp. Ces options viennent s'ajouter à l'option SackOK permettant à eux tous de ne renvoyer que les paquets effectivement perdus et ainsi d'ameliorer la fiabilité et les performances d'une connexion. L'unique bemol est que ces options ne fonctionnent bien sur qu'entre des machines supportant toutes les 2 ces options de manière similaire, or ces options ne semblent pas être très utilisées - notez que la branche 4.4 supporte la RFC 1323 par défaut - et enfin vous pourriez risquer des désagrements face à certains firewalls ou plugins de normalisation de trafic s'ils ne reconnaissent pas ces options. Cependant nous décidons de l'aborder dans cet article afin de faciliter sa diffusion et nous l'appliquons à notre système par acquis de conscience ! Et nous verifions en même temps le support de l'option Selective Acknowledgment definie dans la RFC 2018 tout en augmentant la taille par défaut de notre window size et enfin nous activons l'implémentation de la RFC 1948 appliquant la recommendation de Steve Bellovin sur la génération aléatoire d'ISN selon le schéma ISN = M + F(localhost,localport,remotehost,remoteport) où M est un timestamp.

Pour cela, il vous suffit d'effectuer les commandes suivantes :

huyhuy# sysctl -w net.inet.tcp.rfc1323=1
huyhuy# sysctl -w net.inet.tcp.sack=1
huyhuy# sysctl -w net.inet.tcp.sendspace=32768
huyhuy# sysctl -w net.inet.tcp.recvspace=32768
huyhuy# sysctl -w net.inet.tcp.strict_rfc1948=1

Nous décidons maintenant de nous proteger face a certaines tentatives de DoS ainsi que de diverses techniques de network mapping. Les lignes suivantes nous permettant ainsi de modifier le TTL par defaut utilisé dans l'OS fingerprinting, de ne pas repondre au icmp mask reply permettant une cartographie reseau, mais aussi de ne pas repondre aux message icmp broadcast très souvent source de smurf ou DoS par amplification, de mettre la limite maximale de paquets icmp en réponse à 300 par seconde, d'augmenter la taille de la queue de connexion afin d'eviter le DoS par ressource starvation tels que le SYN Flood ou le Naptha tout en augmentant le nombre maximal de socket (2 fois le maximum de connexion environ) et en verifiant si une connexion est toujours reellement active et non pas conserver dans un etat artificiel suite a un SYN Flood ou Naptha, et enfin le blackhole consiste à empêcher votre systeme d'etre scanné en ne repondant pas par un RST à chaque segment ainsi qu'a ne pas répondre par un ICMP port unreachable aux segment UDP, envoye sur un port fermé et ainsi transformer votre systeme en “trou noir” :

huyhuy# sysctl -w net.inet.ip.ttl=128
huyhuy# sysctl -w net.inet.icmp.maskrepl=0
huyhuy# sysctl -w net.inet.icmp.bmcastecho=0
huyhuy# sysctl -w net.inet.icmp.icmplim=300
huyhuy# sysctl -w kern.ipc.somaxconn=4096
huyhuy# sysctl -w kern.ipc.maxsockets=8212
huyhuy# sysctl -w net.inet.tcp.always_keepalive=1
huyhuy# sysctl -w net.inet.tcp.blackhole=2
huyhuy# sysctl -w net.inet.udp.blackhole=1

Toujours dans les protections contre les DoS mais cette fois-ci cote ressource plutot que reseau, les 2 entrees suivantes de la MIB vont nous permettent de limiter les ressources a la disposition d'un processus et d'eviter ainsi le ressource starvation qu'entrainent plusieurs DoS tels que les SYN Flood et Napthas. Notez enfin que le nombre de fichiers par processus inclut également les sockets et IPC :

huyhuy# sysctl -w kern.maxprocperuid=128
huyhuy# sysctl -w kern.maxfilesperproc=128
huyhuy# sysctl -w kern.maxfiles=65536

Par ailleurs nous possédons également quelques astuces afin d'éviter les tentatives de cache poisoning en accélérant le temps de rafraichissement de la table de routage.

huyhuy# sysctl -w net.inet.ip.rtexpire=60
huyhuy# sysctl -w net.inet.ip.rtminexpire=10

Finissons avec quelques modifications liees au systeme a modifier :

huyhuy# sysctl -w vfs.vmiodirenable=1
huyhuy# sysctl -w kern.coredump=1
huyhuy# sysctl -w kern.corefile=%N.sexfault
huyhuy# sysctl -w kern.ps_showallprocs=0

La première option permet d'améliorer le traitement notamment sur des larges volumes de fichiers. Il concerne les fichiers unix qui seront cachés dans le buffer cache plutôt que directement sur le disque exploitant ainsi pleinement la memoire virtuelle FreeBSD par ailleurs désormais très performante. Ensuite nous decidons d'activer l'application savecore qui permet de conserver une trace du core dump associe a un kernel permettant son etude apres un crash par exemple afin d'en determiner les causes - par exemple un buffer overflow. En tout dernier lieu, nous faisons en sorte que les utilisateurs ne voient que leurs propres processus et que seul le root puisse voir l'ensemble.

Nous disposons également de paramètre pour ipfw notamment pour les options keep-state de ipfw impliquant la création automatique d'une state table permettant le suivi des flux pour le filtrage de paquets. La state table et les règles ipfw qui vont avec, créent pour chaque paquet que 'match' une règle une nouvelle règle dynamique permettant de suivre et autoriser la connexion. Pour ce faire, ipfw utilise notamment pour la couche protocol un mécanisme de lifetime qui permet de conserver la règle dynamique active en attente d'un nouveau paquet qui relancera la décrémentation de ce lifetime. Si le lifetime arrive à zero sans nouveau paquet, alors la règle dynamique disparaît et les paquets sont refusés. Les entrées sysctl suivantes vous permettent de spécifier la taille de la table hashage destinée aux règles dynamiques de votre ruleset ceci ne fonctionnant qu'après avoir flushé. Enfin, la dernière entrée permet d'augmenter encore la verbosité d'ipfw en ajoutant à l'affichage des champs DiffServ, IP ID et TTL ; les champs ack number, sequence number et TCP flags. Voir http://people.freebsd.org/~cjc/ipfw_verbose_stable.patch.

huyhuy# sysctl -w net.inet.ip.fw.dyn_ack_lifetime=300
huyhuy# sysctl -w net.inet.ip.fw.dyn_syn_lifetime=20
huyhuy# sysctl -w net.inet.ip.fw.dyn_fin_lifetime=20
huyhuy# sysctl -w net.inet.ip.fw.dyn_rst_lifetime=5
huyhuy# sysctl -w net.inet.ip.fw.dyn_short_lifetime=30
huyhuy# sysctl -w net.inet.ip.fw.dyn_buckets=256
huyhuy# sysctl -w net.inet.ip.fw.curr_dyn_buckets=256
huyhuy# sysctl -w net.inet.ip.fw.verbose=2

Notez que nous disposons également de quelques fonctionnalités configurables par l'intermédiaire du loader. Si vous disposez d'un disque IDE, la commande suivante permet d'activier le cache en écriture

huyhuy# loader set hw.ata.wc=1

Si vous disposez par ailleurs de disques IBM DPTA ou DTLA, vous pouvez utiliser à la place l'entrée hw.ata.tags mais à vos risques et périls puisqu'elle est encore experimentale. Ces modifications doivent être répercutées sur /boot/loader.conf. De la même manière, les options sysctl voudrez retrouver à chaque demarrage, vous devez reporter chaque entrées dans un fichier /etc/sysctl.conf sous la forme 'entrée=parametre'.

Ci-dessous notre sysctl.conf final.

------------------------------------- SNiP ------------------------------------
net.inet.tcp.rfc1323=1
net.inet.tcp.log_in_vain=1
net.inet.tcp.sack=1
net.inet.tcp.sendspace=32768
net.inet.tcp.recvspace=32768
net.inet.tcp.strict_rfc1948=1
net.inet.tcp.always_keepalive=1
net.inet.tcp.blackhole=2
net.inet.icmp.maskrepl=0
net.inet.icmp.bmcastecho=0
net.inet.icmp.icmplim=300
net.inet.udp.blackhole=1
net.inet.udp.log_in_vain=1
net.inet.ip.ttl=128
net.inet.ip.forwarding=1
net.inet.ip.fw.dyn_ack_lifetime=300
net.inet.ip.fw.dyn_syn_lifetime==20
net.inet.ip.fw.dyn_fin_lifetime=20
net.inet.ip.fw.dyn_rst_lifetime=5
net.inet.ip.fw.dyn_buckets=256
net.inet.ip.fw.curr_dyn_buckets=256
net.inet.ip.fw.verbose=2
net.inet.ip.rtexpire=60
net.inet.ip.rtminexpire=10
net.inet.ipsec.esp_trans_deflev=1
net.inet.ipsec.esp_net_deflev=1
net.inet.ipsec.ah_trans_deflev=1
net.inet.ipsec.ah_net_deflev=1
net.inet.ipsec.def_policy=0
net.inet.ipsec.ecn=1
vfs.vmiodirenable=1
kern.coredump=1
kern.corefile=%N.sexfault
kern.ps_showallprocs=0
kern.maxprocperuid=128
kern.maxfilesperproc=128
kern.maxfiles=65536
kern.ipc.maxsockets=8212
kern.ipc.somaxconn=4096
kern.jail.set_hostname_allowed=1
kern.jail.socket_unixiproute_only=1
kern.jail.sysvipc_allowed=0
compat.linux.osname=FreeBSD
compat.linux.osrelease=4.4-STABLE
------------------------------------- SNiP ------------------------------------

– eberkut

————————————- UPDATE ————————————

kern.ps_showallprocs=0 
sysctl: unknown oid 'kern.ps.showallprocs'
=> ne semble pas exister sous FreeBSD (5.4 / 6.1)

kern.ipc.maxsockets=8212
kern.ipc.maxsockets: Invalid argument
  cela fonctionne avec les valeurs : 16424 / 32768

MODIFICATION FreeBSD version 6.1
net.inet.tcp.sack=1  ==> net.inet.tcp.sack.enable=1
net.inet.tcp.inflight_enable=1  ==> net.inet.tcp.inflight.enable=1 (une "." au lieu de "_") 
net.inet.tcp.inflight_min=6144  devient net.inet.tcp.inflight.min=6144 (une "." au lieu de "_") 

Kzper

freebsd/sysctl_avance.txt · Last modified: 2010/01/12 13:29 (external edit)