Comment créer un pont réseau logiciel sous Debian, pour faciliter les communications réseaux avec les machines virtuelles, gérées par QEMU.
La machine hôte et la|les VM invitées sont sur le même segment réseau.
Le premier point est d’installer les outils nécessaires au pont réseau logiciel :
$ sudo apt install bridge-utils
Cet article propose la configuration soit en mode CLI, soit par le biais de l’interface graphique de Network Manager.
Choisissez l’un ou l’autre, pas les deux !
Pour le principe, voici comment configurer le pont en mode CLI :
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp0s31f6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.168.***.***/24 brd 192.168.***.255 scope global enp0s31f6
valid_lft forever preferred_lft forever
Dans mon cas, l’interface filaire 2 en question se nomme enp0s31f6
… adaptez à votre cas !
$ sudo brctl addbr br0
$ sudo brctl addif br0 enp0s31f6
/etc/network/interfaces.d/br0
:## DHCP ip config file for br0 ##
auto br0
# Bridge setup
iface br0 inet dhcp
bridge_ports enp0s31f6
Si vous préférez avoir une adresse IP statique sur le même segment réseau
que votre machine hôte, adaptez en utilisant static
au lieu de dhcp
et en modifiant selon votre besoin.
$ cat /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
Si ce n’est pas le cas, adaptez ! (cela signifie que vous avez déjà modifié votre fichier)
Votre pont logiciel br0 est créé et devrait être fonctionnel.
Ce qui suit configure le pont réseau depuis l’interface graphique de Network Manager.
L’interface graphique de Network Manager est utilisable depuis l’applet réseau de votre bureau, soit en ligne de commande grâce à :
$ sudo nm-connection-editor
Votre pont réseau logiciel est créé !
Hormis le fait d’installer QEMU sur votre machine hôte, il est nécessaire d’installer les bibliothèques libvirt ; celles-ci s’installent en dépendance du paquet virt-manager.
$ sudo apt install libosinfo-bin qemu-system virt-manager
Lors de la création de votre machine virtuelle, dans les détails de l’interface réseau, il faut paramètrer selon votre propre pont réseau, tel que pour reprendre le propos d’un pont nommé ‘br0’ :
Pour l’exemple :
L’édition de votre machine virtuelle peut se faire en mode CLI, aussi,
en appelant l’outil virsh
, tel que pour l’exemple :
$ virsh --connect qemu:///system edit nom-votre-vm
ce qui vous donnera accès à son fichier XML où vous pourrez entre autre
modifier la section interface
, tel que :
(…)
<interface type='bridge'>
<mac address='00:00:00:ad:a1:9f'/>
<source bridge='br0'/>
<model type='e1000e'/>
<address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</interface>
(…)
Si jamais vous créez votre VM avec l’outil virt-install
, utilisez le
paramètre network
pour spécifier l’utilisation du pont br0,
tel que pour l’exemple :
$ vir-install … --network bridge=br0,model.type=e1000,type=bridge …
Pensez à redémarrer soit la machine hôte, soit à redémarrer la couche réseau
$ sudo systemctl restart network-manager
⇒ Vérifions avec l’outil contrôleur :
$ brctl show
bridge name bridge id STP enabled interfaces
br0 8000.2ef40298a3d6 yes enp0s31f6
On a bien un pont nommé br0
avec pour interface ethernet enp0s31f6
,
comme le montre la capture écran de l’interface graphique ci-dessus.
⇒ puis par vérifier avec l’outil bridge
:
$ bridge link
2: enp0s31f6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 100
⇒ continuons avec l’outil ip
pour vérifier les différentes interfaces réseaux :
$ ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp0s31f6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether **:**:**:**:**:** brd ff:ff:ff:ff:ff:ff
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether **:**:**:**:**:** brd ff:ff:ff:ff:ff:ff
inet 192.168.***.128/24 brd 192.168.***.255 scope global dynamic noprefixroute br0
valid_lft 36709sec preferred_lft 36709sec
inet6 fe80::****:****:****:****/64 scope link noprefixroute
valid_lft forever preferred_lft forever
br0
en tant qu’interface 3enp0s31f6
ayant pour master br0
, donc faisant
bien partie du pont br0
⇒ puis vérifions la route par défaut :
$ ip r
default via 192.168.***.1 dev br0 proto dhcp src 192.168.***.128 metric 425
192.168.***.0/24 dev br0 proto kernel scope link src 192.168.***.128 metric 425
Voilà !
Rien de bien compliqué pour créer un pont logiciel réseau pour la communication de vos VM, sur le même segment réseau que votre machine hôte.
Enjoy-IT!
Enjoy-ID!
Abordons la virtualisation de Windows 11, sous Debian Sid, avec QEMU, avec pour prérequis nécessaire l’utilisation de TPM, Secure-Boot, partage de données entre la machine hôte et la VM, … sans oublier l’UEFI.
Ce processus convient aussi pour un Windows 10 virtualisé nécessitant les mêmes prérequis.
L’hôte sera paramétré en tant que pont et la VM fera partie du même réseau que l’hôte.
Je n’aborde pas ici la configuration de l’hôte en tant que bridge réseau.
Lire mon article : Debian : Pont réseau pour QEMU
Le téléchargement de l’image ISO de Windows 11 se fait depuis : https://www.microsoft.com/software-download/windows11
Procurez-vous légalement une clé de licence Windows.
⇒ Les prérequis minimum pour une machine virtuelle exécutant Windows 11 sont les suivants :
QEMU doit être installé:
$ sudo apt install libosinfo-bin qemu-system virt-manager
libosinfo-bin
est un outil pour interroger la base de données osinfo.virt-manager
est une application de bureau pour gérer des machines virtuelles.Parmi les pré-requis de Windows 11, il y a la gestion :
Il nous installer les binaires suivants :
$ sudo apt install ovmf swtpm swtpm-tools
Pour accéder à l’interface graphique de la VM, au choix
Par défaut l’interface graphique de la VM est configurée sur spice.
Il faut installer les paquets spice-vdagent et spice-client-gtk :
$ sudo apt install spice-vdagent spice-client-gtk
Ce tutoriel se base sur l’utilisation de spice.
Pour utiliser l’interface graphique avec le serveur VNC, un client comme tigervnc-viewer peut être suffisant.
$ sudo apt install tigervnc-viewer
Ce tutoriel n’aborde pas plus cette utilisation… si ce n’est de pararmètrer le client VNC d’interroger localhost et le port VNC par défaut (à moins que vous l’ayez changé, dans ce cas agissez en conséquence).
Ajoutez votre utilisateur au groupe libvirt, voire libvirt-qemu.
$ sudo adduser your-id libvirt libvirt-qemu
Ensuite, choisissez pour faire l’installation de la VM :
Partant du principe d’un répertoire dédié dans votre homme, nommé VM :
$ cd ~/VM
$ ROOT="$(pwd)"
$ name=Win11Test
$ path="${ROOT}/${name}.qcow2"
$ size=64
$ qemu-img create -f qcow2 "${path}" "${size}G"
$ isofile=Win11_23H2_French_x64v2.iso
$ fs_dest="C:\\vmshare"
$ fs_src="${ROOT}/vmshare"
$ cdrom="${ROOT}/${isofile}"
$ conn="qemu:///system"
$ cpu="check=none,mode=host-passthrough,migratable=on"
$ disk="device=disk,format=qcow2,path=${path},size=${size},target.bus=sata,target.dev=sda,type=file"
$ fs="accessmode=passthrough,source=${fs_src},target=${fs_dest},type=mount,driver.type=virtiofs"
$ graphic=spice
$ machine=q35
$ mem="4096,maxMemory=16384"
$ memBacking="source.type=memfd,access.mode=shared"
$ net="bridge=br0,model.type=e1000,type=bridge"
$ os="detect=on,name=win11"
$ tpm="emulator,version=2.0"
$ vcpu="2,maxvcpus=4"
$ virt-install --accelerate --cdrom "${cdrom}" --connect "${conn}" --cpu "${cpu}" --disk "${disk}" --filesystem "${fs}" --graphics type="${graphic}" --hvm --machine "${machine}" --memory "${mem}" --memorybacking="${memBacking}" --name ${name} --network "${net}" --os-variant "${os}" --tpm "${tpm}" --vcpus "${vcpu}"
Direction vers l’interface graphique de la nouvelle fenêtre qui vient de s’ouvrir, titrée “Win11Test”, assez rapidement pour pouvoir valider le choix de démarrer sur le CD-ROM.
Selon votre puissance machine hôte, l’installation de Windows se fait en quelques minutes…
Veillez à activer l’option d’architecture en spécifiant l’*Architecture : x86_64 :
Choisir le chemin de l’ISO d’installation de Windows :
Choisir les paramètres mémoire et CPU :
Activer le stockage en sélectionnant un personnalisé :
Dans votre home, créez un volume de stockage personnalisé
Commençons l’installation de la VM
Le reste est le processus d’installation de Windows…
Je ne développe pas le processus d’installation en lui-même ; il ne différe en rien d’une installation sur une machine physique.
Le moyen le plus simple actuellement pour partager des copier-coller, des fichiers entre l’hôte et l’invité est l’utilisation du serveur spice ; l’utilisation de VNC n’est pas compatible pour ce propos.
D’autres possibilités sont l’usage de SSHFS, voire Samba, qui ne seront pas abordés dans cet article.
⇒ Sur l’hôte :
$ sudo apt install qemu-guest-agent spice-vdagent
⇒ Dans la VM :
Une fois l’installation de Windows terminée, et dans votre session utilisateur, avec n’importe quel navigateur web, allez télécharger :
l’utilitaire WinFSP : https://winfsp.dev/rel/
C’est l’équivalent de Fuse pour Windows.
les outils VirtIO :
https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/latest-virtio/virtio-win-guest-tools.exe
Cet ensemble packagé par l’équipe Fedora comprend les pilotes logiciels
nécessaires à la paravirtualisation et l’émulation matérielle ; il
embarque aussi l’agent Spice pour la gestion de l’affichage graphique,
et son redimensionnement automatique, le copier-coller entre l’hôte
et la VM, la redirection des périphériques USB vers la VM.
Lors de l’installation par le biais de l’outil virt-install en CLI, normalement vous avez paramétré :
fs_dest
et fs_src
nécessaires pour paramétrer correctement la variable --filesystem
memoryBacking
qui est nécessaire pour le partage mémoire.Si vous avez fait l’installation de la VM par le biais de virt-manager, arrêtez proprement la VM, puis paramétrez le partage de fichier.
~/VM/vmshare
C:\vmshare
Au redémarrage de la VM, le chemin de la cible sera privilégié en tant que lecteur Z:… si bien sûr, vous avez réalisé l’installation des deux binaires WinFSP et VirtIO ; sinon faites-le.
Veillez à ce que le module Core soit validé - ce qui est normalement le cas par défaut.
Terminez classiquement l’installation, sans autre détail.
Veillez à ce que le module Viofs soit validé - ce qui est normalement le cas par défaut.
Pendant la phase d’installation:
Une fois l’installation terminée, allez dans le gestionnaire de services :
Redémarrez la VM
Une fois à nouveau dans la session, cliquez sur l’explorateur de fichiers,
puis sur Ce PC, vous devrez y trouver le lecteur Z: connecté sur C:\vmshare.
Vous pouvez maintenant faire transiter les fichiers désirés entre l’hôte et la VM.
Voilà !
À partir de maintenant, vous êtes opérationnel ;)
Q : Le service Virtio-FS refuse de démarrer !
R : Avez-vous installé WinFSP en premier ? Si ce n’est pas le cas, faites-le ; ensuite vous pourrez le démarrer.
Q : J’ai redémarré la VM, mais le partage de fichiers sur Z: n’est pas actif !
R :
https://www.linux-kvm.org/page/WindowsGuestDrivers/Download_Drivers
https://github.com/virtio-win/virtio-win-pkg-scripts/blob/master/README.md
https://www.debugpoint.com/install-windows-ubuntu-virt-manager/
https://getlabsdone.com/how-to-enable-tpm-and-secure-boot-on-kvm/
Tout particulièrement à @Clochette ;)
Enjoy-IT!
Enjoy-ID!
Sysclean est un script perl(1) conçu pour aider à supprimer les fichiers obsolètes entre chacune des mises-à-niveau d’OpenBSD.
Par lui-même, sysclean ne retire aucun fichier ; il compare les fichiers installés par référence à ce qui devrait être dans le système de base et prend en compte les paquets installés.
Les options sont :
-a
: liste tous les fichiers installés par les packages-p
: liste les noms des packages utilisant des fichiers obsolètes-i
: inclut les noms de fichiers à ignorer, en utilisant le fichier
/etc/sysclean.ignore
- un par ligne, chemin absolu vers le fichier.Vérifions les packages “obsolètes” : # sysclean -p
Si le résultat convient à nos attentes, on effectue :
# pkg_delete $(sysclean -p | awk '{print $2}')
Et, pour terminer, retirons les dépendances inutiles :
# pkg_delete -a
L’autre outil, lui, natif au système de base sur OpenBSD est
pkg_check
;-)
Le propos de cet article est d’ajouter unbound pour permettre les requêtes DNS sur le protocole DoT , tout en modifiant légèrement dnsmasq, installé par défaut.
Le but est de :
Installons les paquets nécessaires : unbound unbound-control luci-app-unbound
# opkg update
# opkg install unbound unbound-control luci-app-unbound
Il peut être utile d’installer ces autres paquets liés à unbound :
Éditons le fichier de configuration du serveur dnsmasq, pour s’assurer des deux options suivantes :
option noresolv '1'
list server '127.0.0.1#531'
/etc/resolv.conf
531
.Bien-sûr, ces options peuvent être modifiées directement par LuCI :
Pensez à redémarrer le service dnsmasq !
La chose la plus simple est d’activer Unbound, et de cocher l’option Manual Conf pour modifier manuellement le fichier de configuration, au-travers de LuCI. Ajoutez vos réseaux dans l’option Trigger Networks, à-minima lan.
/var/lib/unbound/unbound.conf
Les changements minimum à faire correspondent aux variables suivantes :
server:
(…)
port: 531
do-ip4: yes
do-ip6: yes
do-tcp: yes
hide-identity: yes
hide-version: yes
qname-minimisation: yes
prefetch: yes
rrset-roundrobin: yes
minimal-responses: yes
tls-cert-bundle: "/etc/ssl/certs/ca-certificates.crt"
(…)
À-propos du numéro de port choisi, ici 531
: non, on ne choisit pas
5353
qui est réservé normalement au service mdns ; bien-sûr, vous pouvez
le modifier, faites-le en conséquence dans la configuration de dnsmasq,
mais veillez à le choisir dans le contexte des numéros de ports privilégiés,
à savoir en deçà des 1024 premiers…
⇒ Pensez absolument à ajouter/modifier des variables access-control
pour
n’autoriser que :
access-control: 0.0.0.0/0 refuse
access-control: ::0/0 refuse
access-control: 127.0.0.0/8 allow
access-control: ::1 allow
Puis à déclarer l’adressage IPv(4|6) de votre LAN, voire de votre Wifi…
Il est nécessaire ensuite de modifier la section forward-zone
:
forward-zone:
name: "."
forward-tls-upstream: yes
Puis d’ajouter toutes les adresses IP de serveurs concernés par DoT ; bien-sûr les deux protocoles IPv4 et IPv6 sont fonctionnels.
forward-addr: 9.9.9.9@853 # Quad9
forward-addr: 1.1.1.1@853 # Cloudflare
forward-addr: 149.112.112.112@853 # Quad9 secondaire
forward-addr: 1.0.0.1@853 # Cloudflare secondaire
forward-addr: 2620:fe::fe@853 # Quad9 / IPv6
forward-addr: 2606:4700:4700::1111@853 # Cloudflare / IPv6
forward-addr: 2606:4700:4700::1001@853 # Cloudflare secondaire / IPv6
Cet exemple ci-dessus montre l’usage des “grands” de ce monde… Voici pour le propos des alternatives intéressantes :
# FDN DoT
## https://www.fdn.fr/ouverture-des-services-dot-doh/
forward-addr: 80.67.169.12@853
forward-addr: 80.67.169.40@853
forward-addr: 2001:910:800::12@853
forward-addr: 2001:910:800::40@853
# see: https://dnsprivacy.org/public_resolvers/
# adguard.com: family protection
## https://adguard.com/en/blog/adguard-dns-announcement.html
forward-addr: 94.140.14.15@853
forward-addr: 94.140.15.16@853
forward-addr: 2a10:50c0::bad1:ff@853
forward-addr: 2a10:50c0::bad2:ff@853
# applied-privacy.net
forward-addr: 146.255.56.98@853
forward-addr: 2a02:1b8:10:234::2@853
# cleanbrowsing.org: family filter
forward-addr: 185.228.168.168@853
forward-addr: 185.228.169.168@853
forward-addr: 2a0d:2a00:1::@853
forward-addr: 2a0d:2a00:2::@853
# controld.com
## https://controld.com/free-dns?
forward-addr: 76.76.2.4@853
forward-addr: 76.76.10.4@853
forward-addr: 2606:1a40::4@853
forward-addr: 2606:1a40:1::4@853
# cz.nic
forward-addr: 193.17.47.1@853
forward-addr: 185.43.135.1@853
forward-addr: 2001:148f:ffff::1@853
forward-addr: 2001:148f:fffe::1@853
# dnsforfamily.com
forward-addr: 78.47.64.161@853
forward-addr: 94.130.180.225@853
forward-addr: 2a01:4f8:1c0c:40db::1@853
forward-addr: 2a01:4f8:1c17:4df8::1@853
# dot.sb
forward-addr: 185.222.222.222@853
forward-addr: 45.11.45.11@853
forward-addr: 2a09::@853
forward-addr: 2a11::@853
# he.net
forward-addr: 74.82.42.42@853
forward-addr: 2001:470:20::2@853
# libredns.gr
forward-addr: 116.202.176.26@853
forward-addr: 2a01:4f8:1c0c:8274::1@853
# switch.ch
forward-addr: 130.59.31.248@853
forward-addr: 130.59.31.251@853
forward-addr: 2001:620:0:ff::2@853
forward-addr: 2001:620:0:ff::3@853
Voilà pour la configuration de base, qui doit/devrait permettre d’utiliser unbound conjointement avec dnsmasq.
Pensez impérativement à redémarrer le service unbound !
Si vous avez eu l’idée d’installer l’outil unbound-checkconf, c’est le moment de l’exécuter pour vérifier que les modifications/écritures faites dans le fichier de configuration sont correctes. Si tout va bien, l’outil vous retournera ce message d’information :
# unbound-checkconf
unbound-checkconf: no errors in /var/lib/unbound/unbound.conf
S’il y a des erreurs, il vous dira où !
Si vous avez eu l’idée d’installer l’outil unbound-host, il sera possible de tester la connexion qui devrait être sécurisée, de telle manière, par exemple :
# unbound-host -vf /var/lib/unbound/root.key com.
com. has no address (secure)
com. has no IPv6 address (secure)
com. has no mail handler record (secure)
Faites de même pour les adresses www.ripe.net, www.afnic.fr, dnssec.cz. La mention (secure) assure de la connexion sécurisée.
Un petit laïus à-propos du fait de contrôler le fonctionnement d’unbound. Il est nécessaire d’initialiser le paramètrage :
# unbound-control-setup
setup in directory /var/lib/unbound/
generating unbound_server.key
Generating RSA private key, 3072 bit long modulus
...............................................................................................................++
............................................................++
e is 65537 (0x10001)
generating unbound_control.key
Generating RSA private key, 3072 bit long modulus
........................................................................++
..................++
e is 65537 (0x10001)
create unbound_server.pem (self signed certificate)
create unbound_control.pem (signed client certificate)
Signature ok
subject=/CN=unbound-control
Getting CA Private Key
Setup success. Certificates created. Enable in unbound.conf file to use
Puis de modifier le fichier de configuration d’unbound, pour ajouter/décommenter
la section remote-control
, tel que :
remote-control:
control-enable: yes
control-interface: 127.0.0.1
control-interface: ::1
control-port: 8953
control-use-cert: no
server-key-file: "/var/lib/unbound/unbound_server.key"
server-cert-file: "/var/lib/unbound/unbound_server.pem"
control-key-file: "/var/lib/unbound/unbound_control.key"
control-cert-file: "/var/lib/unbound/unbound_control.pem"
Après avoir redémarré le service, il ne reste plus qu’à tester avec
l’outil unbound-control
, tel que pour l’exemple :
# unbound-control -s ::1 status
version: 1.17.0
verbosity: 1
threads: 4
modules: 2 [ validator iterator ]
uptime: 3482 seconds
options: reuseport control
unbound (pid 32307) is running...
Il est ainsi possible de connaître la valeur de toute option par l’usage
de l’option get_option
suivie du nom de l’option.
De même, il reste possible de faire un dump du cache pour analyse du flux,
par le biais de l’option dump_cache
redirigé vers un nom de fichier.
Voilà, c’est terminé.
Enjoy-ID! Enjoy-IT!
La virtualisation de machine virtuelle sous OpenBSD est officiellement disponible nativement dans le système de base depuis OpenBSD 5.9.
Pour rappel : utiliser le virtualisateur vmd d’OpenBSD a quelques restrictions, dont celles de ne pas pouvoir utiliser d’interface graphique, …
ATTENTION : Ce tutoriel ne documente pas dans les moindres détails les phases d’installation, voire de configuration.
Il est VRAIMENT nécessaire de faire preuve de réflexion, discernement et d’avoir un minimum de compétences, pour comprendre les liens entre les différentes briques !
Merci de votre compréhension…
Il est nécessaire que votre machine sur laquelle vous souhaitez virtualiser ait un CPU compatible avec les fonctions adéquates. Pour le vérifier, tapez dans votre terminal/console la commande suivante :
$ dmesg | egrep '(VMX/EPT|SVM/RVI)'
La réponse du système doit être :
⇒ pour CPU Intel :
vmm0 at mainbus0: VMX/EPT
⇒ pour CPU Amd :
vmm0 at mainbus0: SVM/RVI
Si aucune ligne n’apparaît, aucune virtualisation ne sera possible. Par acquis de conscience, vérifiez votre BIOS|UEFI que celle-ci ne soit pas désactivée.
De même, en rapport avec les failles CPU relatives à Meltdown, Spectre, certains CPU Intel sont patchés pour remédier à L1TF. Sous OpenBSD, ces CPU reçoivent un correctif approprié. Malheureusement, cela impacte la virtualisation et rend celle-ci difficile pour certains, voire impossible. Vous pouvez vous retrouver dans la situation où vous auriez un CPU compatible, mais dans les faits, la virtualisation ne pourrait être pleinement fonctionnelle.
Préférez AMD, en attendant ARM… voire RISC V.
Il est nécessaire d’installer le firmware vmm
pour que le kernel gère.
# fw_update vmm
Par convention, créons un répertoire ‘‘vm’’ dans notre répertoire personnel,
et nous travaillerons à partir de celui-ci :
$ mkdir vm && cd vm
vether0
de l’hôte aura pour adresse IPv4 : 192.168.0.1
,
cette adresse IP sera l’adresse de la passerelle pour l’interface
réseau de la VM.enp0s3
de la VM Debian aura pour adresse IPv4 : 192.168.0.2
/etc/resolv.conf
de la VM
sont les serveurs publics de la FDN, respectueux de la confidentialité…Dans les deux cas présentés, nous commencerons par créer la VM, très
simplement avec l’outil natif à OpenBSD, nommé vmctl
:
$ vmctl create -s 50G ~/vm/bullseye.qcow2
Téléchargeons l’iso Debian :
$ ftp https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/{debian-11.5.0-amd64-netinst.iso,SHA512SUMS}
Une fois téléchargée, vérifions sa somme de contrôle :
$ sha512 -C SHA512SUMS debian-10.1.0-amd64-netinst.iso
(SHA512) debian-10.1.0-amd64-netinst.iso: OK
Si OK, alors c’est bon… sinon, re-téléchargez !
/etc/vm.conf
.switch "sw" {
interface bridge0
}
vm "bullseye" {
disable
memory 1G
cdrom /home/id/vm/debian-11.5.0-amd64-netinst.iso
disk /home/id/vm/bullseye.qcow2
interface { switch "sw" }
owner votre-identifiant
}
Bien sûr, remplacez :
/home/id
par votre répertoire homevotre-identifiant
par votre identifiant de sessionVérifiez la configuration à l’aide de l’option -n
de vmd :
$ vmd -n
Après avoir configuré les interfaces réseaux
,
il faut maintenant démarrer le service de gestion des VMs :
# rcctl enable vmd && rcctl start vmd
puis il faut s’occuper de la traduction d'adresses réseaux , et aussi des règles du parefeu …
Créons les interfaces réseaux nécessaires que sont vether0
et bridge0
qui permettront un contrôle fin de l’adressage IP et des règles PF.
Le fichier relatif est /etc/hostname.bridge0
:
# echo "add vether0" > /etc/hostname.bridge0
Le fichier relatif est /etc/hostname.vether0
:
# echo "inet 192.168.0.1 255.255.255.0" > /etc/hostname.vether0
Une fois les fichiers d’interfaces créés, donnez des droits 0600 dessus, puis démarrez les deux interfaces :
# chmod 0600 /etc/hostname.{bridge,vether}0
# sh /etc/netstart {bridge,vether}0
Dans ce contexte où la VM invitée est sur un segment réseau différent de l’hôte, il faut autoriser la redirection des paquets IP, pour que la VM puisse communiquer sur Internet - ne serait-ce que pour faire les mises à jour…
# sysctl net.inet.ip.forwarding=1
# sysctl net.inet6.ip6.forwarding=1
La première ligne est pour IPv4, la seconde pour IPv6.
Puis, pour garder les paramètres au redémarrage, modifiez le fichier
/etc/sysctl.conf
pour ajouter :
net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1
/etc/pf.conf
Ajouter au moins les règles suivantes :
(…)
domain = "80.67.169.12 80.67.169.40"
match out on egress from (vether0:network) to any nat-to (egress)
(…)
pass in quick proto { udp tcp } from (vether0:network) to any port domain rdr-to { $domain } port domain
pass on vether0 from 127.0.0.1 to any
pass on vether0 from (vether0:network) to any
(…)
vether0
doit être traduit (NATé) vers les adresses IP faisant partie
du groupe egress
.domain
(port 53
) sur les protocoles udp
et tcp
depuis
le réseau lié à l’interface vether0
soit redirigée vers le service
en question.
Les adresses IPv4 80.67.169.12
et 80.67.169.40
sont celles des
serveurs DNS publics de la FDN.
Elles peuvent être très bien celle de tout autre serveur DNS.vether0
depuis l’interface locale
vers ailleurs…vether0
vers partout !Démarrer la VM pour l’installation :
$ vmctl start -c bullseye
Choisir le menu “Install” - NE PAS APPUYEZ sur la touche ENTRÉE ;
appuyez sur la touche TAB pour éditer le menu. Il va falloir
corriger la ligne :
> /install.amd/vmlinuz vga=788 initrd=/install.amd/initrd.gz --- quiet
en
> /install.amd/vmlinuz vga=off initrd=/install.amd/initrd.gz --- quiet console=ttyS0,115200n8
;
une fois, transformée, appuyez sur la touche ENTRÉE !
Le reste de l’installation de Debian se fait comme tout autre installation…
Lors de la configuration réseau, pensez bien à paramétrer la VM correctement, si nécessaire, revoyez le chapitre sur les précisions réseaux .
Une fois l’installation terminée, ne redémarrez pas par le biais de l’installateur,
choisissez d’exécuter le shell, puis écrivez la commande :
# halt
afin d’arrêter la VM proprement !
Une fois que vous avez fini l’installation de Debian dans votre VM, que
vous avez fait les derniers réglages nécessaires pour son bon fonctionnement,
pensez à éditer à nouveau le fichier /etc/vm.conf
:
cdrom
…disable
par enable
pour la VM Debian -
si vous désirez que la VM correspondante démarre, soit lors du démarrage
de votre machine, si et seulement si le service vmd
est bien actif
et démarré lors du processus de démarrage machine, soit lorsque vous
redémarrez le service vmd
par vos soins.Voilà !
Vous n’avez tout simplement pas installé le firmware vmm !
Si vous avez ce message d’erreur ou similaire dans dmesg, de fait malheureusement, vous ne pourrez pas faire de la virtualisation ! :(
Voici un exemple - en anglais - de CPU Intel patché L1TF où le média de démarrage n’était pas trouvé.
Oui, il est possible que la VM invitée fasse partie du même segment IP que celui de votre hôte.
J’explique le propos dans cet article : [OpenBSD :: Virtualisation] Hôte et invité(s) sont sur le même bateau
Si jamais vous vous y essayer après cet article, comprenez bien :
sysctl
.Mais tout est fait dans l’article, pour que vous compreniez bien le propos.
Enjoy-IT! Enjoy-ID!
MOC (musique en console) est un lecteur audio en mode console/terminal pour Linux/Unix conçu pour être puissant et simple à utiliser.
La lecture faite par MOC est fluide, quelle que soit la charge du système ou des E/S , car elle utilise le tampon de sortie dans un thread/processus séparé. Il permet une lecture sans interruption car le prochain fichier à lire est mis en cache pendant la lecture du fichier en cours.
Les formats de fichiers supportés sont : MP3, Ogg Vorbis, FLAC, Musepack (mpc), Speex, Opus, WAVE, tous ceux supportés par la bibliothèque FFmpeg/LibAV (e.g., WMA, RealAudio, AAC, MP4), AIFF, AU, SVX, Sphere Nist WAV, IRCAM SF, Creative VOC, SID, wavpack.
Ce lecteur audio est pratique pour exécuter de l’audio sur un serveur multimédia, par le biais d’une session SSH, en mode console.
Sous OpenBSD, installez
moc
!
Très simplement, dans un terminal ou en mode console, un appel du binaire
mocp
suffit.
C’est une interface ressemblant à celle de Midnight Commander, avec deux
fenêtres, une à gauche pour naviguer dans le système de fichiers, l’autre
affichant la playlist en cours, sinon l’espace est vide.
Voici quelques interactions possibles depuis l’appui de touches :
la touche a permet d’ajouter un répertoire/fichier dans la playlist
la touche h permet d’avoir accès à la liste des différentes commandes
la touche L affiche les paroles si elles sont disponibles
la touche n permet de passer au morceau suivant
la touche o permet de jouer une piste musicale depuis une URL
les touches p et ESPACE permettent de mettre en pause
la touche q ferme le lecteur, sans arrêter la lecture audio
la touche Q arrête la lecture et ferme le lecteur, et la connexion au serveur de son
la touche R active ou non la relecture
la touche s arrête la lecture musicale
la touche S active ou non la lecture aléatoire
la touche V permet d’enregistrer la playlist, là où vous le désirez et au nom que vous désirez
la touche X active ou non la prise en charge de la lecture suivante
la touche , diminue le son de 5%
la touche . augmente le son de 5%
etc…
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Get’in Start: #!/bin/introduction
influxdb est une base de données de séries temporelles. Elle s’utilise en complément de logiciels tiers, tels des services collectant des métriques systèmes et applications, à intervalles réguliers (telegraf, collectd) ainsi que des logiciels générant des graphes personnalisés par le biais de requêtes sur la base de données (Grafana, …)
Sous OpenBSD ≤ 7.3, influxdb est disponible en tant que paquet, dans sa version 1.x.
Un groupe _influx
et un utilisateur _influx
sont créés.
⇒ Après avoir démarré le service influxdb
, il est possible de vérifier
le bon fonctionnement de la base de données.
Deux manières :
$ influx
Connected to http://localhost:8086 version unknown
InfluxDB shell version: unknown
> show databases
name: databases
name
----
_internal
$ curl -G http://localhost:8086/query --data-urlencode "q=SHOW DATABASES"
{"results":[{"statement_id":0,"series":[{"name":"databases","columns":["name"],"values":[["_internal"]]}]}]}
Dans les deux cas, si vous avez le même résultat, c’est tout bon !
Le fichier de configuration : /etc/influxdb/influxdb.conf
Avant de toucher au fichier de configuration, créons un premier utilisateur administrateur :
$ doas influx
Connected to http://localhost:8086 version unknown
InfluxDB shell version: unknown
> CREATE USER admin WITH PASSWORD 'password' WITH ALL PRIVILEGES
> SHOW USERS
user admin
---- -----
admin true
> QUIT
admin
avec des droits d’administrateur.password
est pour l’exemple…La prochaine connexion à la base de données nécessitera d’utiliser le compte administrateur.
Là, encore deux manières de faire :
auth
:$ influx
Connected to http://localhost:8086 version unknown
InfluxDB shell version: unknown
> auth
username: admin
password:
> *n instructions*
> QUIT
$ influx -username admin -password ''
password:
Connected to http://localhost:8086 version unknown
InfluxDB shell version: unknown
> quit
(en réalité, il existe d’autres manières de faire…)
Si c’est bon dans les deux cas, c’est tout bon !
À partir de maintenant, la base de données n’est pas ouverte à tout le monde.
Pour activer l’authentification HTTP, il faut modifier le fichier de configuration.
Aller à la section [http]
puis décommenter à minima les variables suivantes :
enabled = true
auth-enabled = true
[http]
# Determines whether HTTP endpoint is enabled.
enabled = true
# Determines whether the Flux query endpoint is enabled.
# flux-enabled = false
# Determines whether the Flux query logging is enabled.
# flux-log-enabled = false
# The bind address used by the HTTP service.
bind-address = ":8086"
# Determines whether user authentication is enabled over HTTP/HTTPS.
auth-enabled = true
(…)
Puis redémarrer le service…
Testons à nouveau une requête HTTP :
$ curl -G http://localhost:8086/query --data-urlencode "q=SHOW DATABASES"
{"error":"unable to parse authentication credentials"}
Puisqu’il demande une authentification, utilisons curl en précisant l’utilisateur :
$ curl -G http://localhost:8086/query -u admin -p '' --data-urlencode "q=SHOW DATABASES"
Enter host password for user 'admin':
{"results":[{"statement_id":0,"series":[{"name":"databases","columns":["name"],"values":[["_internal"]]}]}]}
Après avoir entré le bon mot-de-passe, la requête pour voir les bases de données aboutit bien.
Si c’est le cas, nous avons réussi le principal : installer influxdb, faire une configuration de base fonctionnelle. Voilà.
Maintenant, allons plus loin, pour utiliser le protocole HTTPS qui permettra de sécuriser la connexion avec les autres services, d’autant si ceux-ci sont à distance.
Dans ce contexte tutoriel, nous utilisons des certificats auto-signés. En conséquence, ils ne sont pas certifiés par une Autorité de Certification.
Pas besoin de passer par cette étape, si vous utiliser une AC ; il suffit
de renseigner le chemin absolu vers les certificats générés par l’AC.
Dans ce cas, allez directement à la partie de la configuration correspondante
à la section [http]
.
Ici, nous utilisons l’outil certtool
:
$ apropos certtool
certtool(1) - GnuTLS certificate tool
Si le paquet gnutls n’est pas installé, faites-le.
Puis avec des droits administrateurs, allez dans /etc/ssl
, créer un
répertoire influxdb
dans lequel faire les opérations suivantes :
# mkdir -p /etc/ssl/influxdb
# cd /etc/ssl/influxdb
⇒ Création de la clé privée
# certtool -p --hash SHA3-256 --sec-param ULTRA --outfile $(hostname).priv.k.pem
⇒ puis création de la clé publique :
# certtool -s --load-privkey $(hostname).priv.k.pem --outfile $(hostname).cert.pem
qui vous posera plein de questions concernant l’identification, raison sociale et le but de ce certificat.
⇒ modifions les droits utilisateurs :
# chown _influx:_influx *.pem
Ceci étant fait, retournons modifier le fichier de configuration, à nouveau
à la section [http]
, mais cette fois-ci pour modifier les valeurs suivantes :
https-enabled = true
https-certificate = "/etc/ssl/influxdb/votre-nom-hote.cert.pem"
https-private-key = "/etc/ssl/influxdb/votre-nom-hote.priv.k.pem"
(…)
# Determines whether HTTPS is enabled.
https-enabled = true
# The SSL certificate to use when HTTPS is enabled.
https-certificate = "/etc/ssl/influxdb/votre-nom-hote.cert.pem"
# Use a separate private key location.
https-private-key = "/etc/ssl/influxdb/votre-nom-hote.priv.k.pem"
(…)
⇒ Relancer le service !
Testons la connexion :
$ influx -ssl -unsafeSsl -username admin -password ''
password:
Connected to https://localhost:8086 version unknown
InfluxDB shell version: unknown
> SHOW DATABASES
name: databases
name
----
_internal
> SHOW USERS
user admin
---- -----
admin true
> QUIT
$ curl -G https://localhost:8086/query -k -u admin -p '' --data-urlencode "q=SHOW DATABASES"
Enter host password for user 'admin':
{"results":[{"statement_id":0,"series":[{"name":"databases","columns":["name"],"values":[["_internal"]]}]}]}
Remarquez l’utilisation de l’option -k
, sans elle, étant donné ce
contexte d’utilisation de certificats auto-signés, curl refuserait de se
connecter avec le message d’erreur suivant :
curl: (60) SSL certificate problem: unable to get local issuer certificate
Par défaut, la journalisation des traces HTTP(S) se fait dans le moteur interne de journalisation d’influxdb et sera visible dans le log ‘daemon’.
Il est possible de changer ce comportement pour avoir le suivi HTTP(S)
au sein d’un fichier dédié. Toujours dans la section [http]
, modifiez
la variable access-log-path
.
Avant de redémarrer le service, créer impérativement le répertoire dans lequel influxdb écrira le fichier log et donnez lui les droits systèmes liés, tel que :
# mkdir -p /var/log/influxdb/
# chown _influx:_influx /var/log/influxdb/
Puis pour la configuration :
access-log-path = "/var/log/influxdb/access.log"
Pour finir, pensez à modifier le fichier /etc/newsyslog.conf
pour ajouter
une ligne, telle que :
/var/log/influxdb/access.log _influx:_influx 644 7 * * Z
End of Documentation
Voilà. Maintenant, influxdb est prêt pour une utilisation interne et n’attend plus qu’à être configurer pour discuter avec tout plein d’autres services…
curl se plaint… et me casse les pieds, par la même occasion. Voici quelques pistes face à certaines erreurs :
Êtes-vous sûr d’avoir activer l’option https-enabled
dans la section [http]
?
Vérifiez !
Comme le contexte d’utilisation décrit dans ce guide de démarrage, vous avez généré vos propres certificats sans utiliser d’Autorité de Certification.
Ajoutez l’option -k
!
Le message d’erreur dans le log daemon est du type :
lvl=error msg="unable to open access log, falling back to stderr" log_id=0eMCqvRl000 service=httpd error="open /var/log/influxdb/: is a directory" path=/var/log/influxdb/
Le chemin spécifié dans la variable access-log-path
est soit inexistant,
soit influxdb n’a pas les droits systèmes pour y accéder.
Vérifiez !
Voyons ensemble comment gérer les fonctionnalités multimédias sous OpenBSD.
Le bip sonore qui se fait entendre parfois dans certains contextes, tel lors de l’utilisation de la complétion de commande avec la touche Tab, peut être rendu muet.
Avant OpenBSD 6.7, c’est l’outil mixerctl
qui le permettait :
# mixerctl inputs.mix_beep = 0
Depuis OpenBSD 6.7, ce paramètre est géré par le pilote wscons(4)
et configuré par le biais du contrôleur wsconsctl(8)
— ce qui
nécessite des droits administrateurs.
Pour le rendre muet :
# wsconsctl keyboard.bell.volume=0
Pour le désactiver définitivement et garder le paramètre au redémarrage,
copiez-le fichier /etc/examples/wsconsctl.conf
vers /etc
et
décommentez la ligne : #keyboard.bell.volume=0
Depuis OpenBSD 6.4, pour des raisons de confidentialité, l’enregistrement audio est désactivé. Pour le réactiver :
# sysctl kern.audio.record=1
Pensez à modifier le fichier /etc/sysctl.conf
!
Cela sera utile dans le contexte d’utilisation d’un microphone, d’une webcam ayant un micro, etc… ce qui permettra d’utiliser correctement tout logiciel tel audacity… ainsi que lors de l’utilisation du protocole WebRTC avec les navigateurs web, que sont Firefox et Chromium.
La gestion des niveaux de volume se fait en espace utilisateur, grâce à l’outil sndioctl(1). Pas besoin de droits administrateur dans la session utilisateur.
$ sndioctl output.level=+0.1
$ sndioctl output.mute=!
$ sndioctl output.level | awk -F = '{printf "%d\n",$2*100}'
Pensez à modifier votre fichier ~/.kshrc
pour ajouter la commande
si vous voulez un niveau audio par défaut lors du démarrage de la session.
Pour la gestion des paramètres, c’est l’outil mixerctl(1) qui est à utiliser. Celui-ci s’utilise toujours avec des droits administrateurs !
# mixerctl -av
permet de savoir ce qui de votre matériel est reconnu.Toute modification de paramètres devra être enregistré dans le fichier
/etc/mixerctl.conf
qui n’existe pas par défaut. Il faut le copier depuis
les fichiers d’exemples :
# cp /etc/examples/mixerctl.conf /etc/
Illustrons par le cas d’utilisation d’une sortie USB Audio et SPDIF :
C’est apparemment une situation complexe qui semble n’avoir encore à ce jour pas de solution.
Pour comprendre le propos lire la discussion suivante et suivez le fil : https://marc.info/?l=openbsd-tech&m=158780750403100&w=2
outputs.mode=analog
Il est de plus en plus courant d’avoir un périphérique Audio par USB, voir
un DAC Audio USB. Une fois connecté, pour vérifier son support, utilisons
la commande suivante :
dmesg | grep uaudio
ainsi que la commande usbdevs
.
Tel que, pour l’exemple :
uaudio0 at uhub0 port 1 configuration 1 interface 1 "Logitech Logitech USB Headset" rev 1.10/10.13 addr 2
uaudio0: class v1, full-speed, sync, channels: 2 play, 1 rec, 7 ctls
audio1 at uaudio0
qui est reconnu en tant que périphérique uaudio0
qui est connecté sur
le périphérique spécial audio audio1
.
Le serveur sndiod le reconnaît en tant que périphérique snd/1
.
Deux manières différentes de procéder :
server.device
pour qu’il
écoute le périphérique snd/1
:
$ sndioctl server.device=1
ce qui a pour avantage de ne pas avoir à reconfigurer tout autre logiciel
pour écouter ledit périphérique.snd/1
.Par exemple, avec le logiciel audacious, il faut aller dans les
Paramètres > Paramètre de son, puis face au champ Greffon de sortie,
il y a deux boutons, dont l’un nommé [Paramètres] qui ouvre une autre
fenêtre où pour le champ Périphérique :, il faudra écrire le nom du
périphérique audio USB, soit snd/1
, puis valider et écouter du son…
Il existe une manière alternative pour que le serveur sndiod reconnaisse
automatiquement le périphérique USB en tant que périphérique par défaut,
lorsqu’il est connecté physiquement, puis de rebasculer sur le périphérique
snd/0
dès que ce n’est plus le cas.
Pour ce contexte, il faut redéfinir les drapeaux du serveur sndiod puis le relancer :
# rcctl set sndiod flags -f rsnd/0 -F rsnd/1
# rcctl restart sndiod
Le serveur n’est pas capable de se relancer automatiquement si vous connectez
le périphérique USB après le (re)démarrage du serveur. Une fois, le périphérique
connecté, rechargez tout simplement le serveur :
# rcctl reload sndiod
forcera le serveur a détecter à nouveau le périphérique.
Un autre outil disponible est l’utilisation de la commande usbhidaction
…
Je vous renvoie au manpage relatif — cf la section Documentations .
⇒ Après avoir connecté physiquement votre microphone USB, vérifiez la reconnaissance :
$ dmesg | grep audio
uaudio0 at uhub4 port 2 configuration 1 interface 1 "BIRD UM1 BIRD UM1" rev 1.10/1.00 addr 2
uaudio0: class v1, full-speed, sync, channels: 0 play, 1 rec, 2 ctls
audio1 at uaudio0
(dans mon cas, le microphone est bien le BIRD UM1.)
Si vous avez une sortie similaire, alors votre microphone USB est bien reconnu et sera utilisable ; si non, dommage.
Là encore du fait d’être un périphérique USB, le serveur sndiod capture
l’enregistrement micro en tant que périphérique snd/1
principalement.
⇒ Pour utiliser le microphone USB sous OpenBSD :
# rcctl set sndiod flags -s default -m play,mon -s mon
$ sndioctl input.mute=0
$ sndioctl input.level=1
Un petit test de fonctionnement, en parlant près du microphone :
$ aucat -f snd/1 -o output.wav
Et pour l’écoute :
$ aucat -i output.wav
Pour utiliser une sortie SPDIF, il faut modifier le mode de sortie ; en effet, par défaut le mode de sortie correspond à l’analogique.
Avec l’outil mixerctl
, modifiez ce mode, tel que :
outputs.mode=digital
Ensuite, il faut modifier le serveur de son sndiod(8) pour qu’il gère
les canaux audio correspondants, car par défaut, il ne gère que les deux
premiers canaux, à savoir 0:1
; ce qui permet d’avoir quand même un son
stéréo.
Avant de le modifier, vérifions dans un premier temps, la sortie SPDIF,
tel que :
# mixerctl outputs.SPDIF_source
Dans le contexte de la carte-mère que j’utilise :
$ doas mixerctl outputs.SPDIF_source
outputs.SPDIF_source=dig-dac-2:3
Ainsi, la sortie SPDIF se fait sur les canaux 2 et 3.
Modifions le serveur sndiod pour ajouter la gestion des canaux 2 et 3, au démarrage de celui-ci :
# rcctl set sndiod flags -c 0:3
# rcctl restart sndiod
Il est possible de lui signifier de n’utiliser que les canaux 2 et 3.
De plus, votre matériel peut certainement utiliser encore plus de canaux. À vous de modifier en conséquence…
Lire le manpage sndiod(8) qui montre dans les exemples son utilisation en espace utilisateur.
Par défaut, depuis OpenBSD 6.9, pour des raisons de confidentialité, l’enregistrement vidéo est désactivé !
Pour le réactiver :
# sysctl kern.video.record=1
Pensez à modifier le fichier /etc/sysctl.conf
!
Cela sera utile dans le contexte d’utilisation d’une webcam ayant un micro, etc… ce qui permettra d’utiliser correctement tout logiciel tel fswebcam… ainsi que lors de l’utilisation du protocole WebRTC avec les navigateurs web, que sont Firefox et Chromium.
Lorsque vous essayez de changer le mode de sortie de l’analogique vers le digital et réciproquement, le système vous répond avec ce message interdisant la modification.
mixerctl
Pour vérifier le fonctionnement du serveur sndiod(8), hormis de vérifier
le status de son démon, utilisez la commande suivante :
$ pgrep -lf sndiod
Par exemple
$ pgrep -lf sndiod
44982 /usr/bin/sndiod -c0:3
16091 sndiod: helper
qui montre le fonctionnement du serveur…
Enjoy-ID! Enjoy-IT!
obsdfreqd est un service/démon permettant de gérer la fréquence de votre CPU dans l’espace utilisateur.
Beaucoup de paramètres permettent de configurer la fréquence tels que la fréquence min/max, l’inertie, etc. obsdfreqd supporte aussi la limitation de la fréquence une fois qu’une certaine température est atteinte afin de protéger le système, en le faisant revenir sous le seuil. Bien qu’il y ait beaucoup de paramètres, ceux par défaut sont suffisamment bon pour chacun.
Installez
le
paquet obsdfreqd
.
Il est nécessaire :
obsdfreqd
.apmd
s’il est utilisé,-L
.obsdfreqd
et apmd
Note : Il est possible de ne pas utiliser le service apmd
; quoiqu’il
en soit de par le fonctionnement du service d’obsdfreqd, apmd doit être
exécuté en paramètre manuel qui mettra la fréquence CPU au minimum,
obsdfreqd prend le relais correctement.
Utiliser apmd en mode manuel est utile pour la gestion d’événements, tels que la veille et l’hibernation.
Si besoin, il est possible de paramétrer manuellement obsdfreqd.
Retrouvez les différentes options sur la page du projet : https://tildegit.org/solene/obsdfreqd/#usage
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
pass
est un gestionnaire de mot-de-passe, respectant la philosophie Unix,
qui se veut être simple. Et, pour d’aucuns, il est CLI… mais pas que !
Des gestionnaires de mot-de-passe, il en existe pléthore ; pour n’en citer quelques uns, tel KeePass (et ses déclinaisons), BitWarden, etc…
Comme beaucoup, c’est plus un gestionnaire d’identités et d’informations personnelles confidentielles qu’un basique gestionnaire de mots de passe. En bref, c’est un coffre fort numérique, en CLI, à la sauce GPG !
Qu’a donc de SI particulier pass ? Il est :
Mais encore ? Il fait de la complétion pour les shells suivants :
Et pour finir, il a des extensions intéressantes, certaines pour navigateurs web, et des clients GUI pour différentes plateformes.
Installons le binaire et l’interface graphique — cette dernière n’est pas nécessaire, mais utile — :
⇒ Debian/*Buntu (et assimilés) : apt install pass qtpass
⇒ OpenBSD : pkg_add password-store qtpass
Parmi les extensions utiles, il y a :
pass-import pour importer depuis de nombreux autres gestionnaires de mot-de passes ;
pass-extension-tail pour afficher les informations secondaires, renfermées dans un des fichiers chiffrés.
make install
pass-otp qui ajoute le support des tokens OTP. Dans le contexte de sécurité multi-facteurs, il vaut mieux utiliser une autre application, qui sera elle seule responsable de cet aspect.
Il en existe quelques autres… dont pass-tomb.
Parmi les clients compatibles actifs, il existe principalement :
qtpass : interface QT pour Linux, *BSD
Password Store : pour Android, disponible, entre autres, sur F-Droid ; à coupler avec l’app OpenKeychain pour gérer la clé GPG.
BrowserPass : un projet scindé en deux :
passforios : pour iOS
y’en a même une pour les addicts emacs….
Et certainement bien d’autres…
Un fichier de configuration spécial ~/.password-store/.extensions/COMMAND.bash
peut être créé afin d’activer les extensions installées.
Il faut y ajouter :
PASSWORD_STORE_ENABLE_EXTENSIONS=true
pour ajouter le support des extensionsQuelques variables d’environnement utiles :
PASSWORD_STORE_DIR
définit le répertoire par défaut du gestionnaire
PASSWORD_STORE_EXTENSIONS_DIR
définit le répertoire des fichiers
d’extension ; par défaut PASSWORD_STORE_DIR/.extensions
.
PASSWORD_STORE_CLIP_TIME
est le nombre de secondes de rétention dans
le presse-papier, par défaut de 45 secondes.
PASSWORD_STORE_GENERATED_LENGTH
est la longueur en nombre de caractères
du mot de passe à utiliser par défaut pour l’option generate
.
PASSWORD_STORE_GPG_OPTS
afin de passer des options à GPG.
EDITOR
sera l’éditeur texte utilisé par l’option edit
.
Et à coup sûr, d’autres…
Il peut être utile, surtout en rapport avec l’extension Browserpass,
d’éditer le fichier ~/.gnupg/gpg-agent.conf
pour ajouter la gestion de
la saisie correcte des mots de passe par l’outil pinentry, tel que :
pinentry-program /usr/bin/pinentry-gtk-2
pour un bureau utilisant
les bibliothèques Gtk2, tel Cinnamon, Gnome 2, Mate, Xfce, …
pinentry-program /usr/bin/pinentry-gnome3
, pour Gnome 3, Xfce, …
pinentry-program /usr/bin/pinentry-x11
pour tout autre bureau sous
environnement X11, tel Enlightenment, LXDE, LXQt, dwm, …
voire pinentry-program /usr/bin/pinentry
ou son équivalent /usr/bin/pinentry-curses
si vous ne fonctionnez qu’en environnement terminal.
Bien que le site soit descriptif quant à son installation et utilisation, ainsi que le man page, voyons ensemble quelques étapes intéressantes :
⇒ L’usage de la commande pass
sans aucune option affiche le contenu
de l’arborescence tel que créé, par vos soins. Pour l’instant, il est vide.
L’initialisation du gestionnaire se fait localement et est liée à une clé GPG créée précédemment, tel que :
$ pass init email@domain.tld
mkdir: created directory ‘/home/your-user/.password-store’
Password store initialized for email@domain.tld.
Il est important de comprendre que l’initialisation puis l’ouverture du gestionnaire demandera obligatoirement le mot de passe liée à la clé GPG.
En second, vient la phase du dépôt local git :
$ pass git init
Initialized empty Git repository in /home/your-user/.password-store/.git/
[master (root-commit) 998c8fd] Added current contents of password store.
1 file changed, 1 insertion(+)
create mode 100644 .gpg-id
Il crée localement le fichier .gpg-id
qui renferme l’identifiant long
de l’empreinte de la clé GPG.
⇒ Ajout du dépôt extérieur
Ensuite ajouter un dépôt Git extérieur — ceci sera utile pour la réplication des données au-travers des différents GUI disponibles, sur d’autres OS — :
$ pass git remote add origin URL-depot-git
⇒ Ajout des signatures GPG
De plus, il est fortement recommandé d’ajouter le support des signatures GPG :
$ pass git config --bool --add pass.signcommits true
Chaque commit nécessitera ainsi l’usage d’une clé GPG pour confirmer que vous êtes bien l’auteur de la modification. La Clé GPG peut très bien être différente de celle liée au gestionnaire pass. Elle est liée à la configuration du dépôt extérieur.
⇒ À-propos de Git :
Les options de Git sont utilisables en argument de l’option git
exactement
à l’identique de l’outil Git.
pass git push
, à minima.pass git pull
…Du fait d’avoir initié le dépôt local git, chaque création, la moindre modification, d’un fichier chiffré générera automatiquement un commit. Si vous utilisez la signature GPG de commit, il vous sera demandé le mot de passe lié à la clé GPG pour les commits… qui, pour rappel, peut très bien être différente de la clé GPG du gestionnaire pass.
Après un certain délai, relativement court : 45 sec., même la consultation d’un fichier chiffré provoquera un appel du mot de passe lié à la clé GPG relative au gestionnaire pass. Ne soyez pas étonné que cela vous soit régulièrement demandé.
Conventions d’écriture :
C’est une convention utile à respecter… mais par défaut, étant donné que c’est un simple fichier texte chiffré, pass n’impose aucun schéma ou type d’organisation. Si ce n’est qu’il est préférable d’avoir en première ligne l’écriture du mot de passe, car c’est son mode opératoire, et là où toute extension, tout client cherchera cette information précise.
Merci de lire le man page pour avoir d’autres notions de conventions.
⇒ Création
Créons notre premier fichier chiffré nommé test, à l’aide de
l’option insert
:
$ pass insert test
Enter password for test:
Retype password for test:
[master 53331b0] Add given password for test to store.
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test.gpg
Lors de la création, il est demandé de taper un mot de passe, puis de le ré-écrire une deuxième fois, puis un commit est généré.
Cette option permet de définir par ses propres soins un mot-de-passe.
L’utilisation de l’argument -m
permet l’ajout d’autres informations, en
mode multilignes. Il faudra presser la combinaison de touches CTRL+D
pour sortir de ce mode d’édition.
⇒ Édition
L’édition de tout fichier chiffré se fait avec l’option edit
, tel que :
$ pass edit test
Ce qui aura pour propos d’ouvrir l’éditeur de texte lié à votre environnement
ou par défaut vi
, si aucun n’est configuré. Là, encore pour les amoureux
d’emacs, installez l’extension correspondante.
Il est ainsi possible de modifier toute information dans le fichier chiffré, dont le mot de passe, lisible en clair.
⇒ Génération d’un mot de passe
-i
, l’utilisation de cette option
sur un fichier chiffré aura pour conséquence de vider toute information
existante. Il sera demandé de confirmer avant ; en cas de refus de votre
part, l’action cessera.La génération d’un nouveau mot-de-passe pour un fichier chiffré se fait
par le biais de l’option generate
, suivi du nom de fichier chiffré et
d’un chiffre représentant la longueur du mot de passe désiré :
$ pass generate test 32
An entry already exists for test. Overwrite it? [y/N] y
[master 5195534] Add generated password for test.
1 file changed, 0 insertions(+), 0 deletions(-)
The generated password for test is:
zJwz\1E(RjL3Ps{&7|?QZAt{&ps_A_GU
-n
qu’il faut ajouter, tel que :$ pass generate -n test 64
An entry already exists for test. Overwrite it? [y/N] y
[master 6dff2bd] Add generated password for test.
1 file changed, 0 insertions(+), 0 deletions(-)
The generated password for test is:
EWA0SlCkzcmlMgxMWJltGnHCMSxK4YXmPYg4X3BrNryJgoUREVVFaaOXSiKijbtm
L’option generate
utilise le périphérique spécial /dev/urandom
pour
générer le mot-de passe.
L’argument -c
copiera le mot de passe généré dans le presse-papier sans
l’afficher.
L’argument -i
est pertinent pour ne pas détruire les informations contenues
dans le fichier chiffré, tout en créant un nouveau mot de passe, tel que :
$ pass generate -i test 32
[master 25f75ab] Replace generated password for test.
1 file changed, 0 insertions(+), 0 deletions(-)
The generated password for test is:
FrCL98OE9C9*7bJusLVbw$%\@Y^[,|Lj
⇒ Voir le contenu
Pour voir le contenu d’un fichier chiffré, il suffit de l’appeler directement :
$ pass test
EWA0SlCkzcmlMgxMWJltGnHCMSxK4YXmPYg4X3BrNryJgoUREVVFaaOXSiKijbtm
login: test@gmail.com
URL: https://test-moi.tld
comments: Ceci est un faux compte pour test du gestionnaire `pass`
Merci de l'utiliser...
PIN: 123789654
Les informations secondaires affichées dans cet exemple sont des ajouts
par mes soins, grâce à l’option edit
.
⇒ Trouver un contenu
Pour (re)trouver un contenu, c’est l’option find
qui est à utiliser.
⇒ Copie et presse-papier
Pour copier dans le presse-papier, sachant qu’en suivant la convention de la première ligne comme étant le mot de passe :
$ pass -c test
Copied test to clipboard. Will clear in 45 seconds.
Reste plus qu’à le coller où nécessaire.
Pour copier, selon la convention décrite ci-dessus, l’identifiant lié :
$ pass -c2 test
Copied test to clipboard. Will clear in 45 seconds.
Etc.
⇒ Suppression
La suppression d’un fichier chiffré est très simple :
$ pass rm test
rm: remove regular file ‘/home/your-user/.password-store/test.gpg’? y
removed ‘/home/your-user/.password-store/test.gpg’
Il existe quelques autres options ; je vous laisse les découvrir dans le
man page, telles cp
, ls
ou l’usage de grep
, etc.
La fonction OTP fonctionne bien, à partir du moment où l’on importe des données depuis une autre source, grâce à l’extension pass-import.
En CLI, je ne suis pas arriver à utiliser pass-otp ; j’ai beau
eu faire pass otp nom_fichier
, impossible ; alors qu’avec qtpass
et Password Store, cela fonctionne.
Bien-sûr, tout cela se gère aussi au-travers de l’interface graphique qtpass.
L’application graphique qtpass est intéressante car elle permet de définir dans son onglet “Paramètres” :
pwgen
pour générer le mot-de-passe, et exclure ou non les
lettres en majuscule, les nombres, les autres symboles, tels les caractères
accentués, de générer des mots de passe facile à mémoriser⇒ Dans son onglet “Programs”, d’utiliser soit l’outil pass, soit les outils natifs que sont Git et GPG…
⇒ De créer des profils de gestionnaire différents depuis l’onglet “Profiles”.
⇒ De créer des modèles d’affichage de l’information pour les fichiers chiffrés, depuis l’onglet “Templates”.
L’app Password Store nécessite l’app OpenKeychain, toutes deux installables depuis le store F-Droid.
OpenKeychain sert à stocker une ou plusieurs clés GPG.
Pour utiliser votre clé GPG dans votre smartphone, il vaut mieux se prémunir de quelques précautions suivantes :
gpg --armor --gen-random 1 20
gpg --armor --export-secret-keys "GPG-Fingerprint-long" | gpg --armor --symmetric --output mykey.sec.asc
decrypted.key
qu’il faudra importer lui aussi dans OpenKeychain.L’extension Browserpass pour les navigateurs web Chrome et Firefox est simple à utiliser. Pour un site web donné, elle va chercher les occurrences dans le gestionnaire pass. Elle va automatiquement cibler le site web dont la page est ouverte.
Voilà un gestionnaire de mot de passe, totalement chiffré, par clé GPG, dont les changements de chaque fichier .gpg sont versionnés par le biais de Git, encapsulés soit dans une connexion SSH ou TLS selon l’usage.
Chaque usage, que ce soit de la consultation ou de la modification, quelque soit l’outil utilisé, en CLI, par GUI, par une extension ou une autre, telle l’extension Browserpass, nécessite absolument l’authentification GPG.
Voilà pour la découverte, assez complète, de ce gestionnaire de mot de passe, voire d’informations personnelles… pardon, que dis-je, de ce coffre fort numérique différent.
Comment faire de petites économies d’énergie sous OpenWRT : éteindre et activer les puces Wifi à heures programmées !
Très simplement, dans un premier temps, il faut installer les deux modules suivants wifischedule et luci-app-wifischedule.
En mode CLI:
opkg install wifischedule luci-app-wifischedule
Avec l’interface web LuCI, allez dans la section ‘System’ > ‘Software’.
Une fois installés, un nouveau menu est disponible depuis l’interface LuCI, dans ‘Services’ > ‘Wifi Schedule’.
Cette section propose 3 onglets, positionné par défaut sur ‘Schedule’.
Pour activer le programmateur, cliquez sur la case à cocher : ‘Enable Wifi Schedule’, dans la section ‘Global Settings’.
Vous y trouverez tout particulièrement trois boutons :
Dans la section ‘Schedule events’, par défaut, deux programmations sont déjà paramétrées :
Une case à cocher ‘Enable’ à activer ou non pour chacun des paramétrages, avec les jours prédéfinis, ainsi que des horaires. Bin-sûr, tous ces paramétrages par défaut peuvent être changés.
Il est même possible de forcer l’extinction de la connexion des périphériques en cochant la case ‘Force disabling wifi even if stations associated’.
En fin de section, un champ vide avec un bouton [ ADD ] pour ajouter de nouveaux paramétrages.
Une fois les paramètres choisis, reste plus qu’à cliquer sur le bouton [ SAVE & APPLY ].
Maintenant la consultation du menu ‘Network’ > ‘Wireless’ aura pour propos de montrer le wifi actif aux périodes d’activité programmés, ou d’être pleinement désactivés lors des périodes d’extinction programmés, tel que la capture d’écran ci-dessous :
Voilà, comment vous pouvez éteindre la ou les puce(s) Wifi de votre routeur OpenWRT.
Il est possible de le faire en mode CLI de manière plus basique, sans cet outil… mais avouez qu’il est bien pratique.
EOD - Fin de Documentation
En 2018, je me suis posé la question de la gestion des enregistrements TLSA, selon le protocole DANE, lié au protocole de sécurité DNSSEC, dans mes zones DNS. (cf: DNS: Générer un enregistrement TLSA) - je vous invite à le lire…
Certains vont utiliser l’outil knot, fourni en tant que paquet sous OpenBSD, car ils trouvent complexe à gérer. Mais nous verrons avec un peu d’astuces comment gérer cela de manière automatisé en shell, sous OpenBSD.
Pour rappel, mon service DNS fonctionne depuis plus de 4 ans, sous OpenBSD grâce au logiciel natif nsd. La gestion des enregistrements DNSSEC se fait grâce aux outils ldns à installer en tant que paquet tiers. J’utilise dans les faits l’outil ldnscript qui permet de gérer la création des clés nécessaires puis s’occupe de gérer les enregistrements DNSSEC adéquats.
⇒ En Juin 2022, j’ai décidé de basculer du chiffrement RSA par l’utilisation de l’algorithme à courbes elliptiques nommés ECDSA.
Avant d’aller plus loin en ce sens, passons à l’installation des prérequis nécessaires :
Pour me rappeler comment faire, je me suis fait le petit mémo suivant :
installer les binaires nécessaires :
$ doas pkg_add ldns-utils git
télécharger et installer ldnscripts
$ cd /usr/local/src/
$ doas mkdir ldnscripts
$ doas chown $USER ldnscripts
$ git clone https://framagit.org/22decembre/ldnscripts.git
$ cd ldnscripts
$ doas make install
; SHA256 est largement suffisant et sécuritaire
ALG=ECDSAP256SHA256
NSEC3_ALG=SHA-256
initialisation du domaine
$ doas ldnscript init domain.tld
nécessité de créer un lien symbolique /usr/bin/dig vers /usr/sbin/dig :
$ doas ln -sf /usr/bin/dig /usr/sbin/dig
(sans ce dernier point, l’outil ldnscript
ne pourra trouver le binaire
dig
et donc refusera de fonctionner en se mettant en erreur).
Tous les mois, je crée le rollover nécessaire des clés en intégrant dans
le script /etc/monthly.local
, le code shell suivant :
### ldnscript
printf '%s\n' "=> ldnscript rollover"
/usr/local/sbin/ldnscript rollover all
Dans la foulée, du rollover des clés DNSSEC, mon script interroge les services Let’s Encrypt pour savoir s’il faut un renouvellement des certificats pour les noms de domaines que j’utilise.
Normalement, on utiliserait le client acme
natif sous OpenBSD, mais ayant
eu certains déboires, j’ai décidé de basculer sur l’usage de certbot
.
Une simple écriture shell suffit pour le renouvellement :
/usr/local/bin/certbot renew --pre-hook "rcctl stop nginx" --post-hook "rcctl start nginx"
(en effet, j’utilise aussi le serveur nginx, en lieu et place du serveur web natif httpd - mais il suffit de remplacer le nom du service, si jamais c’est votre cas).
Bien-sûr, cette partie n’entre pas directement en ligne de compte de la gestion DNS. Néanmoins, c’est important à prendre en compte car lors du renouvellement de certificat, il est nécessaire de regénérer les enregistrements TLSA - nous verrons ce point plus tard.
Voici pour l’exemple une zone DNS minimaliste, gérée par le serveur ns :
$TTL 1H
$ORIGIN domain.tld.
@ IN SOA domain.tld. dns.domain.tld. (
2022090101 ;
3H ; refresh
1H ; retry
2W ; expire
1H ; negative
)
@ IN NS ns1.domain.tld.
@ IN NS ns2.domain.tld.
@ IN A 46.23.90.29
IN AAAA 2a03:6000:6e65:619::29
; enregistrement CAA
@ IN CAA 0 iodef "mailto:mail@domain.tld"
@ IN CAA 0 issue "letsencrypt.org"
@ IN CAA 0 issuewild "letsencrypt.org"
www IN A 46.23.90.29
IN AAAA 2a03:6000:6e65:619::29
; TLSA
_443._tcp.domain.tld. IN TLSA 3 1 2 5c8fdd68178ce4cd8d88bd90b82a96df41674d555340b88283c24a0b3416aa375144cd6c16a58160ba3b168e59f5003bff656ce67cb24931b462fe4910bd62f5
En shell, générer un enregistrement TLSA n’est pas compliqué :
openssl x509 -noout -pubkey -in "${cert}" | openssl "${command}" -pubin -outform der 2>/dev/null | "${algo}" | tr "a-z" "A-Z"
Explications :
⇒ La commande ci-dessus nous permet de générer une variable intermédiaire
nommée tlsa_cert_associated
où :
$cert
est le nom du chemin absolu du certificat TLS serveur,
dans le système de fichier du serveur, lié au domaine cible.$command
est le nom de la commande utilisée par OpenSSL, soit
rsa
ou ec
(réciproquement pour les enregistrements selon le chiffrement
RSA ou ECDSA).$algo
est le nom de l’utilitaire sha256
, ou sha512
,
au choix personnel et restituera un condensé de message lié à
l’algorithme choisi.⇒ l’écriture relative à l’enregistrement TLSA est aussi simple :
tlsa_record="_${tls_port}._${tls_proto}.${domain}. IN TLSA ${tlsa_usage} ${tlsa_selector} ${tlsa_method} ${tlsa_cert_associated}"
où :
${tls_port}
est le numéro de port du serveur web utilisé, ici 443${tls_proto}
est le nom du protocole utilisé, ici tls${domain}
est le nom de domaine cible${tlsa_usage}
est le chiffre correspondant à la contrainte utilisée,
ici 3, correspondant à la contrainte DANE-EE, et recommandée
par Let’s Encrypt.${tlsa_selector}
est le chiffre correspondant au nom de sélecteur
utilisé, ici 1, correspondant au sélecteur SPKI, là aussi
recommandé par Let’s Encrypt.${tlsa_method}
étant la méthode utilisant l’algorithme de chiffrement
choisi ; ici SHA256, qui offre un niveau actuel de chiffrement
dit sécurisé et tout autant recommandé par Let’s Encrypt.tlsa_cert_associated
précédemment créée.Vérifier un enregistrement TLSA est un poil plus compliqué ; il faut :
dig
, pour l’exemple.openssl
qui va interroger
le certificat installé sur le serveur web utilisé, lié au nom de domaine
en question.tlsa="$(dig TLSA _443._tcp."${domain}" +short)"
d_tlsa="$(echo "${tlsa}" | awk '{ for(i=4;i<=NF;++i) printf "%s", tolower($i); print "" }')"
tlsa="$(echo | openssl s_client -servername "${domain}" -showcerts -connect "${domain}":443 2>/dev/null | openssl x509 -noout -pubkey | openssl pkey -outform der -pubin 2>/dev/null | openssl dgst -"${algo}" 2>/dev/null )"
o_tlsa="$(echo "${tlsa}" | awk -F'=' '{ print $2 }' | tr -d ' ')"
Pour finir, il suffit vraiment de comparer les deux variables shell
d_tlsa
et o_tlsa
pour savoir si elles correspondent, ce qui en temps
normal doit être le cas. Sauf en cas, de renouvellement de certificat
TLS, qui nécessitera donc de renouveller l’enregistrement TLSA, dans la
zone du nom de domaine en question, sur le serveur DNS.
Pour rappel, si cela n’est pas fait, une interrogation du serveur DNS sur le protocole DNSSEC générera une erreur puisque l’enregistrement TLSA ne correspondra pas un certificat web fraîchement utilisé, ou renouvellé, ce qui va entraîner cette conséquence : l’accès au serveur, lié au nom de domaine cible, sera impossible.
Il faudra donc générer un nouvel enregistrement TLSA correspondant au renouvellement du certificat TLS, puis régénerer la signature des enregistrements DNSSEC liés à la zone DNS du domaine cible.
Pour info, les scripts shell tlsa.sh, dns.conf, dns.ksh sont écrits dans un répertoire nommé dns-tools dans le répertoire personnel. À vous de voir où vous désirez les mettre, et modifier le script mensuel.
Voici la teneur de mon script shell monthly.local :
#!/bin/sh
### ldnscript
printf '%s\n' "=> ldnscript rollover"
/usr/local/sbin/ldnscript rollover all
### renew ssl by certbot
printf '%s\n' "=> renew letsencrypt certs"
/usr/local/bin/certbot renew --pre-hook "rcctl stop nginx" --post-hook "rcctl start nginx"
### check tlsa records for domain; only for tcp:443
for domain in "sub.domain.tld" "domain.tld" "www.domain.tld" "sub.domain2.tld" "domain2.tld" "www.domain2.tld"; do
printf '%s\n' "=> Test TLSA for ${domain}"
/home/-your-user-/dns-tools/tlsa.sh "${domain}"
done
(…)
Voici mon script shell nommé tlsa.sh :
#!/bin/sh
set -e
#set -x
########################################################################
#
# Author: Stéphane HUC
# mail: devs@stephane-huc.net
# gpg:fingerprint: CE2C CF7C AB68 0329 0D20 5F49 6135 D440 4D44 BD58
#
# License: BSD Simplified
#
# Github:
#
# Date: 2022/07/01 06:45
#
########################################################################
#
# Purpose: tool to test TLSA record
# - for the geek: DANE-TLSA...
#
# Needed tools: dig, openssl
#
# OS: Tested on OpenBSD, Devuan
#
########################################################################
###
##
# see: https://www.bortzmeyer.org/monitor-dane.html
##
###
########################################################################
ROOT="$(dirname "$(readlink -f -- "$0")")"
. "${ROOT}/dns.conf"
dir_admin="/home/-your-user-/dns-tools"
domain="$1"
### DO NOT TOUCH!
d_tlsa='' # TLSA record by dig
o_tlsa='' # TLSA record by openssl
tlsa_record='' # TLSA record
tlsa_method=2
########################################################################
####
##
# All needed functions! DO NOT TOUCH-IT!
##
###
########################################################################
byebye() {
mssg "KO" "Script stop here!"
mssg "KO" "Please, search to understand reasons."
exit 1
}
check_uid() {
if [ "$(id -u)" -ne 0 ]; then
mssg "KO" "ERROR: Script not launch with rights admin!"
byebye
fi
}
_dig() {
tlsa="$(dig TLSA _443._tcp."${domain}" +short)"
d_tlsa="$(echo $tlsa | awk '{ for(i=4;i<=NF;++i) printf "%s", tolower($i); print "" }')"
}
_openssl() {
tlsa="$(echo | openssl s_client -servername "${domain}" -showcerts -connect "${domain}":443 2>/dev/null | openssl x509 -noout -pubkey | openssl pkey -outform der -pubin 2>/dev/null | openssl dgst -"${algo}" 2>/dev/null )"
o_tlsa="$(echo $tlsa | awk -F'=' '{ print $2 }' | tr -d ' ')"
}
mssg() {
typeset statut info text
statut="$1" info="$2"
case "${statut}" in
"KO") text="[ ${red}${statut}${neutral} ] ${info}" ;;
"OK") text="[ ${green}${statut}${neutral} ] ${info}" ;;
#*) mssg="${text}" ;;
esac
printf "%s \n" "${text}"
unset info statut text
}
new_tlsa() {
cert="/etc/letsencrypt/live/${domain}/cert.pem"
case "${le_key_type}" in
"ecdsa")
tlsa_cert_associated="$(openssl x509 -noout -pubkey -in "${cert}" | openssl ec -pubin -outform der 2>/dev/null | "${algo}")"
;;
"rsa")
tlsa_cert_associated="$(openssl x509 -noout -pubkey -in "${cert}" | openssl rsa -pubin -outform der 2>/dev/null | "${algo}")"
;;
esac
tlsa_record="_${tls_port}._${tls_proto}.${domain}. IN TLSA ${tlsa_usage} ${tlsa_selector} ${tlsa_method} ${tlsa_cert_associated}"
unset tlsa_cert_associated
}
########################################################################
####
##
# Execution
##
###
########################################################################
if [ -z "${domain}" ]; then printf '%s\n' "[ KO ] Script stops here; no domain!"; exit; fi
_dig
_openssl
if [ "${d_tlsa}" = "${o_tlsa}" ]; then
mssg "OK" "Similar TLSA records! :D"
else
mssg "KO" "There seems to be a problem with the TLSA records of the domain: ${domain}!"
printf '%s\n' "Have you renew recently the TLS certs for the domain? If yes, change the TLSA record into the DNS zone relevent!"
printf '%s\n%s\n' "⇒ Perhaps, the dns.sh script shell can help you. ;-)"
check_uid
printf '%s\n' "⇒ Display new TLSA record:"
new_tlsa
printf '%s\n%s\n' "Add/modify tlsa into your DNS zone for ${domain}: " "${tlsa_record}"
printf '%s\n' "⇒ Modify TLSA record into the domain zone for ${domain}"
"${dir_admin}"/dns.ksh tlsa "${domain}"
fi
Modifiez la valeur de la variable dir_admin
!
Comme vous pouvez le remarquer :
tlsa
suivi du
nom de domaine à ciblerVoici le fichier de configuration qui sert à la fois pour le script shell tlsa.sh et le script pdksh dns.ksh.
########################################################################
#
# Author: Stéphane HUC
# mail: devs@stephane-huc.net
# gpg:fingerprint: CE2C CF7C AB68 0329 0D20 5F49 6135 D440 4D44 BD58
#
# License: BSD Simplified
#
# Github: https://framagit.org/hucste/AH.git
#
# Date: 2022/06/01 07:20
#
########################################################################
###
##
# Config file to dns.ksh script
##
###
########################################################################
### Algorithm
## values: sha256, sha512; choose-it segun TLSA Method
algo="sha256"
### SOA Serial type
## values: date, timestamp
## DNS recommandation: prefer date
SOA_serial_type="date"
### Port number
tls_port=443
### Protocols
## values: stcp, tcp, udp
tls_proto="tcp"
### TLSA
## Lets Encrypt Recommandation;
## see: https://community.letsencrypt.org/t/please-avoid-3-0-1-and-3-0-2-dane-tlsa-records-with-le-certificates/7022
## usage: Lets Encrypt recommands 3, at least 2
## values: 0 => 3; or (PKIX-TA, PKIX-EE, DANE-TA, DANE-EE; respectivly: 0 -> 3)
tlsa_usage=3
## selector: Lets Encrypt recommands 1
## values: 0 or 1; or (CERT, SPKI; respectively: O or 1)
tlsa_selector=1
## method: Lets Encrypt recommands 1
## values: 0 => 2; or (FULL, SHA256, SHA512; respectively: 0 -> 2)
# this change segun algo
tlsa_method=1
### Key Type Letsencrypt
## rsa or ecdsa
## if ecdsa, specify elliptic curve: secp256r1, secp384r1, secp512r1 (256 is enough)
le_key_type=ecdsa
le_curve=secp256r1
Personnellement, je fais le choix d’utiliser :
le_curve
.Ce script long et complexe est capable de :
debug
à 1
, ce qui activera la
journalisation des différentes étapes, et pourra aider à l’analyse,
lors d’une exécution manuelle.Un petit coup de ./dns.ksh help
vous en dira peut-être plus sur son utilisation. ;)
#!/bin/ksh
set -e
#set -x
################################################################################
#
# Author: Stéphane HUC
# mail: devs@stephane-huc.net
# gpg:fingerprint: CE2C CF7C AB68 0329 0D20 5F49 6135 D440 4D44 BD58
#
# License: BSD Simplified
#
# Github:
#
# Date: 2022/06/01 07:25
#
################################################################################
#
# Purpose: to add a TLSA Record into DNS zone, segun your cert TLS (LE)
# - for the geek: DANE-TLSA...
#### IMPORTANT: recreate your TLSA Record after (re?)new cert...
#
# Needed tools: nsd* and ldnscript
## ldnscript is a tool to sign dns zone. (DNSSEC)
## https://framagit.org/22decembre/ldnscripts.git
#
# OS: Tested on OpenBSD
#
################################################################################
ROOT="$(dirname "$(readlink -f -- "$0")")"
. "${ROOT}/dns.conf"
################################################################################
###
##
# DONT TOUCH THOSES VARIABLES!
##
###
################################################################################
debug=0
dir_le="/etc/letsencrypt/live"
dir_ns_cfg="/etc/ns" # folder config ns
dir_sbin="/usr/local/sbin"
log="${ROOT}/dns-script.log"
nsd_cfg="/var/nsd/etc/nsd.conf"
timestamp="$(date +%s)"
today="$(date +"%Y%m%d")"
server="nsd"
SOA_ns=""
tlsa_record=""
set -A tlsa_records # if X509 DNS Alternative Names > 1
set -A tlsa_method_names -- "FULL" "SHA256" "SHA512"
set -A tlsa_selector_names -- "CERT" "SPKI"
set -A tlsa_usage_names -- "PKIX-TA" "PKIX-EE" "DANE-TA" "DANE-EE"
NB_PARAMS="$#"
set -A PARAMS -- "$@"
ROOT="$(dirname "$(readlink -f -- "$0")")"
if [ -z "${PARAMS[0]}" ]; then MENU_CHOICE="help"
else
PARAMS[0]="$(printf '%s' "${PARAMS[0]}" | tr -s "[:upper:]" "[:lower:]")"
MENU_CHOICE=${PARAMS[0]}
fi
[ -n "${PARAMS[1]}" ] && domain="$(printf '%s' "${PARAMS[1]}" | tr -s "[:upper:]" "[:lower:]")"
################################################################################
####
##
# All needed functions! DO NOT TOUCH-IT!
##
###
################################################################################
_add_tlsa() {
check_var_algo
check_var_soa_serial_type
check_var_tls_port
check_var_tls_proto
check_tlsa_methods
check_tlsa_selectors
check_tlsa_usages
get_soa_ns
danefile="${zonefile}.dane"
newzonefile="${zonefile}.${today}"
oldzonefile="${zonefile}.${OLD_SOA_sn}"
create_new_filezone
if [ -f "${newzonefile}" ]; then
write_soa_serial_number
build_tlsa_record
write_tlsa_record
mv_new_file_zone
if _resign; then del_old_zonefile; fi
fi
unset danefile newzonefile oldzonefile
}
build_needed_variables() {
check_var_domain
printf '%s\n' "*** Build needed variables:"
# build cert variable if menu 'tlsa'
if [ "${MENU_CHOICE}" = "tlsa" ]; then
cert="${dir_le}/${domain}/cert.pem"
if [ ! -f "${cert}" ]; then
display_mssg "KO" "*** It seems cert file not exists!"
byebye
else
printf '%s\n' "cert: ${cert}"
fi
fi
# build zonedir and zonefile variables
zonedir="$(awk -F '"' '/zonesdir/ { print substr($2,-1) }' "${nsd_cfg}")"
if [ -z "${zonedir}" ]; then zonedir="/var/nsd/zones/"; fi
printf '%s\n' "zonedir: ${zonedir}"
#zonefile="$(awk -F '"' '/zonefile: "[a-z]*\/'"${domain}"'"/ { print substr($2, -1) }' "${nsd_cfg}")"
#if [ "$(printf '%s' "${zonefile}" | awk -F'/' '{ print $1}')" == "signed" ]; then
##zonefilesigned=$zonefile
#zonefile="$(find "${dir_ns_cfg}" -name "${domain}")"
#if [ -z "${zonefile}" ]; then zonefile="$(find "${zonedir}" -name "${domain}")"; fi
#if [ -z "${zonefile}" ]; then
#display_mssg "KO" "ERROR: It seems zonefile for domain: '${domain}' not exists!"
#byebye
#fi
#else
#zonefile="${zonedir}${zonefile}"
#fi
zonefile="${dir_ns_cfg}/${domain}"
printf '%s\n' "zonefile: ${zonefile}"
}
build_tlsa_record() {
# get TLSA by reading cert pem
case "${le_key_type}" in
"ecdsa")
command="ec"
;;
"rsa")
command="rsa"
;;
esac
tlsa_cert_associated="$(openssl x509 -noout -pubkey -in "${cert}" | openssl "${command}" -pubin -outform der 2>/dev/null | "${algo}")"
_log "TLSA Cert Associated: ${tlsa_cert_associated}"
unset command
if [ -z "${tlsa_cert_associated}" ]; then
display_mssg "KO" "ERROR: TLSA Cert Associated could not generated!"
byebye
else
# rebuild tlsa method segun algo choosed; possible: 0 (no match), 1 (sha256), 2 (sha512)
case "${algo}" in
"sha256") tlsa_method=1 ;;
"sha512") tlsa_method=2 ;;
*) tlsa_method=0 ;;
esac
if [ "${tls_port}" = "443" ] && [ "${tls_proto}" = "tcp" ]; then
get_dns_alternative_names
count="${#domains[@]}"
if [ "${count}" -eq 1 ]; then
set_tlsa_record
else
set_tlsa_records
fi
fi
fi
unset tlsa_cert_associated
}
byebye() {
display_mssg "KO" "Script stop here!"
display_mssg "KO" "Please, search to understand reasons."
exit 1
}
check_domain_name() {
pattern="^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$" # like RFC 1123
if [ ${#domain} -gt 67 ]; then # Larg domain name <= 67
display_mssg "KO" "Error: Domain Length: ${domain}; >= 67 carachters!"
byebye
fi
if printf '%s\n' "${domain}" | grep -Eio "${pattern}"; then
display_mssg "OK" "Domain Name: ${domain} is valid!"
sleep 1
else
display_mssg "KO" "Error: Bad Domain Name: ${domain}"
byebye
fi
unset pattern
}
check_tlsa_methods() {
case "${tlsa_method}" in
0|"FULL") tlsa_method=0 ;;
1|"SHA256") tlsa_method=1 ;;
2|"SHA512") tlsa_method=2 ;;
*)
display_mssg "KO" "/!\ The TLSA Method: not correctly configurated!"
byebye
::
esac
_log "TLSA Method: ${tlsa_method}"
}
check_tlsa_selectors() {
case "${tlsa_selector}" in
0|"CERT") tlsa_selector=0 ;;
1|"SPKI") tlsa_selector=1 ;;
*)
display_mssg "KO" "/!\ The TLSA Selector: not correctly configurated!"
byebye
;;
esac
_log "TLSA Selector: ${tlsa_selector}"
}
check_tlsa_usages() {
case "${tlsa_usage}" in
0|"PKIX-TA") tlsa_usage=0 ;;
1|"PKIX-EE") tlsa_usage=1 ;;
2|"DANE-TA") tlsa_usage=2 ;;
3|"DANE-EE") tlsa_usage=3 ;;
*)
display_mssg "KO" "/!\ The TLSA Usage: not correctly configurated!"
byebye
;;
esac
_log "TLSA Usage: ${tlsa_usage}"
}
check_uid() {
if [ "$(id -u)" -ne 0 ]; then
display_mssg "KO" "ERROR: Script not launch with rights admin!"
byebye
fi
}
check_var_algo () {
if [ "${algo}" != "sha256" ] && [ "${algo}" != "sha512" ]; then
display_mssg "KO" "/!\ Algorythm: not correctly configurated!"
byebye
fi
_log "Algo: ${algo}"
}
check_var_domain() {
if [ -z "${domain}" ]; then
display_mssg "KO" "*** It seems fault informations!"
help
byebye
fi
_log "Domain: ${domain}"
}
check_var_soa_serial_type() {
if [ "${SOA_serial_type}" != "date" ] && [ "${SOA_serial_type}" != "timestamp" ]; then
display_mssg "KO" "/!\ SOA Serial Type: not correctly configurated!"
byebye
fi
_log "SOA Serial Type: ${SOA_serial_type}"
}
check_var_tls_port(){
if [ "${tls_port}" -lt 0 ]; then
display_mssg "KO" "/!\ TLS port: not correctly configurated!"
byebye
fi
_log "TLS port: ${tls_port}"
}
check_var_tls_proto() {
if [ "${tls_proto}" != "sctp" ] && [ "${tls_proto}" != "tcp" ] && [ "${tls_proto}" != "tcp" ]; then
display_mssg "KO" "/!\ TLS proto: not correctly configurated!"
byebye
fi
_log "TLS proto: ${tls_proto}"
}
checkconf() {
nsd-checkconf "${nsd_cfg}"
}
checkzone() {
nsd-checkzone "${domain}" "${zonefile}"
}
confirm () {
read -r response?"${1} [y|n] "
case "${response}" in
# 'o', 'O': Oui and not 0!
y|Y|o|O|1) true ;;
*) false ;;
esac
unset response
}
create_new_filezone() {
cp "${zonefile}" "${newzonefile}"
}
del_old_zonefile() {
if [ -f "${oldzonefile}" ]; then
rm -fP "${oldzonefile}"
fi
}
display_mssg() {
typeset statut info text
statut="$1" info="$2"
case "${statut}" in
"KO") text="[ ${red}${statut}${neutral} ] ${info}" ;;
"OK") text="[ ${green}${statut}${neutral} ] ${info}" ;;
#*) mssg="${text}" ;;
esac
printf "%s \n" "${text}"
unset info statut text
}
get_dns_alternative_names() {
# get "X509 DNS Alternative Names" characters
domains="$(echo | openssl x509 -text -noout -in "${cert}" | awk -F ',' '/DNS:/ { for(i=1;i<NF;i++) { p=match($i,":"); print substr($i,p+1) }}')"
# convert into array; no double-quotes, else not run!
set -A domains -- ${domains[@]}
printf '%s\n' "domains: ${domains[*]}"
_log "domains: ${domains[*]}"
}
get_soa_ns() {
OLD_SOA_sn="$(grep -A1 "SOA" "${zonefile}" | tail -n1 | awk -F ' ' '{ print $1 }')"
_log "Old SOA Serial Number: ${OLD_SOA_sn}!"
}
get_soa_serial_number() {
OLD_SOA_sn="$(printf '%s\n' "${line}" | awk -F ' ' '{ print $1 }')"
_log "OLD SOA Serial Number: ${OLD_SOA_sn}"
}
help() {
printf '%s\n' "
$0 sign domain # to sign a domain
$0 tlsa domain # to add a tlsa record into domain zone
----
when use tlsa, this script will resign the domain zone...
"
}
init_zone() {
"${dir_sbin}"/ldnscript init "${domain}"
}
in_array() {
local i=0 need="$1" IFS=" "; shift; set -A array -- $*
count="${#array[@]}"
while [ $i -le $count ]; do
if [ "${array[$i]}" = "${need}" ]; then return 0; fi # true
#let "i=$i+1"
(( i=i+1 ))
done
return 1
unset i need IFS array
}
_log() {
if [ "${debug}" -eq 1 ]; then printf '%s\n' "$1" >> "${log}"; fi
}
main() {
check_uid
verify_need_softs
build_needed_variables
check_domain_name
case "${MENU_CHOICE}" in
"help") help ;;
"sign") _resign ;;
"tlsa") _add_tlsa ;;
*)
display_mssg "KO" "ERROR: this option ${MENU_CHOICE} is not exists!"
help
byebye
;;
esac
}
mv_new_file_zone() {
if [ -f "${newzonefile}" ]; then
mv "${zonefile}" "${oldzonefile}"
mv "${newzonefile}" "${zonefile}"
fi
}
_resign() {
if checkzone && checkconf; then
display_mssg "OK" "file config nsd and zone ${domain} are good! :D"
sign_zone
else
display_mssg "KO" "ERROR: it exists a problem with file config nsd or zone ${domain}"
byebye
fi
}
restart_server() {
printf '%s\n' "=> Restart Server: "
stop_server
start_server
status_server
}
set_soa_serial_number() {
case "${SOA_serial_type}" in
"date")
SOA_date="$(printf '%s' "${OLD_SOA_sn}" | awk '{print substr($0, 0, 8)}')";
SOA_number="$(printf '%s' "${OLD_SOA_sn}" | awk '{print substr($0, 9)}')";
if [ "${SOA_date}" == "${today}" ]; then
#let SOA_number=$SOA_number+1
(( SOA_number=${SOA_number}+1 )) || true
if [ "${SOA_number}" -lt 10 ]; then SOA_number="0${SOA_number}"; fi
SOA_sn="${SOA_date}${SOA_number}"
else
SOA_sn="${today}01"
fi
;;
"timestamp")
SOA_sn="${timestamp}"
;;
*)
display_mssg "KO" "Invalid SOA Serial Type!"
byebye
;;
esac
_log "New SOA Serial Number: ${SOA_sn}!"
}
set_tlsa_record() {
# build tlsa record
tlsa_records[0]="_${tls_port}._${tls_proto}.${domains[0]}. IN TLSA ${tlsa_usage} ${tlsa_selector} ${tlsa_method} ${tlsa_cert_associated}"
_log "TLSA Record: ${tlsa_records[0]}"
}
set_tlsa_records() {
# do not use domain variable here
i=0
for dom in "${domains[@]}"; do
tlsa_records[$i]="_${tls_port}._${tls_proto}.${dom}. IN TLSA ${tlsa_usage} ${tlsa_selector} ${tlsa_method} ${tlsa_cert_associated}"
(( i=i+1 ))
done
unset i dom
_log "TLSA Records: ${tlsa_records[*]}"
}
sign_zone() {
"${dir_sbin}"/ldnscript signing "${domain}"
}
start_server() {
printf '%s\n' "Start serveur: ${server}"
rcctl start "${server}"
sleep 1s
}
status_server() {
printf '%s\n' "Check serveur: ${server}"
rcctl check "${server}"
}
stop_server() {
printf '%s\n' "Stop serveur: ${server}"
rcctl stop "${server}"
sleep 1s
}
verify_need_softs() {
if [ ! -f "${dir_sbin}/ldnscript" ]; then
display_mssg "KO" "ERROR: ldnscript seems not install!"
byebye
elif [ ! -x "${dir_sbin}/ldnscript" ]; then
display_mssg "KO" "ERROR: ldnscript is not executable!"
byebye
fi
}
write_soa_serial_number() {
set_soa_serial_number
if sed -i -e "s#\(.*\)${OLD_SOA_sn} \;#\1${SOA_sn} \;#" "${newzonefile}"; then
_log "SOA serial number changed!"
else
display_mssg "KO" "/!\ Script cant change SOA serial number!"
fi
}
write_tlsa_record() {
if [ ! -f "${danefile}" ]; then touch "${danefile}"; fi
i=0
# add tlsa records into dns zone
for tlsa_record in "${tlsa_records[@]}"; do
dom="${domains[$i]}"
_log "domain: $dom"
### /!\ ERROR with $domain /!\
if sed -i -e "s#_${tls_port}._${tls_proto}.${dom}. IN TLSA\(.*\)#${tlsa_record}#" "${newzonefile}"; then
_log "TLSA Record rewrited!"
else
printf '%s\n' "${tlsa_record}" >> "${newzonefile}"
_log "TLSA Record added!"
fi
(( i=i+1 ))
# add record in first line into dane file
printf '%s\n' "${timestamp}:${tlsa_record}" >> "${danefile}"
_log "${timestamp}:${tlsa_record}"
unset dom
done
unset i tlsa_record
}
################################################################################
main
End Of Documentation
Voilà mon processus de gestion de mes zones DNS, avec le protocole DNSSEC et les enregistrements TLSA pour le service web.
D’un processus long et complexe, je peux ainsi gérer simplement à l’aide de deux commandes bien utiles :
./dns.ksh sign domain
./tlsa.sh domain
Mais si vous avez bien compris, c’est le cron mensuel qui s’en occupe tout seul et qui me fait le rapport adéquat, ainsi je sais comment cela s’est exécuté.
Cet article devrait vous permettre d’utiliser la partie des scanners, pour votre imprimante multi-fonctions, appelée MFP .
Les logiciels suivants sont disponibles depuis le site web officiel de téléchargement d’Epson - http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX :
Une fois installé, vous le retrouverez à-partir du menu “Applications” > “Graphisme”.
Deux pilotes seront utilisés, selon votre imprimante MFP :
Ce pilote concerne principalement les imprimantes MFP suivantes :
Passons à l’installation et la configuration d’Image Scan v2 … Il est possible que ces imprimantes puissent utiliser la v3 , aussi !
Le pilote Utsushi est un nouveau pilote en cours d’écriture.
Le dépôt officiel : https://gitlab.com/utsushi/utsushi
Il est prévu à certain terme l’intégration dans le projet Sane, mais il est actuellement considéré en tant que “External Backend”. http://www.sane-project.org/lists/sane-backends-external.html#S-UTSUSHI
Ce pilote concerne principalement les imprimantes MFP suivantes :
Ne pas hésitez à chercher avec une version supérieure, ainsi :
Mettre un tiret entre les deux, tel que ET-3700. Faire une recherche avec un espace échouera !
Etc.
Maintenant, passons à l’installation soit, à partir :
Actuellement à la version 6.6.40, ce logiciel est très simple d’utilisation.
La version 6 est disponible à partir de cette URL : http://support.epson.net/linux/en/epsonscan2.php
Une fois téléchargée, décompressez-la ; dirigez-vous dans le répertoire nommé
“epsonscan2-bundle-6.6.40.0.x86_64.deb” puis exécutez le script install.sh
,
avec les droits administrateurs.
$ epsonscan2-bundle-6.6.40.0.x86_64.deb
# ./install.sh`
Lors de la première fois, une première fenêtre “Ajouter un scanner réseau” s’ouvre et demande de restituer l’adresse IP de votre MFP.
Puis cliquez sur le bouton [ Ajouter ] qui se sera activé, suivi d’un clic sur le bouton [ OK ].
Il n’y a plus qu’à l’utiliser, voire à modifier quelques paramètrages, à vos besoins. Les boutons [ Aperçu ] et [ Numériser ] sont en bas.
Il est nécessaire d’avoir le package xsltproc
installé dans le système…
Si ce n’est pas fait, faites-le !
Le nom du driver utilisé n’est ni epson, ni epson2, mais bel et bien epkowa ! Pensez-y, avant de modifier tout fichier de configuration, surtout relative aux fonctions réseaux.
Pour ce qui est d’utiliser la partie scanner de votre imprimante, il faut encore aller piocher directement sur leur site.
C’est une archive complète nommée iscan-bundle-1.0.0.x64.deb.tar.gz
.
Une fois téléchargée, décompressez-la ; dirigez-vous dans le répertoire nommé “iscan-bundle-1.0.0.x64.deb”, puis exécutez le script install.sh
, avec les droits administrateurs.
$ cd iscan-bundle-1.0.0.x64.deb
# ./install.sh
Il est probable qu’il faille modifier le fichier de configuration /etc/sane.d/dll.conf
,
afin d’ajouter le nom du pilote epkowa
.
Modifiez le fichier de configuration /etc/sane.d/epkowa.conf
pour ajouter :
usb 0x04b8 0xProductID
lsusb | grep "04b8"
: pour connaître l’identifiant produit ProductID
relatif à votre matérielnet adr_ip 1865
(où adr_ip est l’adresse
ip, relative au MFP)Exemple de fichier /etc/sane.d/epkowa.conf
:
# epkowa.conf -- sample configuration for the EPKOWA SANE backend
# Copyright (C) 2004, 2008, 2009 Olaf Meeuwissen
#
# See sane-epkowa(5), sane-usb(5) and sane-scsi(5) for details.
# Detect all devices supported by the backend.
# If you don't have a SCSI device, you can comment out the "scsi"
# keyword. Similarly for the other keywords.
#
usb
scsi
# For any USB scanner not known to the backend (yet), you may, at your
# own peril(!!), force the backend to recognise and use it via libusb.
# You can do so by the following configuration command:
#
# usb <USB vendor ID> <USB product ID>
#
# SEIKO EPSON's USB vendor ID is '0x04b8' (without quotes). In order
# to find the USB product ID, use lsusb(1).
# A sample configuration for the Epson Perfection 1650 (Epson GT-8200),
# which has a product ID of 0x0110, would look as follows:
#
#usb 0x04b8 0x0110
# For SCSI devices not detected, you can add an entry like:
#
# scsi EPSON GT-20000
#
# where the GT-20000 bit corresponds to the SCSI model information as
# shown in the output of dmesg(1) or in the /var/log/kern.log file.
# Network attached devices may be made to work by first installing the
# (non-free) iscan-network-nt package and then adding configuration lines
# as per information below.
#
# For each network attached device, you must add an entry as follows:
#
# net <IP-address|hostname> [port-number]
#
# Ask your network administrator for the device's IP address or check
# for yourself on the panel (if it has one). The port-number is very
# optional and defaults to 1865.
# Note that network attached devices are not queried unless configured
# in this file.
#
# Examples:
#
#net 192.16.136.2 1865
#net 10.0.0.1
#net scanner.mydomain.com
# Some backend behaviour can be customized by using the option keyword
# followed by an option name, as shown below.
#
# option <option-name>
#
# Currently available options:
#
# Makes the automatic document feeder the default document source
#option prefer-adf
La version 3 est disponible à partir de cette URL : http://support.epson.net/linux/en/imagescanv3.php
Une fois téléchargée, décompressez-la ; dirigez-vous dans le répertoire
nommé “imagescan-bundle-debian-10-3.65.0.x64.deb.tar.gz”, puis exécutez le script install.sh
, avec les droits administrateurs.
$ cd imagescan-bundle-debian-10-3.65.0.x64.deb.tar.gz
# ./install.sh
Le fichier de configuration principal sera/est : /etc/imagescan/imagescan.conf
.
Son écriture peut encore évoluée, néanmoins voici un exemple de configuration
actuelle :
# /etc/imagescan/imagescan.conf -- Image Scan configuration
# Refer to the documentation for details on the configuration options
# for the software. Plugins should come with their own documentation
# if they have configuration options.
#
# Lines starting with a # or a ; are comments. Comments must be on a
# line of their own. End-of-line comments are not supported.
[devices]
myscanner.udi = esci:networkscan://adresse-ip:1865
myscanner.vendor = Epson
myscanner.model = EcoTank ET-3700
Explications :
myscanner.udi
est le nom de l’interface utilisée. Dans cette exemple,
c’est l’interface réseau qui est interrogée.myscanner.vendor
et myscanner.model
sont des chaînes de caractères,
totalement arbitraires, à renseigner à votre convenance.Epson fournit de la documentation, en anglais, pour aider à configurer le logiciel :
=> Epson Scan :
=> Image Scan.
V’Ger est le projet de serveur de publication sur le protocol Gemini, écrit en C. Écrit pour OpenBSD, il bénéficie des mesures de protections, liées à pledge(4) et unveil(4).
Dans cet article, nous aborderons l’installation et la configuration de ce service. Puis nous verrons comment configurer relayd ou nginx en tant que proxy relais ; et nous finirons par quelques règles pour Packet-Filter.
OpenBSD : 6.9 → 7.4
Puisque V’Ger est disponible dans les ports, installez le paquet vger.
Autrement vous pouvez toujours l’installer depuis le dépôt Git… mais là, je vous renvoie à la documention du dépôt.
Pré-requis :
Créons en tout premier un utilisateur dédié, nommé _vger :
$ doas useradd -d /var/gemini -s /sbin/nologin _vger
(dans la documentation officielle, le nom de l’utilisateur est _gemini).
Il nous faut créer le répertoire /var/gemini
puis appliquer les droits
à l’utilisateur dédié :
$ doas mkdir -p /var/gemini/nom_domaine
$ doas chown -R _vger /var/gemini
/etc/inetd.conf
Le service inetd est chargé de l’écoute active sur l’interface localhost puis appelle le binaire vger pour délivrer le contenu.
Configurons maintenant le service inetd :
1965 stream tcp nowait _vger /usr/local/bin/vger vger -d /var/gemini -v
1965 stream tcp6 nowait _vger /usr/local/bin/vger vger -d /var/gemini -v
vger
.⇒ activons et démarrons le service :
$ doas rcctl enable inetd && doas rcctl start inetd
Cet article ne présente pas comment obtenir les certificats SSL, mais vous pouvez les obtenir, soit depuis le client acme secure, natif sous OpenBSD, soit à partir du paquet certbot.
En premier, il semble nécessaire de créer le répertoire private
dans /etc/ssl
.
$ doas mkdir -p /etc/ssl/private
La documentation officielle informe de lier les certificats SSL, générés par le client sécurisé acme sous OpenBSD.
Si c’est votre cas :
$ doas ln -s /etc/ssl/acme/cert.pem /etc/ssl/nom_domaine.crt
$ doas ln -s /etc/ssl/acme/private/privkey.pem /etc/ssl/private/nom_domaine.key
Dans mon contexte de serveur, les certificats sont générés par le client certbot, disponible officiellement dans les ports. Une fois les certificats générés par certbot, les liens symboliques à créer sont de cette forme :
$ doas ln -s /etc/letsencrypt/live/nom_domaine/cert.pem /etc/ssl/nom_domaine.crt
$ doas ln -s /etc/letsencrypt/live/nom_domaine/privkey.pem /etc/ssl/private/nom_domaine.key
/etc/relayd.conf
- chmod 0600 !relayd est le service de relais-proxy natif sous OpenBSD.
La configuration du service relayd peut se faire ainsi - dans cet exemple, à la fois pour Ipv4|6 - :
log connection
table <localhost> { 127.0.0.1, ::1 }
tcp protocol "gemini" {
tls keypair nom_domaine
}
relay "gemini" {
listen on nom_domaine port 1965 tls
protocol "gemini"
forward to <localhost> port 1965
}
⇒ Vérification de la configuration :
$ doas relayd -n
host_dns: nom_domaine resolves to more than 1 hosts
configuration OK
⇒ activons et démarrons le service :
$ doas rcctl enable relayd && doas rcctl start relayd
/etc/nginx.conf
nginx peut lui aussi servir de proxy relais, en lieu et place de relayd ; mais il est nécessaire d’installer en plus le paquet nginx-stream.
Puis il faut modifier la configuration pour y ajouter, en début de fichier,
avant la directive http
:
load_module "modules/ngx_stream_module.so";
Ensuite, il est nécessaire de rajouter les déclarations suivantes en utilisant
la directive stream
:
stream {
log_format basic '$remote_addr $upstream_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time';
access_log logs/nom_domaine/access.gemini.log basic;
upstream backend_ipv4 {
hash $remote_addr consistent;
server 127.0.0.1:1965;
}
upstream backend_ipv6 {
hash $remote_addr consistent;
server [::1]:1965;
}
map $server_addr $backend {
addresse_ipv4 backend_ipv4;
addresse_ipv6 backend_ipv6;
}
server {
listen addresse_ipv4:1965 ssl;
listen [addresse_ipv6]:1965 ssl;
ssl_certificate /etc/letsencrypt/live/nom_domaine/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nom_domaine/privkey.pem;
ssl_ciphers TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:TLS-AES-128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_ecdh_curve X25519:P-521:P-384:P-256;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.3 TLSv1.2;
proxy_pass $backend;
}
}
Quelques petites explications :
en rapport avec les directives listen
, si vous ne déclarez pas l’adresse
IP correspondante, tel que listen 1965 ssl;
, il faudra impérativement
rediriger le port sur un autre numéro de port puis reconfigurer inetd.conf
pour qu’il écoute sur ce même autre numéro de port. En effet, si l’adresse
IP d’écoute n’est pas spécifiée dans la directive listen
, nginx cherchera
à écouter sur toutes les interfaces réseaux configurées et ne pourra redémarrer
car inetd écoute déjà sur l’interface localhost.
deux directives upstream
sont déclarées, chacune pour gérer correctement
le protocole IPv4 ou IPv6, et sont mappées pour n’avoir qu’un seul proxy
à appeler.
un dernier mot, concernant les directives ssl_ciphers
, ssl_ecdh_curve
,
ssl_prefer_server_ciphers
, et ssl_protocols
, elles ne sont pas strictement
nécessaires mais utiles pour renforcer les préférences d’utilisation.
ssl_protocols
permet de prioriser la version de TLS, sachant que :
Servers MUST use TLS version 1.2 or higher and SHOULD use TLS version 1.3 or higher.
Voici un exemple de règles minimalistes à ajouter à PF :
host = adresse_ipv4
host6 = adresse_ipv6
pass in quick on egress proto tcp from any to { $host $host6 } port 1965
Pensez à recharger le jeu de règles par PF :
$ doas pfctl -f /etc/pf.conf
Voilà !
Il ne vous reste plus qu’à créer votre premier fichier index.gmi
et les
suivants et les déposer dans le répertoire correspondant à votre répertoire
de publication… en n’oubliant pas de poser les droits de l’utilisateur
dédié dessus.
Mais qui surveille ?
⇒ L’activité est enregistrée dans les deux logs ‘daemon’ et ‘messages’.
$ grep vger /var/log/messages
May 1 10:54:28 sh1 useradd[86659]: new group added: name=_vger, gid=1011
May 1 10:54:28 sh1 useradd[86659]: new user added: name=_vger, uid=1011, gid=1011, home=/var/gemini, shell=/sbin/nologin
May 1 12:09:53 sh1 vger: request gemini://huc.fr.eu.org/
May 1 13:00:59 sh1 vger: request gemini://huc.fr.eu.org/
⇒ Il est possible de surveiller l’activité de l’utilisateur _vger avec - mais dans ce cas, franchement peu utile :
top -U _vger
fstat -u _vger -n
ps aux -U _vger
⇒ Pour vérifier que le service inetd écoute en local, il est possible de lui envoyer la requête suivante :
$ printf '%s\r\n' "gemini://huc.fr.eu.org" | vger -v -d /var/gemini
20 text/gemini;
# huc.fr.eu.org|gemini
(…)
telnet: Unable to connect to remote host: Connection refused
,
c’est certainement soit que le service inetd
ne peut répondre - est-il
actif ? ou qu’il y a un problème dans sa configuration. Vérifiez !⇒ Vérifier que le port 1965 soit ouvert en écoute sur vos adresses IP :
$ netstat -an | grep 1965
tcp 0 0 *.1965 *.* LISTEN
tcp 0 0 46.23.90.29.1965 *.* LISTEN
tcp6 0 0 2a03:6000:6e65:6.1965 *.* LISTEN
tcp6 0 0 *.1965 *.* LISTEN
⇒ Pour finir, vous pouvez vérifier avec l’outil telnet
sur le port 1965,
en local et depuis une autre machine que le service écoute.
man 8 vger
/usr/local/share/doc/pkg-readmes/vger
iblock est un logiciel dont le but est de détecter des connexions TCP, sur des ports précis, afin de bloquer les adresses IP correspondantes par le biais du parefeu Packet Filter, sous OpenBSD.
Le service inetd est chargé de l’écoute active.
Commençons par la copie du dépôt Git :
$ git clone https://tildegit.org/solene/iblock.git
$ cd iblock
Compilons le binaire - OpenBSD renferme nativement les outils adéquats - :
$ doas make
cc -o iblock main.c
; vérifions la présence du binaire
$ ls -al iblock
-rwxr-xr-x 1 root moi 8496 Apr 10 12:23 iblock*
Si la phase de compilation s’exécute mal, contactez Solène !
Solène n’a pas créé la cible “install”, donc copions le binaire dans le répertoire cible :
$ doas cp iblock /usr/local/bin/
$ ls -al /usr/local/bin/iblock
-rwxr-xr-x 1 root wheel 8496 Apr 10 12:26 /usr/local/bin/iblock*
Passons maintenant à la phase de configuration !
Créons en tout premier un utilisateur dédié, nommé _iblock :
$ doas useradd -s /sbin/nologin _iblock
/etc/doas.conf
Ajoutons la règle suivante dans le fichier de configuration de doas
pour
autoriser l’utilisateur dédié à utiliser l’outil pfctl
:
permit nopass _iblock cmd /sbin/pfctl
/etc/inetd.conf
Configurons maintenant le service inetd :
666 stream tcp nowait _iblock /usr/local/bin/iblock iblock blocked_tcp
666 stream tcp6 nowait _iblock /usr/local/bin/iblock iblock blocked_tcp
iblock
.Et activons et démarrons le service :
$ doas rcctl enable inetd && doas rcctl start inetd
En premier, créons un fichier de “secours” pour rendre la future table dans PF persistante à l’extinction et au redémarrage du serveur :
# touch /etc/pf-blocked_tcp.txt
Puis créons/modifions le fichier /etc/rc.shutdown
pour y ajouter :
pfctl -t blocked_tcp -T show > /etc/pf-blocked_tcp.txt
Voici un exemple de règles à ajouter à PF :
block_tcp_ports = "{ 21 23 111 135 137:139 445 1433 3306 3389 5432 6000:6010 7890 9999 25565 27019 }"
table <blocked_tcp> persist file "/etc/pf-blocked_tcp.txt"
### iblock: block all in table
block in quick from <blocked_tcp> label iblock
### iblock: redirect to inetd service on localhost
pass in quick on egress inet proto tcp to port $block_tcp_ports rdr-to 127.0.0.1 port 666
pass in quick on egress inet6 proto tcp to port $block_tcp_ports rdr-to ::1 port 666
Pensez à faire recharger le jeu de règles par PF :
$ doas pfctl -f /etc/pf.conf
Mais qui surveille ?
⇒ L’activité est enregistrée dans les deux logs ‘daemon’ et ‘messages’.
$ grep iblock /var/log/messages
Apr 10 12:26:38 sh1 iblock: blocking 46.23.148.71
Apr 10 12:30:28 sh1 iblock: blocking 180.225.98.236
Apr 10 12:31:48 sh1 iblock: blocking 46.23.157.246
Apr 10 12:32:43 sh1 iblock: blocking 95.57.218.103
Apr 10 12:36:00 sh1 iblock: blocking 103.89.91.158
Apr 10 12:38:41 sh1 iblock: blocking 23.128.248.41
⇒ De même, l’outil pfctl
peut nous montrer les différentes adresses IP
enregistrées dans la table, gérée par PF :
$ doas pfctl -t blocked_tcp -T show
23.128.248.41
46.23.148.71
46.23.157.246
95.57.218.103
103.89.91.158
180.225.98.236
voire de l’utiliser pour connaître les statistiques liées - pour comprendre ces informations, merci de lire le manpage de l’outil pour connaître la signification du colonnage :
$ doas pfctl -sl | grep iblock
iblock 44666 1188 58504 1188 58504 0 0 0
⇒ Il est possible de surveiller l’activité de l’utilisateur _iblock avec - mais dans ce cas, franchement peu utile :
top -U _iblock
fstat -u _iblock -n
ps aux -U _iblock
Si vous souhaitez obtenir des statistiques avec munin , Solène m’a fournit un script, à exécuter avec les droits de l’utilisateur _munin, tel que :
#!/bin/sh
if [ "$1" = "config" ]; then
echo "graph_title Banned IP absolute number"
echo "graph_vlabel gauge"
echo "a1.label value"
exit 0
fi
printf "a1.value "
doas /sbin/pfctl -t blocked_tcp -T show | sort -n -u | awk 'END { print NR }'
Ce qui nécessite de modifier la configuration de doas
pour autoriser l’utilisateur _munin à utiliser l’outil pfctl
, tel que :
# iblock: auth _munin-plugin to use pfctl
permit nopass _munin-plugin cmd /sbin/pfctl args -t blocked_tcp -T show
Ci-dessous, voici une image de statistiques d’adresses IP bloquées, restituée par Solène, en date du 10/04/2022 :
Dans les logs ‘daemon’ et ‘messages’, vous retrouvez le message suivant :
inetd[69849]: execv /usr/local/bin/iblock: No such file or directory
Assurez-vous d’avoir compiler puis copier le binaire iblock dans le répertoire en question !
Voilà !
sshlockout est un petit outil logiciel bien pratique pour surveiller les connexions sur le service SSH. Il gardera une trace des tentatives de connexions par des utilisateurs inconnus aussi bien que des erreurs d’authentification.
Au bout de 5 tentatives sur une période d’une heure, une entrée permanente est ajoutée à la table associée aux adresses IP par pf(4).
En deux, trois minutes d’installation et de configuration, voici un système de surveillance, géré avec le parefeu, efficace et fonctionnel !
Installez le paquet sshlockout.
Il faut ajouter/modifier vos règles du parefeu Packet-Filter :
table <lockout> persist
block in quick on egress proto tcp from <lockout> to port ssh
Il est nécessaire de modifier le fichier de configuration /etc/syslog.conf
,
en ajoutant la déclaration suivante :
auth.info;authpriv.info | exec /usr/bin/doas -n /usr/local/sbin/sshlockout -pf "lockout"
Pour finir, il faut ajouter une tâche cron, pour libérer les adresses IP de la table lockout, dont l’enregistrement est vieux de plus d’un jour.
Le manpage officiel informe de mettre dans la cron-table de root :
3 3 * * * pfctl -t lockout -T expire 86400
Personnellement, je préfère ajouter à mon fichier daily.local, l’écriture suivante :
## sshlockout: expire IP
pfctl -t lockout -T expire 84600
printf '%s\n' "=> Nb IPs into lockout table:"
pfctl -t lockout -T show | wc -l
ce qui libére les adresses IP enregistrées depuis une journée, et me restitue dans le mail quotidien le nombre d’IP enregistrées dans la table.
Voilà !
man 8 sshlockout
SSHFS permet de monter un répertoire à distance dans une connexion ssh normale.
Installez
le
paquet sshfs-fuse
.
kern.usermount
-
[sysctl(3)]http://man.openbsd.org/OpenBSD-5.9/man3/sysctl.3) - n’est
plus gérée… d’où la nécessité d’utiliser des droits d’administration, tel
que par doas(1) !Pour monter, un répertoire à distance, depuis une machine faisant fonctionner le service SSH, sur votre station :
$ doas sshfs -o compression=yes -o port=numero_de_port -o allow_other -o uid=$(id -u $USER) -o gid=$(id -g $USER) identifiant@hote_distant:/repertoire_cible /point_de_montage
Explications sur les options possibles :
-o compression=yes
peut être remplacée par l’option -C
- option
peu nécessaire-o port=numero_de_port
: le numéro du port SSH à contacter sur la
machine distante ; si c’est le port par défaut, à savoir 22, il n’y
a pas besoin de spécifier l’option ‘port’… cette option peut tout
simplement être remplacée par l’option -p numero_de_port
-o allow_other -o uid=$(id -u $USER) -o gid=$(id -g $USER)
vous permettront d’avoir accès localement aux données montées.allow_other
nécessite l’ajout de l’option user_allow_other
dans le fichier /etc/fuse.conf
identifiant
: votre identifiant sur la machine distantehote_distant
: le nom FQDN ou l’adresse IP de la machine distante.repertoire_cible
: le répertoire, sur la machine distante, que vous
souhaitez pouvoir atteindre. Selon les paramètres de configuration
du serveur SSH, vous ne pourrez très certainement pas monter plus
haut que votre partition /home
. Si vous ne spécifiez rien, tel que
id@hote:
, alors sshfs se connectera à votre répertoire /home
.point_de_montage
: l’endroit où vous désirez que le répertoire
distant se connecte sur votre station de travail.Pour démonter le point de montage :
$ doas umount /point_de_montage
Il peut vous être utile de lire localement sur votre station de travail OpenBSD, la page de manuel correspondante man sshfs
.
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Goaccess est un logiciel libre, réputé pour être léger, rapide, afin d’analyser en temps réel ou non l’activité sur un serveur web, soit directement au sein d’un terminal Unix, soit sur le protocol HTTPS.
Il est capable de produire des statitisques au format HTML, JSON, voire CSV.
⇒ Environnement :
Classique : # pkg_add goaccess
/etc/goaccess/goaccess.conf
.⇒ Il est possible sans aucun soucis d’utiliser goaccess avec son fichier de configuration sans rien modifier. Cela nécessite de passer toutes les options nécessaires dans la ligne de commande, hors certaines options sont clairement communes et peuvent être “figées” dans la configuration commune.
⇒ Il est aussi possible de créer plusieurs fichiers de configuration, chacun spécifique à un domaine web et de paramètrer selon le domaine. Dans ce cas-là, il faudra cibler tel fichier de configuration.
Dans la suite de cet article, j’utilise un seul fichier de configuration, et je cible quelques options dans la ligne de commande.
Voyons les principales options de configuration :
Le formatage de l’heure !
⇒ Si vous utilisez le service httpd, il faudra faire attention à paramètrer correctement le style de log dans son propre fichier de configuration, et de le répercuter dans le fichier de configuration de goaccess dans la section Time Format Options.
⇒ Pour nginx, il suffira de décommenter les options suivantes :
Si vous utilisez nginx, il est impératif d’enregistrer tous les statuts, de ne pas filter les statuts 2xx et 3xx - si vous aviez créer une directive map en ce sens, il vous faudra à minima la commenter puis relancer le service web.
Si vous n’avez qu’un seul domaine web sur votre serveur à analyser, il est utile de paramètrer l’option log-file vers le chemin absolu du fichier access.log relatif.
exclude-ip : n’hésitez pas à utiliser cette option pour exclure de l’analyse soit des adresses IP, soit des segments réseaux, tel votre réseau personnel, si votre serveur est par exemple à domicile.
444-as-404 : l’erreur 444 est spécifique au serveur Nginx. À vous de voir, si vous voulez que ces erreurs soient considérées comme étant des entrées d’erreur 404. Si oui, changez la en true.
ignore-crawlers : afin d’ignorer les robots ; changez la à true
ignore-panel est un ensemble de panneau qui peut être désactivé (voire activé) ; pour des histoires de RGPD, mieux vaut désactiver le panneau REMOTE_USER
anonymize-ip : changez-la à true - en ces temps de RGPD, il vaut mieux !
⇒ Activer les deux dernières options en positionnant sur true, si vous voulez garder les enregistrements de l’analyse dans la base de donnée de goaccess.
Alors, bien sûr, comme vous le verrez, il existe beaucoup d’autres options. À vous de voir…
Ensuite il suffit d’utiliser basiquement le binaire goaccess.
Maintenant, poussons un peu plus la configuration :
Personnellement je préfère créer et utiliser un utilisateur système dédié. Parmi les avantages, citons la recherche dans les log messages, voire cron.
# useradd -s /sbin/nologin -d /var/db/goaccess _goaccess
⇒ la recherche dans les logs se faisant ainsi :
$ grep goaccess /var/log/messages
ou
$ doas grep _goaccess /var/cron/log
⇒ J’ai préféré ajouter l’autorisation d’utiliser le binaire goaccess à l’utilisateur _goaccess.
Ajoutez à votre fichier /etc/doas.conf
:
permit nopass _goaccess cmd /usr/local/bin/goaccess
(J’avoue, je ne suis pas sûr que ce soit réellement nécessaire car le binaire goaccess semble s’exécuter sans droit particulier).
⇒ Création du répertoire principal pour la base de données de goaccess :
# mkdir -p /var/db/goaccess
# chown _goaccess:daemon /var/db/goaccess
(personnellement, j’ai préféré un autre chemin absolu).
Pensez à ajouter ce répertoire dans vos sauvegardes !
Ensuite si comme moi, vous avez plusieurs domaines web sur votre serveur, créez autant de sous-répertoire portant le nom du domaine web, tel que :
$ domain=
$ doas -u _goaccess mkdir "/var/db/goaccess/${domain}"
Ainsi, les futures statistiques seront vraiment dédiés à un domaine…
⇒ Il ne reste plus qu’à ajouter autant de règles cron que nécessaire, tel que :
$ doas -u _goaccess crontab -e
(Il est possible d’appeler la crontab utilisateur, tel que : doas crontab -u _goaccess -e
).
Pour ajouter :
*/15 * * * * -ns goaccess -a --db-path "/var/db/goaccess/domain/" -f /var/www/logs/domain/access.log -o /var/www/goaccess/domain/stats.html
Petites explications :
À vous de voir si vous désirez une authentification web avant la consultation des pages HTML ; d’aucuns estiment qu’il le faut, d’autres non ; personnellement je préfère.
Après l’utilisation du binaire htpasswd, elle se configure au-niveau du fichier de configuration de votre serveur web.
De manière basique :
server "domain.tld" {
(…)
root "/htdocs/domain.tld/www"
location "/stats" {
authenticate with "/file_htpwd"
directory auto index
}
(…)
}
Ne pas oubliez que le chemin du fichier htpasswd est relatif au chroot web !
Idem, basiquement :
(…)
location /stats/ {
auth_basic "Auth Area";
auth_basic_user_file /file_htpwd;
autoindex on;
}
(…)
Voilà pour la partie “configuration” !
Basiquement le binaire s’exécute ainsi :
$ goaccess -o /var/www/htdocs/domain.tld/stats/index.html
⇒ Une fois configuré, goaccess s’utilise ainsi :
Par exemple, une première fois, en précisant une date de mois-année :
$ domain=
$ date="$(date +'%Y-%m')"
$ doas -u _goaccess goaccess -a --db-path "/var/db/goaccess/${domain}/" -f "/var/www/logs/${domain}/access.log" -o "/var/db/goaccess/${domain}/stats-${domain}-${date}.html"
Je me suis créé un script shell pour me faciliter la vie - nommé goaccess.sh :
#!/bin/sh
###
#
# générer les stats du domain
#
##
date="$(date +'%m-%Y')"
dir_db="/var/db/goaccess"
domain="$1"
if [ -z "${domain}" ]; then
printf '%s %s\n' "KO" "No domain. Script stops!"
logger "$0: no domain found as option; script stops!"
exit 1
fi
if [ ! -d "${dir_db}/${domain}/" ]; then
printf '%s %s\n' "KO" "The destination directory '${dir_db}/${domain}/' seems not exist!"
logger "$0: The destination directory for goaccess not exists; script stops!"
exit 2
fi
goaccess -a --db-path "${dir_db}/${domain}/" -f "/var/www/logs/${domain}/access.log" -o "${dir_db}/${domain}/stats-${domain}-${date}.html"
Puis modifié la crontab de l’utilisateur _goaccess :
*/15 * * * * -ns /repertoire/goaccess.sh domain-x.tld
0 * * * * -ns /repertoire/goaccess.sh domain-y.tld
0 0 * * * -ns /repertoire/goaccess.sh domain-z.tld
(chacun à des moments différents).
Et non ce n’est pas fini !
En effet, le fichier d’analyse HTML généré est écrit dans le répertoire de base de données dédié. L’utilisateur _goaccess n’a pas accès au(x) répertoire(s) web, et n’a pas avoir accès.
Par contre, il est possible de demander à l’utilisateur web www de copier le fichier de statistiques HTML pour le déposer dans le répertoire web correspondant.
Ainsi, j’utilise le script shell suivant, nommé cp_stats.sh :
#!/bin/sh
set -e
#set -x
###
#
# copier les stats d'un domaine pour les publier enligne
#
##
date="$(date +'%m-%Y')"
domain="$1"
dir_db="/var/db/goaccess"
dir_stats="/var/www/htdocs/${domain}/www/stats/"
if [ -z "${domain}" ]; then
printf '%s %s\n' "KO" "No domain. Script stops!"
logger "$0: no domain found as option; script stops!"
exit 1
fi
if [ ! -f "${dir_db}/${domain}/stats-${domain}-${date}.html" ]; then
printf '%s %s\n' "KO" "The needed file '${dir_db}/${domain}/stats-${domain}-${date}.html' not exists. Script stops!"
logger "$0: The needed file '${dir_db}/${domain}/stats-${domain}-${date}.html' not exists; script stops!"
exit 2
fi
if [ ! -d "${dir_stats}" ]; then mkdir -p "${dir_stats}"; fi
cp "${dir_db}/${domain}/stats-${domain}-${date}.html" "${dir_stats}"
chown -R www "${dir_stats}"
Puis à modifier la crontab de l’utilisateur web :
$ doas -u www crontab -e
Tel que, pour l’exemple :
*/15 * * * * -ns /repertoire/cp_stats.sh domain-x.tld
5 * * * * -ns /repertoire/cp_stats.sh domain-y.tld
5 0 * * * -ns /repertoire/cp_stats.sh domain-z.tld
L’utilisation temps réel se fait de deux manières possibles.
Dans ces contextes, nous n’aurons pas besoin de l’utilisateur dédié _goaccess.
⇒ À minima, faites :
$ goaccess -f /var/www/logs/${domain}/access.log
Profitez de l’esthétique vue basée sur les couleurs monokaï, par défaut.
Là, ça devient intéressant, mais un peu compliqué :
Là, malheureusement, je n’ai pas trouvé de solution. Voire avec relayd!
Modifions la configuration du serveur en ajoutant une directive location :
location /ws {
proxy_pass http://localhost:7890;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
Maintenant il faut exécuter goaccess avec les droits de l’utilisateur www :
$ doas -u www goaccess -p /etc/goaccess/goaccess.realtime.conf -o /var/www/htdocs/huc.fr.eu.org/www/stats/realtime.html --ws-url=wss://huc.fr.eu.org:443/ws --port 7890
[PARSING /var/www/logs/doc.huc.fr.eu.org/access.log] {0} @ {0/s}
WebSocket server ready to accept new client connections
Remarquez que pour ce test, j’ai :
Du fait d’être obligé d’utiliser l’utilisateur web, nous pouvons en temps réel, surveillez dans une console SSH, l’activité de l’utilisateur, avec des binaires tels fstat, ps, par exemple :
$ fstat -u www -n
USER CMD PID FD DEV INUM MODE R/W SZ|DV
www goaccess 76729 wd 4,15 725760 40755 r 512
www goaccess 76729 0 4,0 78329 20620 rw 5,0
www goaccess 76729 1 4,0 78329 20620 rw 5,0
www goaccess 76729 2 4,0 78329 20620 rw 5,0
www goaccess 76729 3 4,3 175 10644 rw 0
www goaccess 76729 4 4,3 176 10644 rw 0
www goaccess 76729 5 4,3 175 10644 w 0
www goaccess 76729 6 4,3 176 10644 w 0
www goaccess 76729 7 pipe 0x0 state:
www goaccess 76729 8 pipe 0x0 state:
www goaccess 76729 9* internet stream tcp 0x0 *:7890
www goaccess 76729 10 pipe 0x0 state:
www goaccess 76729 11 pipe 0x0 state:
www goaccess 76729 12* internet stream tcp 0x0 127.0.0.1:7890 <-- 127.0.0.1:6459
$ ps aux -U www
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
www 4071 0.0 0.1 1572 3488 ?? S 10:12AM 0:00.88 sshd: www@notty (sshd)
www 76729 0.0 0.3 10096 12752 p0 S+ 7:56PM 0:01.49 goaccess -p /etc/goaccess/goaccess.realtime.conf -o /var/www/htdocs/huc.fr.eu.org/www/stats/realtime.html /var/www/logs/do
Il ne reste plus qu’à pointer un navigateur web le chemin du fichier realtime.html.
Remarquez le petit point vert sous l’icône en forme de roue crantée, en haut à gauche de l’écran.
Il semble nécessaire de rafraîchir soit même la page ; au bout de temps d’un certain temps, elle perd le connecteur. Un petit coup de F5…
Pour finir, on peut s’amuser à exécuter goaccess en tant que service, soit en utilisant l’option –daemonize, soit en configurant le fichier de configuration dédiée.
$ doas -u www goaccess --daemonize -p /etc/goaccess/goaccess.realtime.conf -o /var/www/htdocs/huc.fr.eu.org/www/stats/realtime.html --ws-url=wss://huc.fr.eu.org:443/ws --port 7890
Daemonized GoAccess: 48646
Cette option ne fonctionne qu’avec l’option de temps réel active.
De même, il est impératif que l’utilisateur web est accès au chemin qui enregistrera le fichier de processus PID - autrement vous serez en échec ! Il faut donc paramètrer l’option pid-file dans le fichier de configuratin.
Sous OpenBSD, pour rappel, du fait du chroot web, c’est le répertoire
/var/www/run
par défaut - préférez un sous-répertoire dédié à l’utilisateur
www.
Bien-sûr, tout cela, c’est pour le FUN, et l’exemple ! :D
Voilà !
(C’est mon expérience… et la vôtre !?)
Voici quelques erreurs rencontrées :
Couldn't open file /var/db/goaccess/xxx/I32_DATES.db: Permission denied
Unable to open the specified pid file. Permission denied
Unable to open the specified pid file. Permission denied
_goaccess:daemon
Ce problème est identique lors de la génération des fichiers HTML. Si les droits ne sont pas attribués à l’utilisateur _goaccess, vous ne pourrez pas les générer.
Exemple de message d’erreur :
GoAccess - version 1.5.1 - Sep 26 2021 14:08:19
Config file: /etc/goaccess/goaccess.conf
Fatal error has occurred
Error occurred at: src/output.c - output_html - 1183
Unable to open HTML file: Permission denied.
GoAccess - version 1.5.5 - Apr 8 2022 09:03:43
Config file: /etc/goaccess/goaccess.conf
Fatal error has occurred
Error occurred at: src/geoip2.c - init_geoip - 89
Unable to open GeoIP2 database /var/db/GeoIP/GeoLite2-Country.mmdb: Error opening the specified MaxMind DB file
Vous avez activé certainement l’option geoip-database
.
Mais avez-vous téléchargé les fichiers nécessaires et installés dans le
répertoire /var/db/GeoIP/
?
Puis vérifier l’existence du chemin dans votre système de fichiers, sans oublier que les droits utilisateurs correspondent bien à l’utilisateur dédié !
dir_db
du script goaccess.sh
.https://www.geeek.org/goaccess-analyser-access-log/ - où j’ai piqué la config de proxy nginx
https://hautefeuille.eu/post/goaccess-openbsd/ : un autre exemple de configuration pour httpd, juste pour de la consultation différée.
Enjoy-ID! Enjoy-IT!
]]>Comment faire une redirection permanente, appelée aussi 301, pour Hugo, avec le serveur web nginx… sous OpenBSD ?!
L’article de Romain Therrat donne les grandes lignes… sauf que sous OpenBSD, ça ne fonctionne pas !
Je reprends les grands principes ci-dessous, adapté à OpenBSD :
Le principe est l’utilisation des alias d’URL.
En partant du principe de l’utilisation du format toml, ouvrez le fichier que vous voulez rediriger et dans son entête, ajoutez :
aliases = [/ancienne/URL/de/publication/fichier/]
Si votre format de fichier de configuration est autre, adaptez !
Puis modifier le fichier de configuration de Hugo, pour ajouter les directives suivantes :
⇒ Ajoutez un type de media
[mediaTypes."conf/nginx"]
⇒ Ajoutez une sortie à générer, pour la variable home :
[outputs]
home = ["HTML", "nginx", …]
⇒ Ajoutez la sortie du format adéquat pour créer le fichier de redirections pour nginx :
[outputFormats.nginx]
baseName = "redirections.conf"
isPlainText = true
mediatype = "conf/nginx"
notAlternative = true
path = "nginx-config"
Puis, créer le layout nécessaire : layout/index.nginx
, tel que :
# Nginx redirect
{{- range $p := site.Pages -}}
{{- range .Aliases }}
rewrite ^{{ . }}$ {{ $p.RelPermalink }} permanent;{{ end }}
{{- end }}
nginx-config/redirections.conf
redirections.conf
dans chaque sous-répertoire de langue, tel que fr/nginx-config/redirections.conf
.Voilà, toute la configuration Hugo prête à être fonctionnelle !
La configuration présentée ci-dessous est relative à mon site multilingue… Si le votre est monolingue, adaptez !
Lorsque vous testerez la configuration, nginx se plaindra, telle que :
nginx: [emerg] open() "/var/www/htdocs/doc.huc.fr.eu.org/www/fr/nginx-conf/redirections.conf" failed (2: No such file or directory) in /etc/nginx/conf.d/domain.tld.conf:15
Et, oui le fichier existe bien, au bon endroit :
$ ls -al /var/www/htdocs/doc.huc.fr.eu.org/www/fr/nginx-config/redirections.conf
-rw-r--r-- 1 www www 397 Jul 28 13:23 /var/www/htdocs/doc.huc.fr.eu.org/www/fr/nginx-config/redirections.conf
Copions les fichiers de redirections à la racine du répertoire de configuration de nginx :
# cp /var/www/htdocs/doc.huc.fr.eu.org/www/en/nginx-config/redirections.conf /etc/nginx/hugo-en-redirections.conf
# cp /var/www/htdocs/doc.huc.fr.eu.org/www/fr/nginx-config/redirections.conf /etc/nginx/hugo-fr-redirections.conf
Puis, avec la directive include, incluez ces fichiers de configuration dans la directive server de l’hôte virtuel relatif au domaine, tel que :
server "domain.tld" {
(…)
include /etc/nginx/hugo-en-redirections.conf;
include /etc/nginx/hugo-fr-redirections.conf;
(…)
location /(en|fr)/nginx-conf/redirections.conf {
deny all;
}
(…)
}
Pour finir, remarquez la directive location afin d’interdire toute consultation.
Pensez à vérifier la configuration puis redémarrer le service :
# nginx -t && rcctl restart nginx
Voilà !
⇒ Hugo: URL Management: Aliases
Enjoy-ID! Enjoy-IT!
pfstat est un projet de Daniel Hartmeir pour générer des statistiques graphiques du flux réseau qui passe au-travers du parefeu PF.
⇒ Environnement :
Classique : # pkg_add pfstat pfstatd
Le paquet pfstatd n’est pas essentiel pour une configuration simple et minimale. Il devient intéressant pour être fonctionner avec un utilisateur dédié. ;-)
En admettant que l’interface réseau est de type em0, modifions le fichier
de configuration /etc/pf.conf
pour ajouter :
set loginterface em0
La configuration de pfstat n’est pas compliquée. Pour débuter, le package installe un fichier de configuration exemple, juste pour IPv4.
/etc/pfstat.conf
Il faut le modifier pour changer le chemin du répertoire de destination où seront les futures images créées pour la vision et l’analyse.
En admettant toujours que l’interface reseau à analyser est em0 :
# sed -i -e 's/sis0/em0/g;s/benzedrine.cx/pfstat/g' /etc/pfstat.conf
La commande va changer toutes les lignes où :
Ensuite, il suffit de configurer la crontab de root pour que le binaire pfstat analyse le flux réseau.
* * * * * -ns /usr/local/bin/pfstat -q -d /var/db/pfstat/pfstat.db
*/15 * * * * -ns /usr/local/bin/pfstat -p -d /var/db/pfstat/pfstat.db
30 0 * * * -ns /usr/local/bin/pfstat -t 30 -d /var/db/pfstat/pfstat.db
⇒ Cela nécessite la création du répertoire de la future base de données :
# mkdir -p /var/db/pfstat/
Juste pour info, cela peut être absolument un tout autre chemin sur le système d’exploitation, et avoir un tout autre nom de base de données. C’est à vous de voir…
Voilà une configuration minimale fonctionnelle !
Passons à une configuration plus poussée avec un utilisateur dédié qui va gérer et le service et l’utilisation du binaire.
L’utilisateur dédié nous sera utile pour démarrer le service pfstatd avec les droits utilisateurs de _pfstat, puis d’utiliser pfstat avec cet utilisateur…
# useradd -s /sbin/nologin -d /var/db/pfstat _pfstat
# chown _pfstat /var/db/pfstat
Il suffit d’activer le service, de le paramétrer et le démarrer :
# rcctl enable pfstatd
# rcctl set pfstatd flags -u _pfstat -a 127.0.0.1
# rcctl start pfstatd
N’ayant pas paramétré de numéro de port, c’est celui par défaut, à savoir 9999, qui sera écouté.
Des outils comme nc peuvent permettre de s’assurer du fonctionnement ;
essayez nc localhost 9999
, vous devriez avoir les statistiques qui
s’affichent rapidement les unes à les suites des autres, ligne après ligne.
Si ce n’est pas le cas, il y a un soucis…
Je vous encourage vivement à bloquer au niveau du pare-feu d’OpenBSD, toutes tentatives de communications sur le service de pfstatd !
Une règle comme la suivante devrait suffire :
block drop in on ! lo0 proto tcp to port 9999
Maintenant nous allons pouvoir reconfigurer l’utilisation de pfstat en tenant compte de l’utilisateur dédié _pfstat
* * * * * -ns /usr/local/bin/pfstat -q -d /var/db/pfstat/pfstat.db -r 127.0.0.1
*/15 * * * * -ns /usr/local/bin/pfstat -p -d /var/db/pfstat/pfstat.db
30 0 * * * -ns /usr/local/bin/pfstat -t 30 -d /var/db/pfstat/pfstat.db
Petites explications :
-r
suivie de l’adresse de bouclage
localhost ; cette option nous permet d’interroger le service “à distance”
pour récupèrer les statistiques et les enregistrer dans la base de données.Maintenant injections le fichier crontab4pfstat dans la crontab de l’utilisateur _pfstat :
# crontab -u _pfstat crontab4pfstat
Il y a différents moyens de surveiller l’activité de l’utilisateur _pfstat :
top -U _pfstat
:load averages: 0.05, 0.38, 0.38
56 processes: 54 idle, 2 on processor
CPU0 states: 0.0% user, 0.0% nice, 0.0% sys, 0.0% spin, 0.0% intr, 100% idle
Memory: Real: 84M/5985M act/tot Free: 9778M Cache: 2757M Swap: 0K/32G
PID USERNAME PRI NICE SIZE RES STATE WAIT TIME CPU COMMAND
16833 _pfstat 2 0 700K 984K sleep/6 netcon 0:00 0.00% pfstatd
$ fstat -u _pfstat -n
USER CMD PID FD DEV INUM MODE R/W SZ|DV
_pfstat pfstatd 16833 wd 4,0 2 40755 r 512
_pfstat pfstatd 16833 0 4,0 27162 20666 rw 2,2
_pfstat pfstatd 16833 1 4,0 27162 20666 rw 2,2
_pfstat pfstatd 16833 2 4,0 27162 20666 rw 2,2
_pfstat pfstatd 16833 3 4,0 27028 20600 r 73,0
_pfstat pfstatd 16833 4* internet stream tcp 0x0 127.0.0.1:9999
$ ps aux -U _pfstat
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
_pfstat 16833 0.0 0.0 700 984 ?? I 1:19AM 0:00.02 /usr/local/bin/pfstatd -u _pfstat -a 127.0.0.1
Ces trois commandes nous confirment que :
Configurons maintenant httpd !
Commençons par créer le répertoire :
# mkdir -p /var/www/htdocs/pfstat/
Puis occupons-nous du fichier de configuration de httpd /etc/httpd.conf
et ajoutons les déclarations suivantes, au besoin :
types {
include "/usr/share/misc/mime.types"
}
server "pfstat" {
listen on 127.0.0.1 port 80
location "/pfstat/" {
directory auto index
root "/htdocs/"
}
}
Il reste à vérifier la configuration et activer/démarrer le service :
# rcctl enable httpd
# httpd -n && rcctl start httpd
Il ne reste plus qu’à consulter localement, tel que : http://localhost/pfstat
Voilà une configuration minimale qui fonctionne et qui restituera des images.
Du fait d’avoir créé l’utilisateur _pfstat, donnons à l’utilisateur le droit d’écrire dans le répertoire web :
# usermod -G www _pfstat
# chown -R _pfstat:www /var/www/htdocs/pfstat
PFstats est mon petit projet de page responsive web pour consulter de manière agréable les images générées par pfstat.
Elle est conçue pour analyser des statistiques d’une heure, quotidiennes, hebdomadaires, et mensuelles, voire annuelles.
Voici un aperçu :
Quelques explications :
⇒ Le fichier de configuration pfstat.conf est configuré :
/var/www/htdocs/pfstat
.Il faut le copier à la place du fichier de configuration original.
Si vous analysez le fichier correctement, j’ai commenté toutes les lignes
concernant le traitement des queues ; en effet quand les lignes sont actives,
pfstat se plaint et s’arrête avec le message suivant :
/etc/pfstat.conf:61: ALTQ-style queues not supported anymore
Il semble que ce ne soit plus supporté !
Copier les fichiers .css, .js, et .html dans le répertoire de publication web
⇒ Ce script shell sert à convertir les images JPEG générées par pfstat au format avif, et webp.
Il nécessite l’installation des paquets libavif, et libwebp.
# usermod -G votre-identifiant-utilisateur _pfstat
# chmod 0750 /home/votre-identifiant-utilisateur/pfstats/convert-img.sh
Il faudra modifier la deuxième ligne de la crontab de l’utilisateur _pfstat, tel que :
15 * * * * -ns /usr/local/bin/pfstat -p -d /var/db/pfstat/pfstat.db; /dir/convert-img.sh
Ainsi se déroulent les étapes suivantes :
Pour gérer correctement les images au format avif et webp, il peut être nécessaire de modifier légérement la configuration d’httpd, pour ajouter dans le bloc de directives types :
image/avif avif
Tel que :
types {
include "/usr/share/misc/mime.types"
image/avif avif
}
⇒ Pour vérifier le support du format webp :
$ grep webp /usr/share/misc/mime.types
image/webp webp
Si la commande n’affiche aucun résultat, alors il faudra ajouter au bloc
types : image/webp webp
.
Depuis OpenBSD 6.9, ce n’est pas nécessaire.
Si vous êtes plutôt un fan de nginx, lisez mes articles suivants pour savoir comment gérer :
Il vous suffit d’adapter la configuration pour la consultation de la page web de pfstats.
Le message complet est le suivant :
/etc/pfstat.conf:61: ALTQ-style queues not supported anymore
Il semble que l’analyse des queues ne soit plus possible. Supprimez ou commentez toutes lignes relatives.
Dans le fichier de configuration que je fournis, elles sont commentées, juste au cas où ce serait une erreur de compréhension ou qu’il me manque une information pour les rendre fonctionnelles.
Avez-vous bien pensé à créer le répertoire ; vérifiez !
Voilà !
⇒ Projet PFstats : https://tildegit.org/hucste/pfstats
⇒ Qui supportent ces formats :
Gnome est un des environnements de bureau graphique, disponible aussi sous OpenBSD.
⇒ Environnement :
Dans ce tutoriel, je pars du principe qu’OpenBSD vient d’être fraîchement installé, et que tout est à faire.
Installez les paquets gnome gnome-extras
L’installation de ces paquets installent des dépendances, tels les paquets avahi, consolekit2, dbus, voire samba, sane-backend et bien d’autres.
L’environnement Gnome3 fonctionne différement des autres environnements de bureau. Ne cherchez pas à configurer les fichiers personnels .profile, .kshrc, voire .xsession, ils ne seront pas pris en compte pour le démarrage et l’utilisation de Gnome.
Si lors de l’installation d’OpenBSD, vous avez activé xenodm - le gestionnaire d’affichage par défaut - désactivez-le !
# rcctl disable xenodm
# rcctl stop xenodm
Puis on active le gestionnaire de session gdm ainsi que tous les services nécessaires !
# rcctl enable multicast messagebus avahi_daemon gdm
# rcctl start multicast messagebus avahi_daemon gdm
Ainsi que le mentionne le fichier pkg-readme de Gnome, les limites système par défaut dans OpenBSD ne sont pas assez élevées pour exécuter correctement Gnome.
Faisons cela bien:
Pour cela, modifions le fichier /etc/login.conf
, en ajoutant :
gnome:\
:datasize-cur=1024M:\
:tc=default:
⇒ OpenBSD ≤ 7.0 : de même, pour gdm, qui n’aura pas assez de descripteurs de fichiers à disposition.
créons une classe de login “gdm”, et ajoutons-la à celle de “xenodm”.
gdm:\
:tc=xenodm:
Puis modifions notre utilisateur :
# usermod -L gnome user
(où ‘user’ est votre identifiant utilisateur…)
Voilà !
C’est suffisant pour faire fonctionner correctement Gnome sous OpenBSD. Un petit redémarrage de l’OS et ça devrait le faire. :p
Maintenant allons un peu plus loin dans la configuration, tel qu’avoir sa session en langue française, et d’autres petites astuces utiles.
Pour gérer votre langue - dans mon cas, FR - dès le gestionnaire de session
gdm, il faut modifier le fichier /etc/gdm/locale.conf
, tel que :
# $OpenBSD: locale.conf,v 1.4 2014/01/08 14:07:48 ajacoutot Exp $
#
# Mimics Linux's /etc/locale.conf.
# See locale(1) for a list of supported locales (`locale -a`).
# OpenBSD setlocale(3) does not handle LANG
#LANG="en_US.UTF-8"
LC_CTYPE="fr_FR.UTF-8"
LC_MESSAGES="fr_FR.UTF-8"
Si vous ne faites pas cette modification, et si vous avez un mot-de-passe avec des caractères accentués dans votre langue, selon le clavier paramétré lors de l’installation d’OpenBSD, vous ne pourrez pas vous connecter, car gdm utilise par défaut la langue anglaise.
Pensez à redémarrer gdm…
Pour la gestion des fonctionnalités de mise en veille et d’hibernation, activez le service apmd :
# rcctl enable apmd
# rcctl set apmd flags -A
# rcctl start apmd
Pour gérer l’impression, il est utile d’installer Cups :
# pkg_add cups cups-filters cups-libs foomatic-db gutenprint
Démarrons les services cupsd, voire cups_browsed - ce dernier étant utile pour la détection des imprimantes sur le réseau, utilisant les messages broadcast de type Bonjour, tel Avahi.
# rcctl enable cupsd cups_browsed
# rcctl start cups cups_browsed
L’administration peut se faire au-travers des paramètres Imprimantes, voire de l’interface web de Cups, disponible depuis l’URL http://localhost:631, ou des outils cupsctl, lpadmin.
Le gestionnaire gnome-documents ne gère pas, par défaut, le type des documents Office. Il suffit d’installer le paquet unoconv.
⇒ Ne cherchez pas à masquer toutes les fenêtres pour afficher juste le bureau, l’option n’est pas activée par défaut !
Ouvrer l’application “Paramètres” > “Raccourcis clavier”, puis dans la section “Navigation”, chercher “Masquer toutes les fenêtres normales” qui sera “Désactivé”.
Cliquez dessus, et paramétrez la combinaison de touches que vous désirez, tel que les touches “Super” + “D” (pour Desktop - Bureau en anglais), ou “Super” + “B”. À vous de voir…
Cette fonctionnalité n’existe pas par défaut !
Je mets à disposition deux scripts pour implémenter cette fonctionnalité.
Retrouvez-les sur mon Git : WallpaperManager
Lisez les informations pour l’installer et l’utiliser sans soucis.
Je n’ai pas abordé la question des règles de parefeu, mais voici par exemple :
⇒ Cups :
pass in on egress proto tcp from egress:network to egress port 631 flags S/SA modulate state
⇒ Avahi :
pass proto udp from any to 224.0.0.251 port mdns allow-opts
pass inet6 proto udp from any to ff02::fb port mdns allow-opts
pass proto udp from any to 239.255.255.250 port ssdp allow-opts
pass inet6 proto udp from any to { ff02::c, ff05::c, ff08::c } port ssdp allow-opts
Bien-sûr, c’est à vous de voir à les utiliser, voire à les améliorer selon vos évidences.
GDM refuse de démarrer !
Lisez direct le fichier log des démons, voire celui des messages :
# grep gdm /var/log/daemon
Dans les logs daemons ou messages, vous avez l’équivalent de ce message :
Jul 23 09:38:14 og3 gdm[56941]: Gdm: Couldn't connect to system bus: Could not connect: No such file or directory
Il est très probable que ce soit parce que le service messagebus ne soit pas activé et démarré.
Avez-vous bien activé tous les services comme écrit en début de cet article ?!
Voilà !
Xfce4 est un environnement de bureau graphique, disponible aussi sous OpenBSD.
⇒ Environnement :
Dans ce tutoriel, je pars du principe qu’OpenBSD vient d’être fraîchement installé, et que tout est à faire.
Installez
les
paquets xfce xfce-extras
.
L’installation de ces paquets installent des dépendances, tel le paquet dbus.
Par défaut, certains paquets liés à l’environnement de bureau ne sont pas installés. À vous de voir si vous voulez le faire !
setxkbmap
, voire tout simplement kbd
, suivie du code de langue…
suffit.Depuis la version 4.14 d’Xfce4, disponible depuis OpenBSD 6.6, il est un peu plus simple de configurer son environnement système personnel, pour faire fonctionner aisément Xfce4.
Dans un premier temps, je montre un configuration basique fonctionnel ; puis, j’ajouterai des informations qui peuvent améliorer votre “confort” fonctionnel.
Le premier fichier à créer est le fichier personnel de session
~/.xsession
pour y ajouter simplement :
exec xfce4-session
Il est impératif d’ajouter votre utilisateur système aux deux groupes systèmes suivants :
Avec des droits administrateurs :
# usermod -G _shutdown,wheel user
(modifier ‘user’ par votre identifiant utilisateur, bien-sûr…)
Configurer apmd
va nous
permettre d’utiliser la veille et l’hibernation.
Pour se faciliter, nous le mettrons en mode automatique d’ajustement des
performances.
Si vous avez un laptop ou que vous souhaitez que le système gère plus finement l’ajustement des performances, vous pouvez préférer l’utilisation d’obsdfreqd : un service pour gérer la fréquence CPU / OpenBSD.
obsdfreqd est un gestionnaire de fréquences de CPU, créé par Solène Rapenne. Il a été officiellement packagé depuis OpenBSD 7.1.
Il remplace le service natif apmd.
Explications :
Voilà !
C’est suffisant pour faire fonctionner correctement Xfce4 sous OpenBSD. Un petit redémarrage de l’OS et ça devrait le faire. :p
Maintenant allons un peu plus loin dans la configuration, tel qu’avoir sa session en langue française, et d’autres petites astuces utiles.
Commençons par configurer votre fichier personnel de profil ~/.profile
.
Ajouter à celui de base les mentions suivantes :
EDITOR=vi # ou nano, emacs, voire vim
ENV=$HOME/.kshrc
LC_MESSAGES=fr # ou fr_FR.UTF8, si vous préférez ; mais ça sera pareil !
export EDITOR ENV LC_MESSAGES
⇒ Explications :
vi
est installé de base, les autres sont à installer.Bien-sûr, nous exportons les trois variables afin qu’elles soient toutes utiles et utilisées ensuite.
Pour finir sur ce sujet, il est bien sûr possible de définir toute
variable d’environnement, telle PS1
par exemple :
export PS1="[\t] \e[0;35m:\u@\h: \e[0;32m\w \e[0;36m\$ \e[m"
Voici un exemple du fichier fini :
# $OpenBSD: dot.profile,v 1.7 2020/01/24 02:09:51 okan Exp $
#
# sh/ksh initialization
PATH=$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/usr/games
export PATH HOME TERM
EDITOR=nano
ENV=$HOME/.kshrc
LC_MESSAGES=fr
export EDITOR ENV LC_MESSAGES
Concernant la variable ENV, nous avons déclaré un fichier personnel
~/.kshrc
. Par défaut, il n’existe pas ; il suffit de le créer avec
votre éditeur de texte favori - ce que nous verrons ci-dessous…
Il faut modifier votre fichier personnel ~/.xsession
pour ajouter
l’environnement du profil, tel que :
. $HOME/.profile
exec xfce4-session
Ainsi votre session graphique tiendra compte des différents paramètrages de votre profil, tel que la gestion de la langue, par exemple…
Le contenu de ce fichier personnel n’est pas compliqué. Voici quoi ajouter pour être fonctionnel :
. /etc/ksh.kshrc
. $HOME/.profile
HISTCONTROL=ignoredumps
HISTFILE=$HOME/.mksh_hist
HISTSIZE=10000
PAGER=less
export PAGER
⇒ Explications utiles :
/etc/ksh.kshrc
afin d’avoir un environnement shell correctement configuré par défautHISTFILE
est la variable pour définir le fichier de sauvegarde de
l’historiqueHISTSIZE
est le nombre de commande à se souvenir ; à ne pas confondre
avec le nombre de lignes du fichier, qui lui est défini par la
variable HISTFILESIZE
-
non définie ici.Le paquet dbus est installé en tant que dépendance.
Les modifications ci-dessous ne sont pas essentielles, bien qu’utiles. Elles sont relatées dans le fichier pkg-readme relatif.
Ajouter à votre fichier personnel de session ~/.xsession
:
if [ -x /usr/local/bin/dbus-launch -a -z "${DBUS_SESSION_BUS_ADDRESS}" ]; then
eval `dbus-launch --sh-syntax --exit-with-x11`
fi
Le fichier ressemblera ainsi au final à cela :
. $HOME/.profile
if [ -x /usr/local/bin/dbus-launch -a -z "${DBUS_SESSION_BUS_ADDRESS}" ]; then
eval `dbus-launch --sh-syntax --exit-with-x11`
fi
exec xfce4-session
Le pkg-readme upower nous informe qu’il est utile d’exécuter les services apmd et messagebus afin que le système de gestion d’énergie fonctionne ; activons et démarrons messagebus
⇒ À ce propos si votre machine est un ordinateur portable,
installez
le
paquet xfce4-power-manager
, qui n’est pas fourni par défaut.
Pour gérer l’impression, il est utile d’installer CUPS .
Démarrons les services cupsd, voire cups_browsed - ce dernier étant utile pour la détection des imprimantes sur le réseau, utilisant les messages broadcast de type Bonjour.
Voir : CUPS
L’administration peut se faire au-travers de l’interface web de Cups, disponible depuis l’URL http://localhost:631, ou des outils cupsctl, lpadmin.
Depuis OpenBSD 6.2, les binaires lpq, lpr, et lprm doivent être symboliquement liés, pour fonctionner plus facilement.
Éditons à nouveau le fichier personnel ~/.kshrc
pour y ajouter :
for i in lpq lpr lprm; do alias $i=/usr/local/bin/$i; done
Avahi est sous OpenBSD le service de découverte multicast DNS, de type Bonjour.
Il suffit d’installer le paquet avahi
pour en profiter puis d’activer et démarrer les services dans le bon
ordre.
Je n’ai pas abordé la question des règles de parefeu, mais voici par exemple :
⇒ les règles PF pour Cups,
⇒ les règles PF pour Avahi.
Bien-sûr, c’est à vous de voir à les utiliser, voire à les améliorer selon vos nécessités.
Pensez après vos modifications des fichiers personnels, à redémarrer à minima votre session, voire la machine. À vous de voir ! ;-)
Après, à vous d’installer tout autre logiciel qui peut vous être utile.
Voilà !
Ayant un onduleur Eaton Ellipse ECO, j’utilise le projet NUT pour le gérer sous OpenBSD.
⇒ Environnement :
⇒ Matériel UPS : Eaton Ellipse ECO 650 VA USB FR
Installez nut
Le binaire nut-scanner permet de détecter tout matériel UPS connecté, que ce soit par USB, ou réseau.
Avec des droits admins :
$ doas nut-scanner
SNMP library not found. SNMP search disabled.
Neon library not found. XML search disabled.
AVAHI client library not found. AVAHI search disabled.
Scanning USB bus.
No start IP, skipping NUT bus (old connect method)
[nutdev1]
driver = "usbhid-ups"
port = "auto"
vendorid = "0463"
productid = "FFFF"
product = "Ellipse ECO"
serial = "000000000"
vendor = "EATON"
bus = "005"
Ensuite, plusieurs fichiers de configurations sont à modifier. Tout changement dans un des fichiers de configuration nécessite le redémarre des services ad hoc.
Il faut remplir le fichier de configuration /etc/nut/ups.conf
avec les
informations retournées par le logiciel.
(…)
[eaton]
desc = "Eaton Ellipse ECO 650 VA USB FR"
driver = "usbhid-ups"
port = "auto"
vendorid = "0463"
productid = "FFFF"
product = "Ellipse ECO"
serial = "000000000"
vendor = "EATON"
bus = "005"
Ce fichier de configuration permet de paramètrer le contrôle de l’accès aux données gérées par le serveur upsd. Par défaut, le service est seulement accessible sur localhost, en IPv4 et IPv6, sur le port 3493.
C’est ce fichier de configuration qu’il faudra modifier pour utiliser l’encapsulation TLS, si besoin.
Depuis la version 2.4.0 du projet NUT, les directives ACL et allowfrom ont été remplacés par la directive LISTEN et le mécanisme tcp-wrappers. (cf la note de changements…)
Ne cherchez plus à utiliser les directives ACL ; beaucoup de vieux tutoriels y font de fait références. Tenez en compte !
Ce fichier de configuration permet de configurer des utilisateurs qui auront les droits d’interagir avec le serveur upsd.
Il est IMPératif que ce fichier ait des droits systèmes les plus minimalistes ! Par défaut, sous OpenBSD, seul l’utilisateur dédié y a accès en lecture-écriture.
$ doas chmod 0400 /etc/nut/upsd.users
Profitons en pour configurer un utilisateur qui aura le droit de communiquer entre les services upsd et upsmon.
[upsmon]
password = ***
upsmon master
Ainsi nous créons :
Puis modifions le fichier upsmon.conf.
Ce fichier de configuration paramètre le service moniteur.
Suite à la modification du fichier upsd.users pour configurer un utilisateur upsmon, il nous faut ajouter une directive MONITOR, telle que :
MONITOR eaton@localhost 1 upsmon *** master
(Les ‘***’ doivent correspondre au mot de passe configuré dans le fichier upsd.users pour l’utilisateur upsmon).
Ensuite, il faut modifier à minima, les directives NOTIFYMSG, NOTIFYFLAG ; je vous renvoie à la documentation officielle, ainsi que pour connaître le rôle des autres directives.
Concernant les directives NOTIFYFLAG, il importe d’ajouter le drapeau EXEC pour l’exécution des commandes liées. Sans, celles-ci ne seront pas exécutées.
Finissons par parler de la directive NOTIFYCMD qui n’est pas paramétrée correctement :
Tel que :
NOTIFYCMD /usr/local/sbin/upssched
Ainsi le service upsmon passera le relais au binaire upssched, qui lira alors la configuration du fichier upssched.conf.
Pourquoi faire cela ?
C’est simplement recommandé par la doc officielle, dans la sous section Suppressing notify storms où il est clairement écrit d’utiliser upssched en tant que notificateur de commande, afin d’éviter une “tornade de notifications”, qui pourrait avoir lieu dans certains contextes, si la directive NOTIFYCMD n’était pas configurée.
Ce fichier de configuration permet de configurer des actions à planifier.
Il faut décommenter les directives PIPEFN, LOCKFN, et enfin les directives AT.
Concernant les deux directives LOCKFN et PIPEFN, le chemin absolu renseigné par défaut n’existe pas ; il faut le créer et lui donner les droits de l’utilisateur _ups :
# mkdir -p /var/db/nut/upssched
# chown _ups /var/db/nut/upssched
Ensuite créer les directives AT nécessaires ; voici ce que j’ai configuré :
(…)
AT ONBATT * START-TIMER onbatt 15
AT ONBATT * START-TIMER onbattwarn 30
(…)
AT ONLINE * CANCEL-TIMER onbatt
AT ONLINE * CANCEL-TIMER onbattwarn
(…)
AT ONLINE * EXECUTE ups-back-on-line
Sans parler qu’il est possible de modifier le script /usr/local/bin/upssched-cmd
,
pour interagir avec le système selon l’événement appelé.
Veuillez lire plus profondément la doc officielle.
Ce fichier de configuration permet l’usage de scripts CGI, fournit dans le paquet nut-cgi et n’a qu’un rôle : celui d’attester que la configuration pour utiliser les scripts CGI en question est bel et bien (soit-disant ?) sécurisée.
Il ne sert que dans ce contexte.
Sous OpenBSD, lors de l’installation du binaire, sont configurés :
Il est nécessaire de configurer les permissions utilisateurs afin d’avoir accès au nœud de dispositif adéquat.
⇒ Pour les dispositifs USB, il faut identifier le contrôleur USB sur lequel est connecté le périphérique UPS, voire le(s) nœud(s) de dispositifs ugen.
Utilisons la commande usbdevs :
$ doas usbdevs
(…)
Controller /dev/usb5:
addr 01: 1002:0000 ATI, OHCI root hub
addr 02: 0463:ffff EATON, Ellipse ECO
(…)
Dans mon cas, le périphérique UPS est connecté sur le contrôleur usb5, sans nœud de dispositifs précisé.
Ensuite, il suffit de changer les droits utilisateurs sur le dispositif adéquat ; dans mon cas :
$ doas chown :_ups /dev/usb5 # ou, chgrp _ups /dev/usb5
$ doas chmod g+w /dev/usb5
Ainsi le groupe _ups a accès au contrôleur !
Pour finir, assurons-nous d’avoir les droits utilisateurs sur les fichiers du répertoire de configuration ‘/etc/nut’ :
$ doas chown _ups:_ups /etc/nut/ups*
Normalement, cela suffit pour démarrer les services adéquats.
⇒ Si l’onduleur est connecté par le port RS232, il faut soit :
/dev/tty
adéquat pour
que l’utilisateur _ups puisse le gérer.Ce n’est pas le cas de mon onduleur ! ;-)
Côté service, il faut donc activer puis démarrer les démons suivants :
Le service upsd doit être démarré avant le service upsmon.
$ doas rcctl enable upsd upsmon
$ doas rcctl set upsd flags -u _ups
$ doas rcctl start upsd upsmon
Normallement, le log daemon doit notifier ainsi les services :
(…)
Jul 17 13:25:34 sh1 usbhid-ups[47317]: Startup successful
Jul 17 13:25:34 sh1 upsd[83153]: listening on ::1 port 3493
Jul 17 13:25:34 sh1 upsd[83153]: listening on 127.0.0.1 port 3493
Jul 17 13:25:34 sh1 upsd[83153]: Connected to UPS [eaton]: usbhid-ups-eaton
Jul 17 13:25:34 sh1 upsd[90348]: Startup successful
Jul 17 13:25:34 sh1 upsmon[19005]: Startup successful
(…)
Le binaire upsc permet de vérifier l’état de l’onduleur, tel que :
$ upsc eaton
est la même chose que faire $ upsc eaton@localhost
⇒ Connaître l’état de la batterie :
$ upsc eaton ups.status
OL
Les indicateurs OB et LB doivent déclencher des actions selon ce qui est paramétré dans les fichiers de configuration upsmon.conf, voire upssched.conf.
Il est possible de vérifier quels processus sont gérés par l’utilisateur _ups,
voire quels sont les fichiers ouverts par lui, par exemple avec les
commandes ps
et fstat
, tels que :
$ ps aux -U _ups
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
_ups 31655 0.0 0.0 836 1668 ?? S 5:07PM 0:00.70 /usr/local/bin/usbhid-ups -a eaton
_ups 4840 0.0 0.0 764 1308 ?? S 5:07PM 0:00.12 /usr/local/sbin/upsd -u _ups
_ups 65469 0.0 0.0 780 3084 ?? S 5:07PM 0:00.09 /usr/local/sbin/upsmon
$ fstat -u _ups -n
USER CMD PID FD DEV INUM MODE R/W SZ|DV
_ups upsmon 65469 wd 4,0 103712 40700 r 512
_ups upsmon 65469 0 4,0 27162 20666 rw 2,2
_ups upsmon 65469 1 4,0 27162 20666 rw 2,2
_ups upsmon 65469 2 4,0 27162 20666 rw 2,2
_ups upsmon 65469 3* internet stream tcp 0x0 127.0.0.1:26706 --> 127.0.0.1:3493
_ups upsmon 65469 4 pipe 0x0 state:
_ups upsd 4840 wd 4,4 26111 40700 r 512
_ups upsd 4840 0 4,0 27162 20666 rw 2,2
_ups upsd 4840 1 4,0 27162 20666 rw 2,2
_ups upsd 4840 2 4,0 27162 20666 rw 2,2
_ups upsd 4840 3* internet6 stream tcp 0x0 [::1]:3493
_ups upsd 4840 4* internet stream tcp 0x0 127.0.0.1:3493
_ups upsd 4840 5* unix stream 0x0
_ups upsd 4840 6* internet stream tcp 0x0 127.0.0.1:3493 <-- 127.0.0.1:26706
_ups usbhid-ups 31655 wd 4,4 26111 40700 r 512
_ups usbhid-ups 31655 0 4,0 27162 20666 rw 2,2
_ups usbhid-ups 31655 1 4,0 27162 20666 rw 2,2
_ups usbhid-ups 31655 2 4,0 27162 20666 rw 2,2
_ups usbhid-ups 31655 3 pipe 0x0 state:
_ups usbhid-ups 31655 4 pipe 0x0 state:
_ups usbhid-ups 31655 5* unix stream 0x0 /var/db/nut/usbhid-ups-eaton
_ups usbhid-ups 31655 6* unix stream 0x0 /var/db/nut/usbhid-ups-eaton
Ainsi, on remarque que :
Voici, la série de messages :
(…)
upsd[55984]: Can't connect to UPS [eaton] (usbhid-ups-eaton): Connection refused
upsmon[20574]: Poll UPS [eaton@localhost] failed - Driver not connected
upsmon[20574]: Communications with UPS eaton@localhost lost
(…)
upsmon[44238]: UPS eaton@localhost is unavailable
upsmon[44238]: UPS [eaton@localhost]: connect failed: Connection failure: Connection refused
(…)
Au minimum, deux raisons possibles :
vérifiez la connexion physique USB de l’onduleur. Il peut être utile de changer de câble USB, et/ou de débrancher pour rebrancher le câble. De même les ports USB de votre carte-mère, ou de votre hub USB commencent peut-être à être défectueux.
lors d’une migration d’OpenBSD : il faut refaire les permissions nécessaires !
upsmon[39287]: Login on UPS [eaton@localhost] failed - got [ERR ACCESS-DENIED]
Vérifier qu’un utilisateur a été configuré dans les fichiers upsd.users, qu’il corresponde bien à celui paramétré dans upsmon.conf.
upsd[87303]: Can't open /etc/nut/upsd.conf: Permission denied
Vérifier les droits utilisateurs sur le fichier en question, il doit appartenir à l’utilisateur _ups
Le binaire nut-cgi fournit des scripts CGI pour interagir/visionner au-travers d’un service web le fonctionnement de l’onduleur.
Dans les faits, cela ne fonctionne officiellement qu’avec le serveur Apache, et nécessite l’écriture d’un fichier de configuration hosts.conf, non créé par défaut.
Pour la petite histoire, j’ai essayé de paramétrer et utiliser les services natifs que sont httpd et slowcgi puis à modifier le fichier de configuration upsset.conf, mais le service refuse de fonctionner en informant qu’il s’arrête par défaut de sécurité.
Résultat : nut-cgi semble ne pas fonctionner avec httpd…
Voici ci-dessous la configuration testée :
Ici la configuration minimaliste du serveur httpd utilisée :
types {
include "/usr/share/misc/mime.types"
}
server "default" {
listen on 127.0.0.1 port 80
log { access "httpd-default-access.log", error "httpd-default-error.log" }
location "/cgi-bin/nut/upsset.cgi" {
fastcgi socket "/run/slowcgi.sock"
root "/"
}
}
Pour que les scripts CGI, il semble nécessaire d’installer le binaire sh dans le chroot web :
$ doas install -o root -g bin -m 0555 /bin/sh /var/www/bin/
Il faut aussi donner les droits de l’utilsateur www sur le scrit CGI, tel que :
$ doas chown www:bin /var/www/cgi-bin/nut/upsset.cgi
Il est de même possible de faire de même pour les deux autres scripts CGI ; à ne faire que si vraiment le besoin est réel.
Le fichier de configuration hosts.conf n’existe pas par défaut, sous OpenBSD. Il faut le créer et lui donner les droits de l’utilisateur _ups.
Dans mon cas :
$ doas echo "MONITOR eaton@localhost \"Eaton Ellipse ECO 650 VA USB FR\"" > /etc/nut/hosts.conf
$ doas chown _ups:_ups /etc/nut/hosts.conf
Il est nécessaire de décommenter l’écriture I_HAVE_SECURED_MY_CGI_DIRECTORY dans le fichier de configuration upsset.conf
/usr/local/share/doc/pkg-readmes/nut
Par défaut, il y a la commande ftp
utile pour télécharger un fichier en http :
$ ftp -o /chemin/vers/lefichier.zip http://URL.com/fichier
Il n’y a ni wget
ni curl
par défaut !
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Historiquement, sous OpenBSD, on utilise l’outil natif
cksum
(1) :
$ cksum -a ${algo} -h ${hashfile} nom_fichier
algo
: est le nom de l’algorithme à choisir, parmi cksum
, md5
,
rmd160
, sha1
, sha224
, sha256
, sha384
, sha512/256
, et
sha512
hashfile
: est le fichier de sorti de la somme de contrôle calculéemd5
(1) :
Il n’est pas recommandé d’utiliser les algorithmes MD5, SHA1.J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Par défaut, depuis OpenBSD 6.9, pour des raisons de confidentialité, l’enregistrement vidéo est désactivé !
Pour le réactiver : # sysctl kern.video.record=1
N’oubliez pas de modifier le fichier /etc/sysctl.conf
en conséquence,
si vous désirez qu’il soit actif dès le démarrage :
# echo kern.video.record=1 >> /etc/sysctl.conf
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Retrouvez ci-dessous la traduction EN → FR de l’article “Full list of services offered by a default OpenBSD installation”, écrit par Solène Rapenne.
Cet article donne une courte description de CHACUN des services disponibles dans l’installation par défaut d’OpenBSD (càd hors packages installés).
Parmi tous dans cette liste, les services suivant sont démarrés par défaut : cron, pflogd, sndiod, openssh, ntpd, syslogd et smtpd. Les démons réseaux que sont smtpd (localement), openssh et ntpd (client), sont fonctionnels.
J’ai extrait cette liste des services installés dans la base en recherchant
dans /etc/rc/conf
.
$ grep _flags /etc/rc.conf | cut -d '_' -f 1
Ce démon est utilisé pour monter automatiquement un serveur NFS distant
quand une personne veut y accéder ; il peut fournir une méthode alternative
en cas où le système de fichier n’est pas joignable. Vous aurez plus
d’informations en utilisant la commande “info amd
”.
Ce démon est responsable de la gestion de la frèquence CPU. Il est important de l’exécuter sur une station de travail et spécifiquement sur un portable ; il peut aussi déclencher automatiquement la mise en veille ou une hibernation en cas de niveau de batterie bas.
C’est le démon BGP qui est utilisé par les routeurs réseaux pour échanger les routes avec d’autres routeurs. C’est ce qui fait principalement qu’Internet fonctionne ; chaque compagnie d’hébergement annonce leurs ensembles d’adresses IP et comment les atteindre, en retour, elles reçoivent aussi les chemins pour se connecter à toutes les autres adresses.
Ce démon est utilisé pour le démarrage sans disque sur réseau ; il fournit l’information pour qu’un client, tel un point de montage NFS, utilise des dispositifs racine ou swap.
C’est le démon qui lira la table de cron de chaque utilisateur et celles
du système afin d’exécuter les commandes programmées. Les tables de cron
utilisateur sont modifiées par l’usage de la commande crontab
.
C’est le serveur DHCP utilisé pour fournir automatiquement des adresses IPv4 sur le réseau aux systèmes utilisant un client DHCP.
C’est un client DHCP - apparu sous OpenBSD 6.9 2
C’est un relais de requêtes DHCP, utilisé par une interface réseau pour relayer les requêtes vers une autre interface.
Ce démon est un démon de routage multicast, au cas où vous auriez besoin d’un spanning multicast pour le déployer en dehors de votre LAN local. Il est toutefois remplacé par PIM .
Ce démon est un protocol de routage à états de liens pour une passerelle Internet ; il est comparable à OSPF mais compatible avec CISCO.
C’est un serveur FTP fournissant beaucoup de fonctionnalités. Bien que FTP soit abandonné et obsolète (certainement parce qu’il n’est pas pleinement fonctionnel dans le cas de NAT ), il peut être utilisé pour fournir des accès en lecture et écriture anonymes sur un répertoire (et bien d’autres choses).
C’est un démon proxy FTP qui est un de ceux supposés être fonctionnels par dessus NAT ; il ajoutera les règles PF automatiquement afin de connecter les requêtes entrantes au serveur derrière la NAT. C’est une partie de la folie FTP.
La version IPv6 du précédent. Utiliser IPV6 derrière une NAT n’a pas de sens.
C’est le démon qui permet à OpenBSD de devenir un point d’accès Wifi.
hotplugd est un magnifique démon qui exécutera des actions lorsque des dispositifs sont connectés ou déconnectés. Il pourrait être programmé pour exécuter automatiquement une sauvegarde si certaines conditions sont remplies, comme l’insertion d’un disque USB correspondant à un nom connu ou comme le montage d’un lecteur.
httpd est le démon HTTP(S) qui supporte certaines fonctionnalités, telles la prise en charge de FastCGI, la réécriture d’URL et SNI . Bien qu’il n’ait pas toutes les fonctionnalités d’un serveur web tel nginx, il est capable d’héberger certains programmes PHP tels que nextcloud, roundcube ou mediawiki.
identd est un démon pour le Protocole d’Identification qui retourne le nom de session pour un utilisateur qui a initié une connexion, qui peut être utilisé sur IRC pour authentifier l’utilisateur.
C’est le démon pour surveiller l’état des interfaces réseaux et qui peut mettre en place des actions lors de changements. Il peut être utiliser pour déclencher des changements en cas où une interface perd sa connectivité. Je l’ai utiliser pour déclencher un changement de route pour un dispositif 4G dans le cas où un ping échoue par dessus l’interface de liaison montante.
C’est le démon utilisé pour fournir une authentification IKEv2 afin d’établir un tunnel IPSec.
Ce démon est souvent oublié mais est très utile. inetd peut écouter sur les ports TCP ou UDP et exécutera une commande lors de la connexion à un port donné, des données entrantes seront passées à l’entrée standard d’un programme et la sortie sera retournée au client. C’est une manière facile de transformer un programme en programme réseau ; il n’est pas largement utilisé car il n’est pas très évolutif. En effet, le processus d’exécution d’un nouveau programme à chaque connexion peut pousser un système à ses limites.
Ce démon est utilisé pour fournir une authentification IKEv1 afin d’établir un tunnel IPSec.
Ce démon est un initiateur iSCSI qui connectera une cible iSCSI (c’est ainsi
qu’est appelé un dispositif de bloc réseau) et l’exposera localement en
tant que dispositif /dev/vcsi
. OpenBSD ne fournit pas de démon de cible
iSCSI dans son système de base mais il en existe un dans les ports.
C’est un serveur LDAP léger, offrant la version 3 du protocole.
Ce démon permet de configurer des programmes exposés sur le port série, tels des dispositifs gps.
Ce démon est spécifique à la plateforme sparc64 et fournit des services pour la fonctionnalité dom.
Ce démon est utilisé pour les routeurs MPLS afin d’obtenir des labels.
Ce démon est utilisé comme part de l’environnement NFS pour supporter le verrouillage de fichiers.
Ce démon est utilisé pour gérer un accès à une imprimante.
Ce démon est utilisé pour les clients distants NFS afin d’obtenir l’information
sur ce que le système offre actuellement. La commande showmount
peut
être utilisée pour voir ce qu’expose mountd.
Ce démon est utilisé pour distribuer des images MOP, qui semble être relatif aux architectures alpha et WAX.
Identique à dvmrpd .
Ce serveur est utiliser pour servir les requêtes NFS venant des clients
NFS. Des statistiques NFS (client ou serveur) peuvent être obtenues par
la commande nfsstat
.
Ce démon est utilisé pour établir une connexion par PPP mais peut aussi créer des tunnels avec les protocoles L2TP, PPTP et PPPoE. PPP est utilisé par certains modems pour se connecter à Internet.
Ce démon est un serveur de nom DNS faisant autorité, ce qui signifie qu’il gère toutes les informations à-propos d’un nom de domaine et de ses sous-domaines. Il reçoit les requêtes depuis les serveurs récursifs, tels qu’unbound ou unwind, etc. Si vous voulez gérer un nom de domaine et que vous souhaitez le faire depuis votre système, c’est ce qu’il vous faut.
Ce démon est un service NTP qui permet de garder l’horloge système à l’heure ; il peut utiliser des serveurs NTP ou des senseurs (tels des GPS) comme source de temps, mais aussi supporter des serveurs distants afin de challenger vos sources de temps. Il peut agir comme démon afin de fournir le temps aux autres clients NTP.
C’est un démon pour le protocole de routage OSPF. (Open Shortest Path First)
La version IPv6 du démon ci-dessus.
Ce démon reçoit les paquets depuis des règles PF correspondantes au mot clé
“log” et enregistrera les données dans un fichier journal qui peut être
réutiliser plus tard avec la commande tcpdump
.
Chaque paquet dans le fichier journal contient l’information sur quelle règle
l’a déclenché, ce qui est très pratique pour l’analyse.
Ce démon est utilisé en tant que partie de l’environnement NFS.
Ce démon est utilisé sur les routeurs IPv6 pour avertir des routes, ainsi les clients peuvent automatiquement les obtenir.
Ce démon est utilisé pour offrir le protocole d’authentification RADIUS.
Ce démon est utilisé pour les démarrages sans disque, qui aide à associer une adresse ARP à une adresse IP et un nom d’hôte.
Selon le manpage, il est dit “rboot répond aux demandes de démarrage d’une station de travail Hewlett-Packard sur le LAN”.
Ce démon est utilisé pour accepter les connexions entrantes et les distribue aux services en arrière plan. Il prend en charge beaucoup de protocoles et peut agir de manière transparente ; son but est d’avoir un frontend qui délivrera les connexionx à un liste de backend mais aussi de vérifier leurs statuts.
C’est un démon pour gérer la configuration du fichier /etc/resolv.conf
,
qui contient les détails des noms de serveurs à interroger - apparu sous OpenBSD 6.9 2
C’est un démon de routage utilisant un vieux protocole largement supporté.
La version IPv6 du service ci-dessus.
Ce démon est utilisé pour garder les passerelles IPSec synchronisées, en cas de repli nécessaire. Il peut être utilisé avec les dispositifs carp.
Ce démon a pour propos de sauvegarder un core dump du système d’exploitation.
Ce démon recueille les informations de surveillance venant du matériel tel la température ou le status du disque. Si une vérification excède un niveau, une commande peut être exécutée.
Ce service est un démon qui obtiendra automatiquement une configuration IPv6 sur le réseau.
Ce démon est utilisé pour exposer un programme CGI en tant que service FastCGI, permettant au serveur HTTP httpd d’exécuter du CGI. C’est l’équivalent d’inetd pour FastCGI.
Ce démon est le serveur SMTP qui sera utilisé pour délivrer des mails localement ou vers un serveur mails distant.
C’est un démon gérant le son depuis de nombreuses sources. Il prend en charge l’envoi de son local vers un serveur sndiod distant.
Ce démon est un serveur SNMP exposant certaines métriques système à un client SNMP.
Ce démon agit comme un faux serveur qui délaiera, bloquera ou laissera passer des courriels selon certaines règles. Il peut être utilisé pour ajouter une adresse IP à une liste de blocage, qui essaie d’envoyer un courriel à une adresse spécifique (tel qu’un “pot de miel”), de transmettre des courriels depuis des serveurs figurant dans une liste d’acceptation ou de délayer des connexions depuis des serveurs inconnus (liste grise) pour qu’ils se reconnectent plusieurs fois avant de transmettre le mail au serveur SMTP. C’est un moyen assez efficace d’empêcher le spam, mais perd de sa pertinence lorsque l’envoyeur utilise de larges ensembles d’adresses IP pour envoyer des courriels, signifiant que si vous essayer de recevoir un mail depuis un gros serveur, vous bloquerez le serveur X.Y.Z.1, mais X.Y.Z.2 essaiera et ainsi de suite, résultat aucun ne passera la liste grise.
Ce démon est dédié pour la mise à jour de liste d’acceptation de spamd .
C’est le bien connu serveur SSH. Permettre les connexions sécurisés vers
un shell depuis un client distant. Il a beaucoup de fonctionnalités qui
gagneraient à être connues, telles que les commandes de restriction par
clé publique dans les fichiers ~/.ssh/authorized_keys
ou SFTP permettant
seuls les accès chrootés.
Ce démon est utilisé dans un environnement NFS gérant lockd afin de vérifier si l’hôte distant est toujours en vie.
Ce démon est utilisé pour contrôler un pseudo dispositif de commutation;
C’est le serveur de journalisation qui reçoit les messages depuis les
programmes locaux et les enregistrent en accord avec le fichier journal.
Il peut être configuré pour capturer certains messages depuis des commandes,
des programmes tels que sshlockout qui utilise cette méthode pour apprendre
quelle adresse IP doit être bloquée, mais peut aussi écouter sur le réseau
afin d’aggréger les journaux d’autres machines.
Le programme newsyslog
est utilisé pour faire une rotation des fichiers
(déplacer un fichier, le compresser et permettre la création d’un nouveau
et supprimer aussi les anciennes archives). Un script peut utiliser la
commande logger
pour envoyer du texte au syslog.
Ce démon est le serveur TFTP, utilisé afin de fournir des noyaux sur le réseau pour les machines sans disques ou pousser des fichiers aux appareils.
Ce démon est utilisé pour manipuler le parefeu PF afin de relayer les requêtes TFTP vers un serveur TFTP.
Ce démon est un serveur DNS récursif ; c’est le type de serveur listé dans
le fichier /etc/resolv.conf
qui est responsable de traduire un nom de
domaine pleinement qualifié à l’adresse IP correspondante, en demandant
un serveur à la fois, par exemple en demandant le serveur www.dataswamp.org,
il est requis de demander au serveur faisant autorité .org où est le serveur
faisant autorité pour dataswamp (faisant partie du domaine supérieur .org),
puis le serveur DNS dataswamp.org sera interrogé pour savoir quelle est
l’adresse IP de www.dataswamp.org.
Il peut aussi garder les requêtes en cache et valide les requêtes et les
réponses ; c’est une bonne idée d’avoir un tel serveur sur un LAN ayant
beaucoup de clients pour lesquels partager un cache de requêtes.
Ce démon est un serveur DNS récursif local qui fera de son mieux pour donner des réponses valides ; il est conçu pour les utilisateurs nomades qui peuvent rencontrer des environnements hostiles tels que des portails captifs ou un serveur DNS par DHCP empêchant le fonctionnement de DNSSEC, etc. unwind interroge certaines sources DNS (récursif à partir des serveurs racines, fourni par DNS, stub ou un serveur DoT depuis un fichier de configuration) régulièrement et choisit le plus rapide. Il agira aussi comme cache local et ne peut écouter sur le réseau pour ne pas être utilisé par d’autres clients. Il prend en charge aussi une liste bloquante de domaines en entrée.
C’est le démon qui permet d’exécuter des machines virtuelles utilisant vmm. Depuis OpenBSD 6.4, il est capable de faire fonctionner des invités OpenBSD et Linux, sans interface graphique, et avec un seul cœur.
Ce démon est utilisé pour déclencher les timers watchdog, s’il y en a.
Ce démon est utilisé pour fournir la prise en charge de la souris à la console.
Ce démon est utilisé pour démarrer le serveur X et permettre aux utilisateurs leur propre authentification et se connecter à leur session.
Ce démon est utilisé avec un serveur de Pages Jaunes (YP pour garder et maintenir un fichier d’informations.
Ce démon offre un service YP en utilisant un backend LDAP .
Ce démon est un serveur YP.
FIN
Retrouvez ci-dessous la traduction EN → FR de l’article “OpenBSD: getting started”, écrit par Solène Rapenne.
Ceci est un guide pour les débutants sous OpenBSD ; j’espère que cet article deviendra une ressource utile pour aider les gens à se familiariser avec ce système d’exploitation que j’adore. Je vais utiliser beaucoup de liens parce que je préfère me référer à la documentation officielle.
Si vous êtes nouveau sous OpenBSD, vous êtes bienvenue, ce guide est pour vous. Si vous ne l’êtes pas, et bien, vous pourriez apprendre plusieurs choses.
Cet article n’a pas pour propos d’expliquer comment installer OpenBSD. Il y a assez de documentation officielle pour cela.
Ainsi, vous avez installé OpenBSD ; maintenant vous devez choisir d’activer X (l’interface graphique au démarrage) et vous avez face à vous un terminal sur un fond gris. Plusieurs choses deviennent intéressant ici.
Vous allez souvent avoir besoin d’utiliser le compte root pour diverses commande ou modifier des fichiers systèmes.
$ su -l
Vous allez devoir entrer le mot de passe root (défini lors de l’installation)
afin de changer d’utilisateur. Si vous tapez la commande “whoami
”, alors
vous devriez voir “root” comme résultat.
Quand vous installez le système (ou le mettez à jour), vous aurez un courriel
dans le compte root ; vous pouvez le lire par l’usage de la commande “mail
”.
C’est un mail venant de Theo De Raadt (fondateur d’OpenBSD) vous remerciant.
Vous remarquerez que ce courriel contient des indications, et a basiquement le même propos que mon article - celui que vous êtes en train de lire. Une page de manuel importante à lire est afterboot(8).
afterboot(8)Si vous ne savez pas ce qu’est un manpage (ou une page de manuel), c’est
vraiment le moment de l’apprendre parce que vous en aurez besoin. Quand
quelqu’un dit un “man page
”, cela implique “une page de manuel”.
La documentation dans OpenBSD est faite de pages de manuels relatifs à de
nombreux logiciels, concepts ou fonctions du langage C.
Pour lire un manpage, tapez dans un terminal (ou une console) “man afterboot
”,
et utilisez les flèches de votre clavier (ou les touches page haut ou bas)
à l’intérieur du manpage. Vous pouvez lire le “man man
” à-propos du manpage man.
Précédemment, j’ai écrit “afterboot(8)” mais le nom réel du manpage est
“afterboot”, le “(8)” permet de spécifier la section du manpage.
Certains mots peuvent être utilisé dans des contextes variés, selon la section
où ils sont placés. Par exemple, il y a sysctl(2) qui est la documentation
des appels systèmes “sysctl()”, là où sysctl(8) vous donnera les informations
à-propos de la commande sysctl afin de changer des paramètres noyaux.
Vous pouvez spécifier quelle section vous désirez lire en tapant le numéro
avant le nom de la page, tel que “man 2 sysctl
” ou “man 8 sysctl
”.
Les manpages sont construits de la même manière : NAME, SYNOPSIS, DESCRIPTION… SEE ALSO… ; la section “SEE ALSO” est une section importante, qui vous donne en références d’autres manpages que vous pouvez lire. Par exemple, afterboot(8) vous donne les indications à-propos de doas(1), pkg_add(1), hier(7) et beaucoup d’autres pages.
Maintenant, vous devriez être capable d’utiliser les pages de manuels.
Si vous voulez installer un environnement de bureau, il vous est offert un “meta paquet” qui récupérera tous les paquets requis pour que l’environnement fonctionne.
OpenBSD fournit certains environnements de bureau, tels que :
Gnome 3 => pkg_add gnome
Xfce => pkg_add xfce
MATE => pkg_add mate
Quand vous installez un paquet utilisant la commande “pkg_add
”, vous aurez
peut-être un message final vous informant qu’il y a un fichier à lire dans le
répertoire /usr/local/share/doc/pkg-readmes/ ; ces fichiers sont spécifiques
aux paquets et contiennent des instructions qu’il faut lire avant d’utiliser
un paquet.
Ces instructions peuvent être relatives à la performance, à des problèmes potentielles de limites, des bouts de configuration, comment initier le service, etc… Il est très important de les lire, et dans le cas d’un environnement de bureau, ils vous diront tout ce qu’il faut savoir pour le faire démarrer.
Quand vous vous connectez depuis l’écran de connexion de xenodm (celui où vous avez le poisson globe et le logo OpenBSD qui vous demande votre identifiant et mot de passe de connexion), le programme xenodm lira votre fichier ~/.xsession, là où vous avez préparez votre environnement de bureau et les commandes à exécuter. Habituellement, la première commande bloquante (celle qui continue de s’exécuter au premier plan) est votre gestionnaire de fenêtres ; vous pouvez placez des commandes avant, afin de paramétrer votre système ou d’exécuter des programmes en arrière-plan.
# désactiver bell
xset b off
# auto blank après 10 minutes
xset s 600 600
# exécuter xclock et xload
xclock -geometry 75x75-70-0 -padding 1 &
xload -nolabel -update 5 -geometry 75x75-145-0 &
# charger le fichier ~/.profile file pour définir ENV
. ~/.profile
# afficher des notifications
dunst &
# charger des changements dans les paramètres du serveur X
xrdb -merge ~/.Xresources
# diminuer la couleur bleue
sct 5600
# synchroniser les tampons de copie
autocutsel &
# kdeconnect pour contrôler un smartphone Android
kdeconnect-indicator &
# réduire le son par défaut
sndioctl -f snd/1 output.level=0.3
# le compositeur pour dessiner plus rapidement les fenêtres
picom &
# certains paramètres pour ma souris
xset mouse 1 1
xinput set-prop 8 273 1.1
# exécuter mon gestionnaire de fenêtres
fvwm2
C’est une question vraiment récurrente : comment faire pour que les alias de votre shell fonctionnent une fois que vous vous êtes connecté ? Pour les shells bash, sh, et ksh (et peut-être d’autres shells), à chaque fois que vous créez un nouveau shell interactif (dans lequel vous pouvez entrer des commandes), la variable d’environnement ENV sera lue et si sa valeur correspond à un chemin de fichier, il sera chargé.
La conception de votre environnement shell préféré est la suivante :
le fichier ~/.xsession qui sourcera le fichier ~/.profile lors du démarrage de X, héritant du contenu de tout ce qui est exécuté à partir de X
le fichier ~/.profile qui exportera ENV tel que “export ENV=~/.myshellfile
”
Si vous avez un ordinateur commun (architecture amd64), vous voudrez exécuter le service “apmd” en mode automatique ; il maintiendra votre CPU à la fréquence la plus basse et augmentera la fréquence lorsque vous aurez une certaine charge, ce qui permettra de réduire la chaleur, la consommation d’énergie et le bruit.
Voici les commandes à exécuter en tant que root :
# rcctl enable apmd
# rcctl set apmd flags -A
# rcctl start apmd
Pour faire simple, la version “-release” est l’ensemble des fichiers pour
installer OpenBSD dans cette version quand elle sort. D’autres mises à jour
pour cette version sont appelés la branche -stable ; si vous exécutez
“pkg_add -u
” pour mettre à jour vos paquets et “syspatch
” pour mettre
à jour la base de votre système, vous suivrez automatiquement la branche
stable (ce qui est bien !). Release est un état unique à un moment précis
de l’état d’OpenBSD.
Pas de steam ; c’est propriétaire et ne peut être exécuter sous OpenBSD.
Pas de wine ; cela requiert des changements dans le noyau.
Pas de pilote nvidia ; cela pourrait fonctionner mais avec le pilote VESA, cela sera vraiment très lent.
Il n’y a pas d’émulation Linux.
S’il n’est pas Open Source et n’utilise pas un langage tel Java ou C# qui utilise une Machine Virtuelle de Langage, calque d’abstratction pour fonctionner, il ne fonctionnera pas (et la plupart des programmes ne sont pas ainsi).
S’il est Open Source, cela peut être possible si toutes ses dépendances sont disponibles pour OpenBSD.
OpenBSD est livré avec une alternative à sudo nommé “doas” dans le système de base, mais sudo peut être installé en tant que paquet.
Vous pouvez vérifier le répertoire des paquets depuis un miroir ou visitez :
Le système de virtualisation d’OpenBSD peut exécuter OpenBSD et certaines distributions Linux mais sans interface graphique et avec un seul CPU. Cela signifie que vous aurez à configurer une console série afin de procéder à l’installation puis d’utiliser ssh ou la console série pour utiliser votre système.
qemu est dans les ports mais il n’est pas accéléré et ne correspondra pas aux besoins de la plupart des personnes car il est terriblement lent.
FIN
FLoC est une nouvelle technique de pistage développée par Google…
Ajoutez la règle suivante :
match response header set "Permissions-Policy" value "interest-cohort=()"
La faille HTTPoxy utilise l’entête HTTP non standardisée, non conforme, nommée PROXY. Pour en savoir plus sur cette faille : https://httpoxy.org
Pour la bloquer, il faut modifier votre filtre httpfilter
, en ajoutant :
match request header remove "Proxy"
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Il y a quelques semaines, j’ai écris l’article sur la gestion des images webp par nginx .
Actuellement, un récent format d’image apparaît, le format AVIF . Ainsi les images compressées dans ce format sont encore plus légères que le format Webp (bien sûr, généralement, cela dépend fortement des taux de qualités de compression utilisés).
Actuellement seules les versions des clients suivants prennent en charge ce format AVIF :
image.avif.enabled
sur true
dans la configuration…Bref, cela nécessite d’installer sur votre système d’exploitation la bibliothèque nécessaire :
qui installera principalement le binaire avifenc
dont nous avons besoin.
Malheureusement, sous De(bi|vu)an Stable, il semble manquer le support de la libyuv, ce qui empêchera bien des images d’être converties !
$ avifenc --help
(…)
Version: 0.8.4 (dav1d [dec]:0.7.1, libgav1 [dec]:0.16.1)
libyuv : unavailable
Heureusement, il existe le programme cavif, écrit en langage Rust. Reste plus qu’à télécharger la version .deb fournie : https://github.com/kornelski/cavif-rs/releases
ImageMagick est aussi capable de convertir une image au format AVIF :
$ convert "${file}" "${file}.avif"
Mais il semble qu’il faille attendre les versions 7.x pour que ce soit correctement géré !
Bien-sûr, il existe d’autres logiciels capable de convertir au format AVIF. Au dernière nouvelle, Gimp 2.10.x en est capable.
Il est ainsi possible de transformer les images gif, jpg, png et tiff.
La génération de l’image au format AVIF peut prendre un certain temps, plus ou moins considérable, selon les options choisies et le poids de l’image source à convertir !
$ avifenc -s 0 --min 25 --max 35 "${file}" "${file}.avif"
$ cavif --quality 50 "${file}" --output "${file}.avif"
--overwrite
, soit vous veillez à le supprimer avant.Modifions la configuration de nginx, afin de lui signifier que quand il est demandé des images au format jpeg|gif|png|tiff, il essaye de diffuser celles au format AVIF, si elles existent.
⇒ Dans le contexte http
du serveur :
/etc/nginx/mime.types
, ajoutons la déclaration image/avif avif;
map
afin de déclarer une variable $avif_suffix
qui nous
permettra de reconnaître une image ayant l’extension .avif
.map $http_accept $avif_suffix {
avif_suffix "";
"~*avif" ".avif";
}
⇒ Modifions le contexte server
, préalablement modifié pour le support webp
:
location ~ /*.(jpe?g|gif|png|tiff)$ {
access_log off;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
add_header Pragma public;
add_header Vary "Accept-Encoding";
expires max;
log_not_found off;
try_files $uri$avif_suffix $uri$webp_suffix $uri =404;
}
Et ajoutons lui ce nouveau bloc location
:
location ~ /*.(gif|jpe?g|png|tiff).avif {
access_log off;
add_header Cache-Control "public, must-revalidate, proxy-revalidate, max-age=31536000";
add_header Content-Type image/avif;
add_header Pragma public;
add_header Vary "Accept-Encoding";
default_type image/avif;
expires max;
# try_files $uri$avif_suffix $uri =404;
types {
image/avif avif;
}
}
Et, voilà !!!
Reste plus qu’à tester votre configuration avec nginx et redémarrer le service correspondant - par exemple, pour OpenBSD :
# nginx -t
# rcctl restart nginx
Pour finir, modifiez votre code HTML à-propos de la gestion des images, tel que, par exemple pour une image jpeg, à minima :
<picture>
<source srcset="/img/{{ $img }}.jpg.avif" type="image/avif">
<source srcset="/img/{{ $img }}.jpg.webp" type="image/webp">
<img alt="texte" src="/img/{{ $img }}.jpg" type="image/jpeg">
</picture>
Ce qui permettra aux clients web qui supportent le format AVIF de demander l’affichage de ce format en lieu et place…
Test avec mon Logo :
Ainsi, selon le support du client web, vous recevrez soit le format webp, soit avif, sinon le fichier “source” png…
@Lord et son article qui m’a fait découvrir ce format d’image…
Pour rappel, l’hyperviseur vmm(4) sous OpenBSD n’a pas de support vidéo pour les VM invités. Seule la console série est prise en charge.
Quand vous faites de la virtualisation sous OpenBSD amd64 ou i386, OpenBSD
gère tout ce qu’il faut, comme de nécessaire. Ainsi la console série est
configurée au sein du fichier de configuration /etc/boot.conf
et le dispositif
tty00
est configuré correctement pour utiliser ladite console série.
Le problème est quand vous avez l’idée de créer votre VM, sous Linux par
exemple, à moins de spécifiquement répondre yes
lorsqu’est demandé le
paramétrage de com0
, il est possible de se retrouver avec le problème
suivant :
Pas d’écran de connexion == pas de login possible !
(où il y en a des malchanceux, et d’autres où ça roule sans soucis… je suis souvent de la première catégorie)
Pour illustrer le propos, une fois la VM OpenBSD copiée sur un hôte OpenBSD, voici le démarrage :
$ vmctl start -c vm-test
Using drive 0, partition 3.
Loading......
probing: pc0 com0 mem[638K 1022M a20=on]
disk: hd0+
>> OpenBSD/amd64 BOOT 3.52
boot>
booting hd0a:/bsd: 14329128+3191816+337072+0+872448 [999468+128+1135344+859361]=0x14ba488
entry point at 0xffffffff81001000
[ using 2995336 bytes of bsd ELF symbol table ]
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.
Copyright (c) 1995-2020 OpenBSD. All rights reserved. https://www.OpenBSD.org
OpenBSD 6.8 (GENERIC) #4: Mon Jan 11 10:34:36 MST 2021
root@syspatch-68-amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC
real mem = 1056956416 (1007MB)
avail mem = 1010040832 (963MB)
random: good seed from bootblocks
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.4 @ 0xf3f40 (10 entries)
bios0: vendor SeaBIOS version "1.11.0p3-OpenBSD-vmm" date 01/01/2011
bios0: OpenBSD VMM
acpi at bios0 not configured
cpu0 at mainbus0: (uniprocessor)
cpu0: AMD FX-8320E Eight-Core Processor, 3211.59 MHz, 15-02-00
cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,CX8,SEP,PGE,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,SSE3,PCLMUL,SSSE3,FMA3,CX16,SSE4.1,SSE4.2,POPCNT,AES,XSAVE,AVX,F16C,HV,NXE,MMXX,FFXSR,PAGE1GB,LONG,LAHF,CMPLEG,EAPICSP,AMCR8,ABM,SSE4A,MASSE,3DNOWP,OSVW,IBS,XOP,SKINIT,WDT,FMA4,TCE,NODEID,TBM,TOPEXT,CPCTR,ITSC,BMI1
cpu0: 64KB 64b/line 2-way I-cache, 16KB 64b/line 4-way D-cache, 2MB 64b/line 16-way L2 cache, 8MB 64b/line 64-way L3 cache
cpu0: ITLB 48 4KB entries fully associative, 24 4MB entries fully associative
cpu0: DTLB 64 4KB entries fully associative, 64 4MB entries fully associative
cpu0: smt 0, core 0, package 0
pvbus0 at mainbus0: OpenBSD
pvclock0 at pvbus0
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "OpenBSD VMM Host" rev 0x00
virtio0 at pci0 dev 1 function 0 "Qumranet Virtio RNG" rev 0x00
viornd0 at virtio0
virtio0: irq 3
virtio1 at pci0 dev 2 function 0 "Qumranet Virtio Network" rev 0x00
vio0 at virtio1: address fe:e1:bb:d1:a9:7b
virtio1: irq 5
virtio2 at pci0 dev 3 function 0 "Qumranet Virtio Storage" rev 0x00
vioblk0 at virtio2
scsibus1 at vioblk0: 1 targets
sd0 at scsibus1 targ 0 lun 0: <VirtIO, Block Device, >
sd0: 51200MB, 512 bytes/sector, 104857600 sectors
virtio2: irq 6
virtio3 at pci0 dev 4 function 0 "OpenBSD VMM Control" rev 0x00
vmmci0 at virtio3
virtio3: irq 7
isa0 at mainbus0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns8250, no fifo
com0: console
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
scsibus3 at softraid0: 256 targets
root on sd0a (6dc570f70e2c7991.a) swap on sd0b dump on sd0b
Automatic boot in progress: starting file system checks.
/dev/sd0a (6dc570f70e2c7991.a): file system is clean; not checking
/dev/sd0m (6dc570f70e2c7991.m): file system is clean; not checking
/dev/sd0d (6dc570f70e2c7991.d): file system is clean; not checking
/dev/sd0f (6dc570f70e2c7991.f): file system is clean; not checking
/dev/sd0g (6dc570f70e2c7991.g): file system is clean; not checking
/dev/sd0h (6dc570f70e2c7991.h): file system is clean; not checking
/dev/sd0j (6dc570f70e2c7991.j): file system is clean; not checking
/dev/sd0i (6dc570f70e2c7991.i): file system is clean; not checking
/dev/sd0e (6dc570f70e2c7991.e): file system is clean; not checking
/dev/sd0k (6dc570f70e2c7991.k): file system is clean; not checking
/dev/sd0l (6dc570f70e2c7991.l): file system is clean; not checking
pf enabled
kern.seminfo.semmni: 10 -> 60
kern.seminfo.semmns: 60 -> 1024
starting network
reordering libraries: done.
starting early daemons: syslogd pflogd nsd ntpd.
starting RPC daemons:.
savecore: no core dump
checking quotas: done.
clearing /tmp
kern.securelevel: 0 -> 1
creating runtime link editor directory cache.
preserving editor files.
starting network daemons: sshd smtpd.
starting local daemons: cron.
Thu Feb 18 12:25:45 CET 2021
Et, voilà cela s’arrête à l’affichage de l’heure… et vous allez pouvoir attendre longtemps l’écran de connexion de session qui ne viendra jamais !
Et, au cas où tu te le demandes, toi lecteur, non cela ne vient pas d’une corruption de la VM lors de la copie/synchronisation, des tests à base de somme de contrôle sha256 ont été faits avant la copie et après celle-ci, tel que :
Sur la station Linux :
$ cat vm-test.qcow2.sha256
73054a89bb2e0b13d78e8cb446424baa01f7761099d8681a59137655b28c979c vm-test.qcow2
Puis sur l’hôte OpenBSD :
$ sha256 vm-test.qcow2
SHA256 (vm-test.qcow2) = 73054a89bb2e0b13d78e8cb446424baa01f7761099d8681a59137655b28c979c
$ sha256 -C vm-test.qcow2.sha256 vm-test.qcow2
(SHA256) vm-test.qcow2: OK
Mais alors que faire ?!
Sur ton OS source, par exemple le Linux où la VM a été créée, avec qemu et les différents outils virt*, connectes-toi à ta VM, et fais les deux petites modifications suivantes nécessaires :
Le fichier de configuration /etc/boot.conf
n’a pas été créé - s’il l’est,
vérifies l’écriture. Il doit absolument contenir à minima ceci :
set tty com0
Par défaut, le taux de connexion est ainsi de 9200 baups.
Or, étant donné que le futur hôte est OpenBSD, faisons ça bien :
stty com0 115200
set tty com0
Ainsi nous configurons le taux de débit au maximum supporté, soit de 115200.
L’autre modification nécessaire à faire est de reparamétrer les informations d’initialisation du Terminal tty00.
Le fichier est /etc/ttys
, et il faut commenter/supprimer la ligne correspondante
à tty00 pour ajouter la déclaration correcte suivante :
tty00 "/usr/libexec/getty std.115200" vt220 on secure
Si vous déclarez le fichier boot.conf
ci-dessus a sa valeur par défaut,
configurez cette déclaration ainsi :
tty00 "/usr/libexec/getty std.9600" vt220 on secure
Et, voilà !
Une fois la VM recopiée sous OpenBSD, vous aurez à nouveau l’écran de connexion.
@jggimi…
La virtualisation sous OpenBSD, disponible depuis 5.9, est assez aisée à mettre en place, à partir du moment où on fait attention à certains détails.
Cet article traite de la partie de la virtualisation où hôte et invité(s) sont sur le même réseau, et offrira en sus ce que ne restitue pas la FAQ officielle (ou sa traduction [FR][2]).
En premier, toujours vérifier et s’assurer de la compatibilité du processeur de votre machine :
$ dmesg | egrep '(VMX/EPT|SVM/RVI)'
La réponse du système doit être :
⇒ pour CPU Intel :
vmm0 at mainbus0: VMX/EPT
⇒ pour CPU AMD :
vmm0 at mainbus0: SVM/RVI
Si aucune ligne n’apparaît, aucune virtualisation ne sera possible. Par acquis de conscience, vérifiez votre BIOS|UEFI que celle-ci ne soit pas désactivée.
De même, en rapport avec les failles CPU relatives à Meltdown, Spectre, certains CPU Intel sont patchés pour remédier à L1TF. Sous OpenBSD, ces CPU reçoivent un correctif approprié. Malheureusement, cela impacte la virtualisation et peut rendre celle-ci impossible. Vous pouvez vous retrouver dans la situation où vous auriez un CPU compatible, mais dans les faits, la virtualisation ne pourrait être pleinement fonctionnelle.
Préférez AMD, en attendant ARM…
Après avoir téléchargé l’image instalXX.iso
de la dernière version d’OpenBSD
puis l’avoir vérifié - oui, préférez l’image iso, et lors de l’installation,
choisissez cd0
au lieu de http
, elle se fera plus vite car ira chercher
les jeux d’installation sur votre média.
⇒ Créons simplement une VM :
$ vmctl create -s 50G disk.qcow2
⇒ Démarrons l’installation :
# vmctl start -c -m 1G -i 1 -r installXX.iso -d disk.qcow2 test
Il est important de déclarer une interface réseau, au moins avec l’option
-i
lors de cette étape. Cela va permettre d’allouer automatiquement une
interface tap(4) à la VM.
Pour la virtualisation de VM sur le même réseau que l’hôte, n’utilisez pas
l’option -L
qui déclare une interface locale, empêchant de communiquer
avec le bridge. Il faudrait dans ce cas-là, faire de la traduction d’adresses
réseaux, configurer sysctl, etc. - Avouez, ce serait dommage.
Faites votre installation, et au bout de quelques minutes, à la fin de
celle-ci choisissez [halt]
pour arrêter proprement l’OS dans la VM.
Puis déconnectez-vous de celle-ci, par exemple par les caractères d’échappement
~.
ou ~~.
si SSH.
Une autre raison pour laquelle il vaut mieux arrêter la VM : si vous ne le faites pas, vous allez redémarrer celle-ci sans soucis… mais vous n’aurez pas de réseau ; ne cherchez pas à à modifier vos paramètres réseaux, vous pouvez quand même vérifier l’adresse IP de votre passerelle/routeur, ainsi que résolveur DNS que vous avez paramétré.
L’astuce est simplement de configurer le fichier /etc/vm.conf
de l’hôte,
puis de (re)démarrer le service vmd, et ensuite de redémarrer la VM.
Normalement, là, vous devriez avoir du réseau… dans votre VM.
En admettant que :
Ce sont les paramètres réseaux à fournir dans les VM.
Les configurations suivantes se font sur l’hôte :
Seuls les périphériques Ethernet, non Wifi, peuvent être utilisés.
Utilisez dhcp peut compliquer les choses, préférez l’usage d’adresse IP statique.
Partons du contexte où votre interface réseau est gérée par le pilote réseau Intel em(4).
Si ce n’est pas votre cas, modifiez en conséquence.
Modifions le fichier /etc/hostname.em0
, pour l’exemple :
inet 192.168.1.2
Le fichier de configuration est : /etc/vm.conf
switch "sw" {
interface bridge0
}
vm "test" {
disk /home/vous/disk.qcow2 format qcow2
enable
memory 1G
interface { switch "sw" }
owner vous
}
Configurons le pont :
# echo 'add em0' > /etc/hostname.bridge0
# sh /etc/netstart bridge0
Et, voilà !
Sauf que… ce dont ne parle pas la FAQ, a un rapport étroit avec PF, principalement.
Autre information importante que ne restitue pas la FAQ est que lorsque la VM est active, une interface tap est créée et montée dans le bridge. Du moins, c’est compréhensible au-travers de la lecture des différents manpages.
Selon les notes du manpage relatif à bridge, paramétrer PF pour gérer le bridge est possible, mais il faut être très fin dans ces réglages et avoir une excellente compréhension du flux réseau au sein de PF.
Faisons au plus simple, sur le fichier de configuration de PF de l’hôte :
⇒ Gérons le groupe d’interface tap en autorisant tout le flux :
pass on tap
L’avantage de gérer le groupe tap est de ne pas avoir à gérer finement toutes les interfaces tap liées à chacune des VM. En effet, chaque VM aura sa propre interface tap. La première aura l’interface tap0, la seconde aura tap1, etc.
Dans ces cas, il faudrait déclarer pour chaque interface, par exemple pour tap0 :
pass on tap0
⇒ Ensuite, il faut gérer d’abord votre interface réseau, qui pour l’exemple est em0, au cas par cas selon le flux que vous désirez permettre en entrée depuis l’hôte vers l’IP de la VM.
Là encore, pour simplifier, déclarer une table comprenant l’adresse IP de chaque VM, telle que :
table <vm_tap> const { 192.168.1.3 192.168.1.4 }
Puis par exemple pour autoriser le flux à destination de SSH vers les VM :
pass in log on em0 inet proto tcp from any to <vm_tab> port 22
Bien sûr, ces règles PF sont minimalistes, en soit. À vous de les granuler plus finement, selon vos besoins et selon les services à accéder.
Pour finir, pensez à gérer vos règles PF au sein de la VM, elle-même. ;-)
Par défaut, OpenBSD fournit 4 pseudo-interfaces virtuelles tap. En cas, où vous nécessitez de plus de VM que ces 4 disponibles par défaut, il est nécessaire de créer le nombre d’interface supplémentaire.
Lire la note suivante… pour bien comprendre l’allocation automatique des interfaces virtuelles.
Il faudra utiliser MAKEDEV(8), par exemple :
# sh MAKEDEV tap5
De même, il est possible d’assigner tel pseudo-dispositif virtuel tap, à telle VM, utilisez pour cela le mot clé interface dans votre fichier de configuration, tel que par exemple :
vm "test" {
(…)
interface tap5 { … }
(…)
}
Autre point à bien comprendre est que tant que la VM n’est pas active,
l’interface tap correspondante ne sera pas créée ni montée au sein du
bridge. Faites la comparaison avec la commande ifconfig
avant puis
après… et vous comprendrez ;-)
Non, il n’y a pas besoin de configurer sysctl pour rediriger (forward) le flux. Nous ne faisons pas de la traduction d’adresses réseaux, autrement appelée NAT. Ce serait le cas et le besoin dans le contexte de bridge où les VM auraient leur propre réseau différent de celui de l’hôte.
Le rappel est fait dans la section suivante de la page de manuel vmctl :
If NAT is desired, the net.inet.ip.forwarding sysctl(8) must also be set to 1.
Donc, non, dans le contexte de bridge où l’hôte et les invités sont sur le même bateau, pas besoin de forwarder le flux !
Merci de lire la documentation officielle FAQ Virtualisation (EN) afin de bien comprendre le sujet, les différentes informations nécessaires à une meilleure préhension de celui-ci.
Il est fortement intéressant de lire les pages de manuels, en anglais, relative à :
dmesg
:
vmx_fault_page: uvm_fault returns 14, GPA=0xffffca78, rip=0xfbd49
Enjoy-IT!
Enjoy-ID!
Retrouvez ci-dessous la traduction EN → FR de l’article “What security does a default OpenBSD installation offer?”, écrit par Solène Rapenne.
Dans ce texte, j’expliquerais ce qui rend OpenBSD sécurisé par défaut quand vous l’installez. Ce n’est pas une analyse de la sécurité, mais plutôt un guide pour vous aider à comprendre ce qui est fait pour qu’OpenBSD soit un environnement sécurisé. Le but est ce texte n’est pas de comparer OpenBSD à d’autres OS mais de vous dire ce que vous pouvez attendre honnêtement d’OpenBSD.
Il n’y a pas de sécurité sans modèle de gestion des menaces. Je considère toujours les cas suivants : un ordinateur volé à domicile, une attaque à distance qui essaye d’exploiter les services fonctionnant, un exploit au-travers des clients réseaux.
Voici une liste de fonctionnalités que je considère importante pour la sécurité du système d’exploitation. Bien que tous les éléments de la liste suivante ne sont pas à strictement parlé des fonctionnalités de sécurité, ils aident à obtenir un système strict qui empêche le logiciel de mal se comporter ou les risques inconnus.
Mon opinion relative à la sécurité n’est pas seulement de prévenir les attaques à distances de pénétrer le système, mais aussi d’empêcher les programmes ou les utilisateurs de rendre le système inutilisable.
Pledge et unveil sont souvent cités ensembles bien qu’ils puissent être utilisés indépendamment. Pledge est un système d’appels pour restreindre les permissions d’un programme au sein de son code source, permissions qui ne peuvent pas être annulées une fois l’appel à pledge. Unveil est un système d’appels qui cache tout le système de fichiers au processus excepté les chemins qui ne sont pas surveillés ; il est possible de choisir quelles permissions sont appliquées aux chemins.
Les deux sont de puissants outils de sécurité “chirurgicaux” mais ils requièrent quelques modifications dans le code source d’un programme, et les ajouter requiert une profonde compréhension de ce que fait le logiciel. Il n’est pas toujours possible d’interdire les appels systèmes d’un logiciel qui exige de faire presque tout ; un logiciel conçu avec la séparation des privilèges est un meilleur candidat pour l’ajout propre de pledge, ainsi chaque partie fait son travail.
Certains logiciels parmi les paquets prennent en charge pledge et/ou unveil, tel que Chromium ou Firefox, pour les plus connus.
La plupart des services du système de base d’OpenBSD fonctionnent selon le modèle de séparation des privilèges. Chaque part d’un démon est restreint au minimum requis. Un démon monolithique devrait lire, écrire des fichiers, accepter des connexions réseaux, envoyer des messages au système de journalisation, dans le cas d’une brèche de sécurité qui offre une énorme surface d’attaque. En séparant un service en de multiples parties, cela permet un contrôle plus fin de chacun des processus, et en utilisant les appels systèmes de pledge et unveil, il est possible de paramétrer les limites et de réduire hautement les dommages en cas où un processus est attaqué.
Le démon du serveur est démarré par défaut afin de synchroniser l’horloge avec des serveurs de temps. Un serveur TLS référant est utilisé pour interroger les serveurs de temps. Garder un ordinateur avec son horloge synchronisée est très important. Ce n’est pas réellement une fonctionnalité de sécurité mais vous ne pouvez pas être sérieux si vous utilisez un ordinateur sur le réseau qui n’ait pas son temps synchronisé.
si vous utilisez le serveur X, il abandonne les privilèges à l’utilisateur
_x11
; le serveur est exécuté avec les droits d’un utilisateur
sans privilèges au lieu de root, ainsi en cas de problèmes de sécurité
cela empêche un attaquant d’accéder au-travers de bogues de X11 à plus
qu’il ne devrait.
Les limites de ressources par défaut empêchent un programme d’utiliser trop de mémoire, d’ouvrir trop de fichier ou trop de processus. Bien que cela puisse empêcher que certains gros programmes de s’exécuter avec les paramètres par défaut, cela aide aussi à trouver les failles de descripteurs de fichiers, prévenant ainsi une bombe dérivée ou un simple démon de capturer toute la mémoire jusqu’au crash.
Quand vous installez OpenBSD selon le mode de chiffrement complet de disque, tout sera verrouillé par une passphrase à l’étape du chargeur de démarrage, ainsi vous ne pouvez accéder au noyau ou à d’autres parties du système sans la passphrase.
La plupart des programmes dans OpenBSD n’ont pas l’autorisation de cartographier la mémoire avec un bit d’Exécution et d’Écriture en même temps (W^X signifie Écrire et/ou Exécuter), cela peut empêcher un interpréteur d’avoir sa mémoire et modifiée et exécutée. Certains paquets ne sont pas conformes à cela et doivent être liés à une bibliothèque spécifique qui contourne cette restriction ET doivent être utilisés depuis une partition ayant l’option de montage “wxallowed”.
Lorsque votre système requiert un nombre de données aléatoires (et c’est souvent le cas), OpenBSD fournit seulement une seule API pour obtenir ces données aléatoires, qui sont réellement aléatoires et ne peuvent être devinées. Un bon générateur de nombres aléatoires (RNG) est important pour de nombreuses exigences en matière de cryptographie.
OpenBSD est fournit avec une documentation complète dans ses pages de manuels. On doit pouvoir configurer entièrement son système en utilisant seulement les pages de manuels. Les pages de manuels sont fournis parfois avec des sections CAVEATS ou BUGS ; il est important de bien faire attention à ces sections. Il est mieux de lire la documentation et de comprendre ce que cela fait avant de configurer un système au lieu de suivre un anonyme texte obsolète disponible sur Internet.
Si vous avez besoin de paramétrer un VPN, vous pouvez utiliser nativement les protocoles IPSec ou Wireguard, sans aucun autre paquet requis.
OpenBSD a de nombreuses mesures de sécurités à-propos de l’allocation de la mémoire et empêchera son utilisation après libération ou un usage très agressif de mémoire non sûre, souvent sources de crash pour certains logiciels fournis en tant que paquets puisqu’OpenBSD est très strict sur l’utilisation de la mémoire que vous faites. Cela aide à trouver les utilisations abusives de la mémoire et à arrêter les mauvais comportements logiciels.
Lorsque vous installez le système, un compte root est créé et son mot de passe est demandé, puis vous créez un utilisateur qui sera membre du groupe “wheel”, permettant de basculer l’utilisateur vers root avec le mot de passe de root. doas (l’équivalent sudo d’OpenBSD) n’est pas configuré par défaut. Avec l’installation par défaut, le mot de passe root est requis pour toute interaction root. Je pense qu’un compte root dédié qui peut être journalisé sans l’usage de doas ou sudo est mieux qu’une mauvaise configuration de doas ou sudo permettant ainsi de faire des choses seulement si vous connaissez le mot de passe utilisateur.
Les seuls services qui pourraient être activés dès l’installation, écoutant sur le réseau, sont OpenSSH (demandé lors de l’installation, avec par défaut sur yes), dhclient (si vous choisissez dhcp) et slaacd (si vous utilisez IPv6 en configuration automatique).
Par défaut, la swap d’OpenBSD est chiffrée, ce qui signifie que si la mémoire des programmes est envoyée vers la swap, nul ne pourra la déchiffrer plus tard.
Dû fait d’un très grand nombre de failles de sécurité sur SMT (tel que l’HyperThreading), l’installation par défaut désactive les cœurs logiciels afin de prévenir toutes fuites de données.
Avec l’installation par défaut, les microphones et webcam ne peuvent actuellement rien enregistrer excepté du bruit blanc à moins que vous configuriez sysctl pour cela.
L’équipe d’OpenBSD publie une nouvelle version tous les six mois, et seules les deux dernières versions reçoivent les mises à jours de sécurité. Cela permet de mettre à jour sans douleur ; le processus de mise à jour est constitué de petites étapes deux fois par an, ce qui aide à garder l’ensemble du système à jour. Cela évite la crainte d’une mise à jour massive, de ne jamais la faire et je considère que c’est un énorme bonus de sécurité. La plupart des OpenBSD fonctionnent sur les versions les plus récentes.
L’installateur, les archives et les paquets sont signés en utilisant les clés publiques et privées de signify. Les installations d’OpenBSD sont fournies avec les versions de clés de la version courante et n+1 afin de vérifier l’authenticité des paquets. Une clé est utilisée seulement six mois et de nouvelles clés sont reçues à chaque nouvelle sortie permettant de construire une chaîne de confiance. Les clés Signify sont très petites et sont publiées dans de nombreux médias afin de permettre une double vérification si vous avez besoin de vous assurer de cette chaîne de confiance.
Alors que la plupart des éléments précédents concernaient le système de base ou le noyau, les paquets ont également quelques astuces à offrir.
La plupart des démons qui sont disponibles offrent une fonctionnalité de chroot qui sera activée par défaut. Dans certaines circonstances, tel que pour le serveur web Nginx, le logiciel est patché par l’équipe OpenBSD afin d’activer chroot qui n’est pas une fonctionnalité officielle.
La plupart des paquets qui fournissent un serveur crée aussi un utilisateur dédié exactement à ce service, permettant la séparation des privilèges en cas de problèmes de sécurité dans le service.
Lorsque vous installez un service, celui-ci n’est pas activé par défaut.
Vous allez devoir configurer le système pour l’activer au démarrage.
Il y a un unique fichier /etc/rc.conf.local
qui peut être utilisé pour
voir ce qui est actif au démarrage, qui peut être manipulé par l’utilisation
de la commande rcctl
.
Forcer l’utilisateur à activer les services oblige l’administrateur système
à être pleinement attentif à ce qui est exécuté dans le système, ce qui
est un bon point pour la sécurité.
La plupart des “fonctionnalités de sécurité” vues devraient être considérées comme de bonnes pratiques et non pas comme des fonctionnalités. Beaucoup des bonnes pratiques suivantes pourraient être facilement mises en œuvre : Limiter les ressources utilisateurs, réduire les privilèges des démons, être strict dans l’utilisation de la mémoire, fournir une bonne documentation, démarrer le strict minimum requis de services et fournir à l’utilisateur une installation par défaut propre qui peut être personnalisé plus tard.
Il y a aussi de nombreuses autres fonctionnalités qui ont été ajoutées, que je ne comprend pas pleinement ; je préfère laisser au lecteur le soin d’en prendre connaissance.
Sous OpenBSD, il est possible de surveiller l’état de son|ses disque(s) dur(s), nativement par le biais de l’outil atactl, qui reste basique, mais fait le job.
Néanmoins concentrons-nous sur le projet smartmontools… qui est disponible en tant que paquet.
Installez le paquet smarmontools.
Le fichier de configuration est /etc/smartd.conf
.
Selon l’emplacement de votre disque dur, il peut être intéressant de le paramètrer ainsi :
/dev/sd0c -a -o on -S on -s (S/../.././02|L/../../7/03)
Qui :
⇒ Syntaxe :
la syntaxe entre parenthèses est : T/MM/DD/d/HH
Où :
⇒ Activation du démon logiciel :
# rcctl enable smartd
# rcctl start smartd
⇒ Obtenir les informations du disque dur :
# smartcl -i /dev/sd1c
Exemple :
$ doas smartctl -i /dev/sd1c
smartctl 7.1 2019-12-30 r5022 [x86_64-unknown-openbsd6.8] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF INFORMATION SECTION ===
Model Family: SAMSUNG SpinPoint F1 DT
Device Model: SAMSUNG HD103UJ
Serial Number: S13PJ9CZ200215
LU WWN Device Id: 5 0024e9 201ee0406
Firmware Version: 1AA01118
User Capacity: 1,000,204,886,016 bytes [1.00 TB]
Sector Size: 512 bytes logical/physical
Device is: In smartctl database [for details use: -P show]
ATA Version is: ATA/ATAPI-7, ATA8-ACS T13/1699-D revision 3b
Local Time is: Fri Feb 19 12:27:52 2021 CET
SMART support is: Available - device has SMART capability.
SMART support is: Enabled
⇒ Exécuter un test smart court :
# smartctl -t short /dev/sd1c
Exemple :
$ doas smartctl -t short /dev/sd1c
smartctl 7.1 2019-12-30 r5022 [x86_64-unknown-openbsd6.8] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===
Sending command: "Execute SMART Short self-test routine immediately in off-line mode".
Drive command "Execute SMART Short self-test routine immediately in off-line mode" successful.
Testing has begun.
Please wait 2 minutes for test to complete.
Test will complete after Fri Feb 19 12:30:26 2021 CET
Use smartctl -X to abort test.
⇒ Exécuter un test smart long :
# smartctl -t long /dev/sd1c
Exemple :
$ doas smartctl -t long /dev/sd1c
smartctl 7.1 2019-12-30 r5022 [x86_64-unknown-openbsd6.8] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===
Sending command: "Execute SMART Extended self-test routine immediately in off-line mode".
Drive command "Execute SMART Extended self-test routine immediately in off-line mode" successful.
Testing has begun.
Please wait 228 minutes for test to complete.
Test will complete after Fri Feb 19 17:00:35 2021 CET
Use smartctl -X to abort test.
⇒ Vérifier rapidement les erreurs :
# smartctl -l error /dev/sd1c
Exemple correct :
$ doas smartctl -l error /dev/sd1c
smartctl 7.1 2019-12-30 r5022 [x86_64-unknown-openbsd6.8] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF READ SMART DATA SECTION ===
SMART Error Log Version: 1
No Errors Logged
⇒ Vérifier les résultats des auto-test :
# smartctl -l selftest /dev/sd1c
Exemple correct :
$ doas smartctl -l selftest /dev/sd1c
smartctl 7.1 2019-12-30 r5022 [x86_64-unknown-openbsd6.8] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Short offline Completed without error 00% 21190 -
Exemple avec erreur :
$ doas smartctl -l selftest /dev/sd1c
smartctl 7.1 2019-12-30 r5022 [x86_64-unknown-openbsd6.8] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Short offline Completed: read failure 20% 20826 1800697692
# 2 Short offline Completed without error 00% 20817 -
Ici l’auto-test ne va pas jusqu’au bout de l’analyse.
⇒ Afficher la température du disque :
# smartctl -l scttemp /dev/sd1c
Exemple :
$ doas smartctl -l scttemp /dev/sd1c
smartctl 7.1 2019-12-30 r5022 [x86_64-unknown-openbsd6.8] (local build)
Copyright (C) 2002-19, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF READ SMART DATA SECTION ===
SCT Status Version: 2
SCT Version (vendor specific): 256 (0x0100)
Device State: Active (0)
Current Temperature: 27 Celsius
Power Cycle Min/Max Temperature: --/27 Celsius
Lifetime Min/Max Temperature: --/55 Celsius
SCT Temperature History Version: 2
Temperature Sampling Period: 1 minute
Temperature Logging Interval: 1 minute
Min/Max recommended Temperature: -4/72 Celsius
Min/Max Temperature Limit: -9/77 Celsius
Temperature History Size (Index): 128 (29)
Index Estimated Time Temperature Celsius
30 2021-02-19 10:47 24 *****
31 2021-02-19 10:48 23 ****
32 2021-02-19 10:49 23 ****
33 2021-02-19 10:50 24 *****
34 2021-02-19 10:51 23 ****
35 2021-02-19 10:52 23 ****
36 2021-02-19 10:53 23 ****
37 2021-02-19 10:54 24 *****
38 2021-02-19 10:55 23 ****
39 2021-02-19 10:56 24 *****
⇒ Afficher les données complètes :
# smartctl -a /dev/sd1c
$ man smartd smartd.conf
Gemini et Gopher sont deux autres Internet, tout à fait légaux, dont le but est de la publication “légère” d’informations, principalement du texte. En fait, historiquement Gopher est né en 1991, en parallèle du Grand Net sur protocole HTTP ; tandis que Gemini est un protocole de communication récent, né courant juin 2019.
Tout comme le Grand Net sur HTTP(S), Gopher et Gemini ont leur propre protocole de communication, portant leur propre nom :
gemini://
gopher://
À savoir que le protocole gemini est basé sur TLS directement… De plus, bien que ces protocoles soient cloisonnés entre eux, en effet les protocoles Gemini, Gopher et HTTP(S) sont des réseaux différents, par des services différents, sur des ports différents, il existe des passerelles du côté de Gemini et Gopher, vers HTTP(S).
Ne cherchez pas toutes les fioritures que permet le protocole HTTP(S), exit les scripts CSS, JS, voire les images, avec Gemini et Gopher, on se concentre principalement sur la ressource importante : le texte. cf : cherchez Low Web ;-)
Comment modifier Hugo pour lui faire générer des fichiers à publier sur les protocoles Gemini, et Gopher ?
Dans les faits, vous prendrez plus de temps à lire cet article, qu’à faire vos modifications basiques, qui sont possibles d’être faites en moins de 5 minutes !!!
Il y a(ura) certainements de petites modifications à apporter… mais l’esprit de l’article est là, et fonctionnel. ;-)
ATTENTION : les modifications ci-dessous actuellement sont fonctionnelles dans le contexte d’une configuration basique de Hugo.
Dans le cas d’un site multi-langue, ou que vous avez paramétré la variable
permalinks.posts
, le résultat attendu n’aura pas lieu.
Dans les faits, le repertoire géré par la variable path
est lié au répertoire
de sortie. Ainsi dans le contexte multilangue, vous retrouverez dans chaque
répertoire de langue un répertoire nommé selon le protocole cible !
Ainsi, vous aurez dans le répertoire public/
, d’abord les répertoires de
langue, puis le répertoire gemini
ou gopher
.
Alors que dans une configuration basique, le répertoire gemini
ou gopher
sera directement déposé à la racine du répertoire public/
.
Concernant les modifications pour Gemini, voici le propos :
Modifions très simplement le fichier de configuration de Hugo config.toml
:
# Gemini
[mediaTypes."text/gemini"]
suffixes = ["gmi"]
# Gemini
[outputFormats.Gemini]
isPlainText = true
isHTML = false
mediaType = "text/gemini"
name = "gemini"
path = "gemini/"
permalinkable = true
protocol = "gemini://"
Remarquons que la publication des fichiers gmi auront lieu dans un répertoire
distinct, nommé gemini, dans le répertoire public/
.
Ce seront de purs fichiers texte, ayant l’extension .gmi
.
Puis dans la configuration de la sortie, par exemple :
[outputs]
home = ["HTML", "gemini", …]
page = ["HTML", "gemini", …]
Bien sûr, ne pas utiliser les ‘…’ dans votre configuration ; ici, ils expriment les autres options de génération possible, sans les nommer !
Gemini est capable de lire des fichiers au format RSS, ce qui nous permet de générer un flux RSS ; ajoutons un nouveau format de sortie spécifique :
[outputFormats.GeminiRSS]
isHTML = false
mediaType = "application/rss+xml"
name = "GeminiRSS"
protocol = "gemini://"
path = "gemini/"
et modifions la génération de sortie, tel que par exemple :
[outputs]
home = ["HTML", "gemini", "GeminiRSS", …]
Ajoutons un fichier index.gmi
dans le repertoire layouts/
, qui pour
l’exemple aura le code hugo basique suivant :
{{ range .Paginator.Pages }}
{{- if .OutputFormats.Get "gemini" }}
⇒ {{ replace .Permalink "/gemini" "" 1 }} {{ .Date.Format "January 2, 2006" }}: {{ .Title | safeHTML }}{{ end }}{{ end }}
Libre à vous de modifier, améliorer la pertinence du code Hugo pour obtenir le contenu que vous désirez publier…
Si vous désirez gérez un flux RSS pour Gemini, selon la configuration ci-dessus,
ajoutons un fichier index.geminirss.xml
, ayant le contenu de génération
tel que :
{{- $pctx := . -}}
{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
{{- $pages := slice -}}
{{- if or $.IsHome $.IsSection -}}
{{- $pages = $pctx.RegularPages -}}
{{- else -}}
{{- $pages = $pctx.Pages -}}
{{- end -}}
{{- $limit := .Site.Config.Services.RSS.Limit -}}
{{- if ge $limit 1 -}}
{{- $pages = $pages | first $limit -}}
{{- end -}}
{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ .Site.Title | safeHTML }}</title>
<link>{{ replace .Permalink "https" "gemini" 1 }}</link>
<description>{{ .Site.Params.siteDescription | safeHTML }}</description>
<generator>Hugo {{ hugo.Version }} gohugo.io</generator>{{ with .Site.LanguageCode }}
<language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
<managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
<webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
<copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
<lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
{{ with .OutputFormats.Get "RSS" }}
{{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
{{ end }}
{{ range $pages }}
{{- if .OutputFormats.Get "gemini" -}}
<item>
<title>{{ .Title | safeHTML }}</title>
{{ with .OutputFormats.Get "gemini" }}
<link>{{replace .Permalink "/gemini" "" 1}}</link>
{{ end }}
<pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
{{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
{{ with .OutputFormats.Get "gemini" }}
<guid>{{replace .Permalink "/gemini" "" 1}}</guid>
{{ end }}
</item>
{{- end -}}
{{ end }}
</channel>
</rss>
Dans le répertoire enfant _default
du sous répertoire layouts/
, ajoutons
un simple fichier single.gmi
qui s’occupera principalement de la génération
des pages :
# {{ $.Title | safeHTML }}
{{ .RawContent }}
C’est basique ; ca fait le boulot, simplement. Là encore libre à vous de modifier, ajouter votre code Hugo, pour générer plus proprement afin de débarrasser du code Markdown, par exemple :
{{ $scratch := newScratch }}
{{ $content := .RawContent -}}
{{ $content := $content | replaceRE `#### ` "### " -}}
{{ $content := $content | replaceRE `\n- (.+?)` "\n* $1" -}}
{{ $content := $content | replaceRE `\n(\d+). (.+?)` "\n* $2" -}}
{{ $content := $content | replaceRE `\[\^(.+?)\]:?` "" -}}
{{ $content := $content | replaceRE `<br/??>` "\n" -}}
{{ $content := $content | replaceRE `<a .*href="(.+?)".*>(.+?)</a>` "[$2]($1)" -}}
{{ $content := $content | replaceRE `\sgemini://(\S*)` " [gemini://$1](gemini://$1)" -}}
{{ $content := $content | replaceRE "([^`])<.*?>([^`])" "$1$2" -}}
{{ $content := $content | replaceRE `\n\n!\[.*\]\((.+?) \"(.+?)\"\)` "\n\n=> $1 Image: $2" -}}
{{ $content := $content | replaceRE `\n\n!\[.*]\((.+?)\)` "\n\n=> $1 Embedded Image: $1" -}}
{{ $links := findRE `\n=> ` $content }}{{ $scratch.Set "ref" (add (len $links) 1) }}
{{ $refs := findRE `\[.+?\]\(.+?\)` $content }}
{{ $scratch.Set "content" $content }}{{ range $refs }}{{ $ref := $scratch.Get "ref" }}{{ $contentInLoop := $scratch.Get "content" }}{{ $url := (printf "%s #%d" . $ref) }}{{ $contentInLoop := replace $contentInLoop . $url -}}{{ $scratch.Set "content" $contentInLoop }}{{ $scratch.Set "ref" (add $ref 1) }}{{ end }}{{ $content := $scratch.Get "content" | replaceRE `\[(.+?)\]\((.+?)\) #(\d+)` "$1 [$3]" -}}
{{ $content | safeHTML }}
Explications :
Ce code - qui fait très bien son travail - est un copié-collé du code créé par un certain Wouter Groeneveld ; les explications sont fournies en anglais. N’ayant pas l’utilité de gérer des fichiers audio, vidéo, localement ou sur d’autres plateformes, j’ai simplement supprimé les lignes correspondantes.
Voilà (pour la partie Gemini) !
Il ne reste plus qu’à publier…
Attaquons les modifications de configurations et de calques pour générer
les fichiers textes pour Gopher. Là encore, nous générons les fichiers
dans un répertoire dédié, nommé gopher dans le répertoire public/
afin de faciliter la synchronisation vers le serveur gopher…
Modifions donc le fichier de configuration de Hugo, pour ajouter les formats de génération. En effet :
Tous auront l’extension de fichier .txt
et seront publiés dans un sous-répertoire
nommé gopher du répertoire public/
.
[outputFormats.Gopher]
baseName = "index"
isPlainText = true
isHTML = false
mediaType = "text/plain"
noUgly = false
path = "gopher/"
protocol = "gopher://"
[outputFormats.GopherMap]
baseName = "gophermap"
isPlainText = true
isHTML = false
mediaType = "text/plain"
noUgly = false
path = "gopher/"
protocol = "gopher://"
Puis modifions la génération des sorties, tel que :
[outputs]
home = ["HTML", "gemini", "GeminiRSS", "gophermap", …]
page = ["HTML", "gemini", "gopher"]
Attaquons la partie des fichiers à créer dans le sous-répertoire layouts/
.
Restons simple :
{{ .Site.Title | safeHTML }}
⇒ Menu :
{{ range .Site.Menus.main }}
{{- if (or (eq .Identifier "search") (eq .Identifier "lang-switcher") (eq .Identifier "theme-switcher") ) }}
{{- else }}
1{{ .Name }} {{ .URL | safeURL }} 70
{{- end -}}
{{ end }}
⇒ Articles les plus récents :
{{ $nb := 7 }}
{{ range first $nb .Paginator.Pages }}
0{{ .Title }} {{ with .OutputFormats.Get "gopher" }} {{ replaceRE "/gopher" "" .RelPermalink }} 70 {{ end }}
{{- end }}
Ce fichier gophermap nous permet de publier simplement l’équivalent
du menu principal de Hugo, ainsi que promouvoir les x
derniers
articles. - ici, les 7 derniers -
Pour ceux qui n’auraient pas compris : les fichiers gophermap sont des fichiers d’indexation de contenu…
Ajoutons dans le répertoire enfant _default/
du sous-répertoire layout/
,
un fichier de génération de liste, qui peut avoir le contenu basique suivant :
!{{ .Title | safeHTML }}
{{ .RawContent }}
{{ range .Paginator.Pages }}
0{{ .Title }} {{ with .OutputFormats.Get "gopher" -}}{{ .RelPermalink }} {{ $.Site.Params.hostname}} 70 {{ end }}
{{ end }}
Pour la génération des pages, ajoutons dans le même sous-répertoire _default/
,
un fichier nommé single.gopher.txt
qui peut avoir le contenu basique suivant :
!{{ .Title | safeHTML }}
{{ .Date.Format (.Site.Params.dateform | default "01 January 2006") }} · {{ .ReadingTime }} minute(s) de lecture.
{{ if .Params.tags }}
Tags : {{ range .Params.tags }}{{ . }} {{ end }}
{{ end }}
---
{{ .RawContent }}
---
Publié le : {{.Date.Format "2 January 2006"}}.
0⇒ Revenir à la page d'accueil : / 70
h⇒ Lire l'article “{{ $.Title | safeHTML }}” sur le protocole HTTP(S) : {{ .Permalink | safeURL }} 443
Le contenu de ce site est diffusé sous Licence {{ $.Site.Copyright | safeHTML }}.
Encore une fois, à vous de modifier à votre convenance et autres imaginations nécessaires pour votre promotion…
Voilà (pour la partie Gopher) !
Il ne reste plus qu’à publier…
Retrouvez ci-dessous la traduction EN → FR de l’article “Host your Cryptpad web office suite with OpenBSD”, écrit par Solène Rapenne.
Dans cet article, j’expliquerai comment déployer votre propre instance de Cryptpad sous OpenBSD. Cryptpad est une suite web office permettant de collaborer en temps réel sur des documents. Cryptpad est écrit en JavaScript et le démon agit en tant que serveur web.
Vous avez besoin d’installer les paquets git, node, automake et autoconfig afin d’être capable de récupèrer les sources et d’exécuter le programme.
# pkg_add node git autoconf--%2.69 automake--%1.16
Un autre logiciel en amont est requis pour assurer les connexions TLS et sécuriser les accès réseaux à l’instance Cryptpad. Cela peut être relayd, haproxy, nginx ou lighttpd. Je couvre le paramétrage en utilisant httpd, et relayd. Notez que les développeurs de Cryptpad ne fournissent du support que seulement pour les utilisateurs de Nginx.
Je recommande réellement l’utilisation d’utilisateur dédié au service. Nous créerons un nouvel utilisateur par la commande :
# useradd -m _cryptpad
Ensuite, nous continuerons l’installation logiciel avec l’utilisateur
_cryptpad
.
# su -l _cryptpad
Nous suivrons principalement le guide d’installation officiel à certaines exceptions près afin d’adapter à OpenBSD :
$ git clone https://github.com/xwiki-labs/cryptpad
$ cd cryptpad
$ env AUTOMAKE_VERSION=1.16 AUTOCONF_VERSION=2.69 CC=clang CXX=clang++ npm install
$ env AUTOMAKE_VERSION=1.16 AUTOCONF_VERSION=2.69 CC=clang CXX=clang++ npm install bower
$ node_modules/.bin/bower install
$ cp config/config.example.js config/config.js
Voici les quelques variables importantes à personnaliser :
https://cryptpad.kongroo.eu
.https://api.cryptpad.kongroo.eu
.Nous avons besoin d’automatiser le démarrage proprement, en même temps que celui du système.
Créez le fichier /etc/rc.d/cryptpad
:
#!/bin/ksh
daemon="/usr/local/bin/node"
daemon_flags="server"
daemon_user="_cryptpad"
location="/home/_cryptpad/cryptpad"
. /etc/rc.d/rc.subr
rc_start() {
${rcexec} "cd ${location}; ${daemon} ${daemon_flags}"
}
rc_bg=YES
rc_cmd $1
Activez et démarrez le service avec le contrôleur rcctl
:
# rcctl enable cryptpad
# rcctl start cryptpad
Enregistrez-vous sur votre instance Cryptpad puis allez à la page “Settings” de votre profil : copiez votre clé public de signature.
Éditez le fichier config.js
et cherchez adminKeys
; décommentez la section
en supprimant les /*
et */
autour, puis supprimez la clé d’exemple pour
copier la vôtre, tel ce qui suit :
adminKeys: [
"[solene@cryptpad.kongroo.eu/YzfbEYwZq6Xhl7ET6AHD01w3QqOE7STYgGglgSTgWfk=]",
],
Redémarrez Cryptpad ; l’utilisateur est maintenant administrateur et a accès au nouveau panel d’administration depuis l’application web.
Vous avez besoin de sauvegarder les répertoires data
et datastore
qui
sont dans le répertoire de Cryptpad.
Dans cette section, j’expliquerai comment générer votre certificat TLS avec acme-client et comment configurer httpd et relayd pour publier cryptpad. Je considère cela en plus de l’actuel article, car si vous utilisez déjà nginx, et avez une installation pour générer des certificats, vous n’en avez pas besoin. Si vous démarrez de zéro, c’est la manière la plus simple pour obtenir un résultat.
À partir de là, je considère que vous utilisez OpenBSD et que vos fichiers de configuration sont vierges.
J’utiliserai pour l’exemple le domaine kongroo.eu.
Nous utiliserons httpd d’une manière trés simple. Il écoutera seulement sur le port 80 pour tous les domaines, permettant à acme-client de fonctionner et redirigera aussi automatiquement les requêtes HTTP vers HTTPS.
# cp /etc/examples/httpd.conf /etc/httpd.conf
# rcctl enable httpd
# rcctl start httpd
Nous utiliserons le fichier exemple par défaut :
# cp /etc/examples/acme-client.conf /etc/acme-client.conf
Éditez le fichier /etc/acme-client.conf
et changez le dernier bloc domain
;
remplacez example.com
et secure.example.com
par votre domaine, tels que
cryptpad.kongroo.eu
et api.cryptpad.kongroo.eu
en tant que nom alternatif.
Pour des raisons pratiques, nous allons remplacer le chemin du certificat
full chain pour avoir hostname.crt
au lieu de hostname.fullchain.pem
pour correspondre aux attentes de relayd.
Voici à quoi ressemble ce paragraphe sur mon paramétrage :
domain kongroo.eu {
alternative names { api.cryptpad.kongroo.eu cryptpad.kongroo.eu }
domain key "/etc/ssl/private/kongroo.eu.key"
domain full chain certificate "/etc/ssl/kongroo.eu.crt"
sign with buypass
}
Notez qu’avec le fichier acme-client.conf par défaut, vous pouvez utiliser letsencrypt ou buypass en tant qu’autorité de certification.
Vous devriez maintenant être capable de créer vos certificats.
# acme-client kongroo.eu
C’est fait !
Vous souhaitez que le certificat soit renouvellé automatiquement et que
relayd redémarre après le changement de certificat ? Comme l’indique la
page de manuel d’acme-client.conf, ajoutez ce qui suit à la crontab de root
en utilisant la commande crontab -e
:
~ * * * * acme-client kongroo.eu && rcctl reload relayd
Cette configuration est assez simple : remplacez kongroo.eu
par votre
domaine.
Créez un fichier /etc/relayd.conf avec le contenu suivant :
tcp protocol "https" {
tls keypair kongroo.eu
}
relay "https" {
listen on egress port 443 tls
protocol https
forward to 127.0.0.1 port 3000
}
Activez et démarrez relayd en utilisant rcctl :
# rcctl enable relayd
# rcctl start relayd
Vous devriez être capable d’atteindre votre instance Cryptpad en utilisant maintenant votre URL publique. Félicitations !
Voyons dans cet article comment paramétrer OpenWRT pour qu’il puisse communiquer avec des serveurs DNS sur le protocole DoH .
Le but est de :
Installons les deux paquets nécessaires que sont https-dns-proxy, et luci-app-https-dns-proxy.
# opkg update
# opkg install https-dns-proxy luci-app-https-dns-proxy
Puis il faut redémarrer le service rcpd.
# /etc/init.d/rpcd restart
Le service est accessible par le menu “Services → HTTPS DNS Proxy”.
Paramétrez-le de manière à :
Puis, appuyez sur le bouton :
Ainsi le service sera actif, et prendra en charge la communication vers les serveurs DNS DoH configurés.
Il est possible de configurer le service par le biais de la console shell :
Voici l’exemple que donne la communauté OpenWRT :
# Configure DoH provider
while uci -q delete https-dns-proxy.@https-dns-proxy[0]; do :; done
uci set https-dns-proxy.dns="https-dns-proxy"
uci set https-dns-proxy.dns.bootstrap_dns="8.8.8.8,8.8.4.4"
uci set https-dns-proxy.dns.resolver_url="https://dns.google/dns-query"
uci set https-dns-proxy.dns.listen_addr="127.0.0.1"
uci set https-dns-proxy.dns.listen_port="5053"
uci commit https-dns-proxy
/etc/init.d/https-dns-proxy restart
Le paramétrage présenté est pour les serveurs DNS de Google…
Mais peut-être que vous préférerez utiliser DoT ; si oui, lisez : OpenWRT + Unbound : utiliser le protocole DoT
Enjoy-ID! Enjoy-IT!
Ici, il n’est pas question de demander au serveur web nginx de modifier/créer à la volée des images au format Webp.
Pour ceux qui ne savent pas ce qu’est le format WebP, sachez que c’est un conteneur d’image matricielle, développé par… Google. Il permet de faire d’obtenir des images plus légères, qu’elles ne le seraient au format Jpeg. cf: la section Documentation ci-dessous !
Bref, cela nécessite d’installer sur votre système d’exploitation la bibliothèque nécessaire :
ImageMagick est aussi capable de convertir une image au format webp :
$ convert "${file}" "${file}.webp"
Pour transformer une image jpg, png, voire tiff au format, il suffit d’appeler la bibliothèque cwebp, très simplement :
cwebp -m 0 -mt "${image}" -o "${image}.webp"
Quant aux images gif, elles sont converties grâce à la bibliothèque gif2wepb :
gif2webp -m 0 -mt "${image}" -o "${image}.webp"
Veuillez lire le manpage correspondant pour connaître les différentes options de la bibliothèque :
$ man cwebp
$ man gif2webp
Voici le code que j’utilise personnellement :
_webp() {
if [ ! -f "${file}.webp" ]; then
case "$(file -b "${file}")" in
'GIF'*)
gif2webp -m 0 -mt "${file}" -o "${file}.webp"
;;
'JPEG'|'PNG'|'TIFF'*)
cwebp -exact -lossless -m 0 -mt -progress "${file}" -o "${file}.webp"
;;
esac
fi;
}
Que fait ce code ?
Dans les faits, il teste :
.webp
Par soucis de simplicité et de lecture, il génére une image au format webp,
portant l’extension .webp
, ajouté à son nom de fichier originel, tel que
image.jpg.webp, pour l’exemple.
Tu verras, toi mon lecteur, que cela nous facilite la configuration de
nginx, par la suite.
Ensuite, je parcoure un répertoire d’image par le biais de la fonction
find
, qui appelle la fonction _webp
déclarée ci-dessus, tel que :
find . -type f -a \( \
-name "*.gif" -o -name '*.jpg' -o -name '*.jpeg' -o -name '*.png' -o -name '*.tiff' \
\) | while read -r file; do _webp; done
Voici le script shell que j’utilise :
Fichier : webp.bash
|
|
Celui-ci est aisément modifiable pour l’utiliser sous tout autre shell.
De deux manières l’une, j’utilise ce script soit en l’appelant individuellement, soit par le biais de mon script de déploiement de mes fichiers vers le serveur web.
Ainsi, en sus des images aux formats originels, j’y dépose celles au format webp. ;-)
Modifions la configuration de nginx, afin de lui signifier que quand il est demandé des images au format jpeg|gif|png|tiff, il essaye de diffuser celles au format webp, si elles existent.
⇒ Dans le contexte http
du serveur, ajoutons une map
afin de déclarer
une variable $webp_suffix
qui nous permettra de reconnaître une image
ayant l’extension .webp
.
map $http_accept $webp_suffix {
webp_suffix "";
"~*webp" ".webp";
}
⇒ Le script suivant est à inclure dans le contexte de la déclaration server
de votre configuration d’hôte virtuel.
Fichier : /etc/nginx/conf.d/images-webp
|
|
Ce que fait cette configuration ?
.webp
, suffixé au nom
de l’image appelée, sinon retourne logiquement une erreur 404.
remarque l’utilisation de la variable $webp_suffix
à la ligne 13..webp
:
Et, voilà !!!
Reste plus qu’à tester votre configuration avec nginx et redémarrer le service correspondant - par exemple, pour OpenBSD :
# nginx -t
# rcctl restart nginx
Pour finir, modifiez votre code html à-propos de la gestion des images, tel que, par exemple pour une image jpeg, à minima :
<picture>
<source srcset="/img/{{ $img }}.jpg.webp" type="image/webp">
<img alt="texte" src="/img/{{ $img }}.jpg" type="image/jpeg">
</picture>
Ce qui permettra aux clients web qui supportent le format webp de demander l’affichage de ce format en lieu et place…
Test avec mon Logo :
Ainsi, selon le support du client web, vous recevrez soit le format webp, sinon le fichier “source” png…
Pare-feu segmentant un réseau, avec DHCP, DNS (Unbound), blocage de domaine et bien plus encore.
Dans ce guide, nous verrons comment nous pouvons utiliser du matériel “bas de gamme” bon marché pour construire un routeur OpenBSD terrible avec des capacités de pare-feu, des réseaux locaux segmentés, du DNS avec blocage de noms de domaines, du DHCP et bien plus.
Nous commencerons par paramétrer les segments réseaux (LAN) par trois réseaux séparés, un pour les adultes à la maison, un pour les enfants et un pour les serveurs face à Internet (comme une DMZ), tel qu’un serveur web ou serveur mail privé. Nous chercherons à voir comment nous pouvons utiliser DNS pour bloquer les publicités, le porno, et d’autres sites sur Internet. Le routeur OpenBSD peut aussi être utilisé dans de petites ou moyennes entreprises.
largeur fixe
(mono-espacement) est utilisée pour les commandes
en console, les noms de fichiers et leurs chemins, les paramètres de
configuration, etc…root
sont préfixées du symbole dièse #
et la commande apparaît en
gras dans le texte.$
et la commande apparaît en
gras dans le texte.Peu importe comment vous vous connectez à Internet depuis votre domicile ou votre bureau, vous avez besoin d’un vrai pare-feu entre vous et le modem ou routeur que vous fourni votre FAI.
Il est très rare que les modems ou routeurs grand public reçoivent des mises à jour du micrologiciel et sont souvent vulnérables aux attaques réseau qui transforment ces appareils en Botnet, tel que le fait le logiciel malveillant Mirai. De nombreux modems et routeurs grand public sont à blâmer à propos de certaines attaques par déni de service de grande envergure (DOS)
Un pare-feu entre vous et le modem ou routeur de votre FAI ne peut pas protéger votre dispositif modem ou routeur contre de telles attaques, mais il peut protéger vos ordinateurs et dispositifs à l’intérieur du réseau, et il peut vous aider à surveiller et contrôler le trafic qui arrive vers votre réseau local et qui en part.
Sans un pare-feu entre votre réseau local et le modem ou routeur du FAI, vous pouvez considérer basiquement que votre porte est grande ouverte, comme laisser grande ouverte la porte de votre maison, ainsi vous ne pouvez pas faire confiance en l’équipement de votre FAI.
C’est toujours réellement une bonne idée de mettre un vrai pare-feu entre votre réseau local et Internet, et avec OpenBSD vous avez une solution très solide.
Vous n’avez pas besoin d’acheter du matériel cher pour avoir un routeur et un pare-feu efficaces pour votre maison ou votre bureau. Même avec du matériel “bas de gamme” bon marché, vous pouvez avoir une solution très solide.
J’ai créé de multiples solutions avec la carte-mère ASRock Q1900DC-ITX qui est fournie avec un processeur Intel Celeron Quadri-Cœur.
Je l’admet, c’est une carte-mère assez “pourrie”, mais elle fait le boulot et j’ai de nombreuses solutions très solides qui fonctionnent depuis de nombreuses années sur des réseaux Gigabit avec saturation complète et le pare-feu, DNS, faisant des “heures supplémentaires” et où le CPU ne chauffe pas.
La carte-mère ASRock Q1900DC-ITX a pour avantage qu’elle est fournie avec une prise jack DC-In (entrée électrique) qui est compatible avec un adaptateur électrique 9-19V, ce qui la rend très économe en énergie. Malheureusement, la carte-mère ASRock Q1900DC-ITX n’est plus fabriquée, mais comme je l’utilise juste comme exemple ; j’ai utilisé de nombreuses autres carte-mères bon marché tout aussi bien.
J’ai aussi utilisé l’ASRock Q1900-ITX (qui est fournie sans la prise jack DC-In) combinée à un PicoPSU.
Vous pouvez trouvez différentes marques et version du PicoPSU, certains sont de meilleurs qualités que d’autres. J’ai deux marques différentes, l’original et une copie moins chère, toutes deux sont très performants et permettent d’économiser par mal d’énergie contrairement à une alimentation normale.
Enfin, j’utilise une carte réseau quadruple port Intel bon marché, trouvé sur Ebay, tel que celle-ci :
Je sais, il est préférable d’utiliser du matériel de qualité, spécifiquement sur un réseau dont vous avez à prendre soin, mais ce tutoriel est relatif au fait de comment vous pouvez vous en sortir en utilisant du matériel bon marché tout en ayant un produit extrêmement utile qui continue à bien vous servir pendant de nombreuses années - du moins, telle est mon expérience.
Je vous recommande de chercher une carte mini-ITX dont le matériel est pris en charge par OpenBSD, tel qu’un CPU Intel Celeron ou Intel i3. Ces cartes-mères sont typiquement peu chères, peu gourmandes d’énergie, et ne prennent pas beaucoup de place. Je ne recommande pas l’utilisation d’un CPU Intel Atom si vous avez un réseau Gigabit, car il ne peut pas gérer la quantité de trafic.
Vous pourriez également avoir besoin de quelques commutateurs Gigabit bon marché pour segmenter votre réseau local, au moins si vous avez plus d’un ordinateur connecté sur le même LAN :)
En vérité, vous pouvez avoir le même paramétrage avec une autre saveur BSD ou une des différentes distributions Linux, mais OpenBSD est spécifiquement très bien adapté et conçu pour ce genre de tâche. Non seulement il est livré avec tous les logiciels nécessaires dans l’installation de base, mais il offre également une sécurité nettement supérieure, et des tonnes de mesure d’atténuation améliorées déjà intégrées dans le système d’exploitation. Je recommande chaudement OpenBSD plutôt que tout autre système d’exploitation pour ce genre de tâches.
Ce guide ne vous montre pas comment installer OpenBSD. Si vous ne savez pas faire, je vous recommande de faire fonctionner une machine virtuelle avant ou de voir si vous avez du matériel inutilisé et pris en charge avec lequel vous pourriez tester. OpenBSD est un des systèmes d’exploitations des plus faciles et rapides à installer. N’ayez pas peur de l’approche sans GUI (interface utilisateur) ; une fois que vous l’avez essayé, vous apprécierez vraiment sa simplicité. Dans le doute, utilisez les paramètres par défaut.
Avant de commencer ce voyage, assurez-vous de consulter la documentation d’OpenBSD ! Non seulement, chaque chose est très bien documentée, mais vous trouverez très probablement toutes les réponses dont vous avez besoin. Lisez la FAQ OpenBSD, regardez les différentes pages de manuels à propos des différents logiciels que nous allons utiliser.
Un autre endroit vraiment utile où trouver des informations générales à propos d’OpenBSD sont les archives des listes de diffusions d’OpenBSD. Aussi assurez-vous de rester à jour des informations pertinentes en souscrivant à la liste de diffusion des Annonces et avis de sécurité.
Un routeur est basiquement un dispositif qui régule le trafic réseau entre deux ou plusieurs réseaux séparés. Le routeur garantira que le trafic réseau à destination du réseau local ne circule pas sur Internet, et que le trafic sur Internet, qui n’est pas à destination de votre réseau local, reste sur Internet.
Dans ce tutoriel, nous construirons un routeur et nous avons 4 réseaux de même type à faire travailler ensemble. L’un est Internet, et les trois autres sont segmentés intentionnellement en réseaux locaux (LAN). Certaines personnes préfèrent travailler avec des LAN virtuels (VLAN), mais dans ce tutoriel nous utiliserons une interface réseau 4 ports, telle que vue sur l’illustration ci-dessus. Vous pouvez arriver au même résultat en utilisant de multiples cartes réseau à port unique, si vous préférez ; vous devez juste vous assurez d’avoir assez de place et de slot PCI libre sur la carte-mère. Vous pouvez aussi utiliser le port Ethernet de la carte-mère, mais cela dépend du pilote et de la prise en charge du dispositif. Je n’ai pas de problème à utiliser un contrôleur Ethernet Gigabit PCI Realtek qui est fourni avec beaucoup de carte-mères, bien que je recommande plutôt Intel.
Bien sûr, vous n’avez pas à segmenter le réseau en de nombreuses parties si vous n’avez pas besoin de cela, et il serait très facile de changer les paramètres de ce guide, mais j’ai décidé d’utiliser cette approche avant de vous montrer comment vous pouvez protéger vos enfants en segmentant leur réseau dans un LAN séparé qui permet non seulement de bloquer la publicité et la pornographie grâce au blocage des DNS (tous les segments en bénéficient), mais vous pouvez même mettre sur une liste blanche les partie de l’Internet auxquelles vous voulez qu’ils aient accès. La dernière partie à propos des listes blanches est difficile et n’est généralement pas recommandé à moins que vos enfants aient besoin d’un accès très limité, mais c’est faisable avec un peu de travail, et le guide va vous montrer une façon de faire.
Ceci est une illustration du réseau que nous allons paramétrer :
Les adresses IP qui commencent par 10.24.0 sont n’importe quelle adresse IP que le routeur ou modem de votre FAI vous donne ; elles peuvent être très différentes. Les adresses IP commençant par 192.168 sont les adresses IP que nous allons utiliser dans ce guide pour notre réseau local (LAN).
Ce guide ne s’occupe en aucun cas de connectivité Wifi. Les micrologiciels des puces sans fil sont notoirement bogués et exploitables ; je vous recommande de n’utiliser aucun type de connectivité sans fil, si vous pouvez vous en passer. Si vous avez besoin de la connectivité sans fil, je recommande chaudement que vous désactiviez l’accès Wifi du modem ou routeur du FAI (si possible), et ensuite d’acheter le meilleur routeur Wifi que vous pouvez trouver puis de le mettre derrière le pare-feu dans un segment isolé. Ainsi, si jamais votre appareil sans fil est compromis, vous pourrez mieux contrôler le résultat et limiter les dégâts. Vous pouvez en outre configurer le routeur sans fil de telle sorte que tout appareil, qui y est connecté, dispose de ses propres adresses IP qui passent directement par le routeur sans fil, tout en bloquant le trafic provenant du routeur sans fil lui-même. De cette façon, vous pouvez empêcher le routeur sans fil de “téléphoner à la maison”. Vous pouvez aussi avoir un adaptateur Wifi supporté par OpenBSD et que votre routeur OpenBSD agisse en tant que point d’accès, toutefois je préfère de beaucoup segmenter la partie Wifi soit par un routeur sans fil séparé, soit par une autre machine OpenBSD servant de point d’accès Wifi derrière le pare-feu lui-même.
La première chose que nous allons paramétrer sont les différentes interfaces réseaux de notre routeur OpenBSD. Sur ma machine, j’ai désactivé l’interface réseau qui est livré avec la carte-mère via le BIOS, et je n’utilise que l’interface réseau 4 ports d’Intel.
Si vous suivez ce tutoriel et que vous souhaitez seulement un pare-feu basique alors vous avez au moins besoin de deux interfaces réseaux séparées.
Avant de commencer, assurez-vous de lire et de comprendre les différentes options de la page de manuel hostname.if. Prenez aussi le temps de lire la section réseau de la FAQ d’OpenBSD.
Puisque j’utilise Intel, le pilote em est
celui qu’OpenBSD charge sur chacun des ports de cette interface réseau,
qui sont listés comme étant des cartes séparées.
Cela signifie que chaque carte est listée en tant qu’emX
où X est le
numéro actuel du port de la carte.
dmesg
liste ma carte réseau avec 4 ports de telle manière :
# dmesg
em0 at pci2 dev 0 function 0 "Intel I350" rev 0x01: msi, address a0:36:9f:a1:66:b8
em1 at pci2 dev 0 function 1 "Intel I350" rev 0x01: msi, address a0:36:9f:a1:66:b9
em2 at pci2 dev 0 function 2 "Intel I350" rev 0x01: msi, address a0:36:9f:a1:66:ba
em3 at pci2 dev 0 function 3 "Intel I350" rev 0x01: msi, address a0:36:9f:a1:66:bb
Ce qui montre que ma carte est reconnu comme étant une Intel I350-T4 PCI Express Quad Port Gigabit NIC.
Il faut ensuite déterminer quel est le port correspondant physiquement au numéro indiqué ci-dessus. Vous pouvez le faire en connectant manuellement un câble Ethernet, connecté sur un commutateur actif, un modem ou un routeur, sur chacun des ports, un à la fois, afin de voir quel port est activé et le noter ensuite quelque part.
Vous pouvez vérifier le statuts d’activité avec la commande ifconfig
.
Un port sans câble Ethernet sera listé comme ayant le champ status
notifié
no carrier
alors qu’un port avec un câble attaché sera listé en active
.
Tel que :
# ifconfig
em1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr a0:36:9f:a1:66:b9
index 2 priority 0 llprio 3
media: Ethernet autoselect (none)
status: active
em2: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr a0:36:9f:a1:66:ba
index 3 priority 0 llprio 3
media: Ethernet autoselect (none)
status: no carrier
Nous allons utiliser le port em0
afin de le connecter au modem ou routeur
de votre FAI, vers Internet.
Dans mon cas, j’ai une adresse IP publique fournie par mon FAI ; vous en
aurez besoin si vous voulez faire fonctionner un serveur web depuis votre
maison, mais si ce n’est pas le cas, vous n’en avez pas besoin, ainsi vous
pouvez paramétrer la carte par DHCP.
Dans mon cas, j’ai besoin de spécifier une adresse IP fixe pour em0
qui
recevra alors le trafic redirigé depuis mon FAI vers mon adresse IP publique.
Pour faire cela, je paramètre em0
avec l’information suivante :
# echo 'inet 10.24.0.50 255.255.254.0 NONE' > /etc/hostname.em0
Si vous n’avez pas besoin d’une adresse IP publique et que votre adresse
IP est obtenue par votre FAI via DHCP, alors écrivez juste dhcp
à la place :
# echo 'dhcp' > /etc/hostname.em0
Ensuite, je paramètre le reste des ports de l’interface réseau avec leurs adresses IP, tel que je l’ai précédemment illustré.
# echo 'inet 192.168.1.1 255.255.254.0 NONE' > /etc/hostname.em1
# echo 'inet 192.168.2.1 255.255.254.0 NONE' > /etc/hostname.em2
# echo 'inet 192.168.3.1 255.255.254.0 NONE' > /etc/hostname.em3
Regardez la page du manuel hostname.if pour avoir plus d’informations.
Ensuite, j’ai besoin de paramétrer l’IP de la passerelle du FAI.
Selon le paramétrage de votre FAI, cela peut être une autre adresse IP que
celle du modem ou routeur du FAI.
Si vous n’ajoutez pas le fichier /etc/mygate
alors aucune passerelle par
défaut ne sera ajouté à la table de routage.
Vous n’avez pas besoin de /etc/mygate
si votre IP est fournie par le
modem ou routeur de votre FAI via DHCP.
Si vous utilisez la directive dhcp
dans n’importe quel fichier hostname.ifX
alors l’entrée dans le fichier /etc/mygate
sera ignorée.
Cela est parce que la carte obtient son adresse IP depuis un serveur DHCP
qui fournira aussi l’information de routage vers la passerelle.
Enfin, mais pas des moindres, nous avons besoin d’activer la redirection IP. La redirection IP est le processus qui dirige les paquets IP qui voyagent entre les interfaces réseaux du routeur. Par défaut, OpenBSD ne fera pas de redirection des paquets IP entre les différentes interfaces réseaux. En d’autres mots, les fonctions de routage (appelées aussi fonctions de passerelles) sont désactivées.
Nous pouvons activer la redirection d’IP en utilisant les commandes suivantes :
# sysctl net.inet.ip.forwarding=1
# echo 'net.inet.ip.forwarding=1' >> /etc/sysctl.conf
Maintenant OpenBSD sera capable de rediriger les paquets IPv4 depuis une interface réseau vers une autre. Ou, tel dans notre cas avec les 4 ports, d’un port à l’autre. Regardez la page du manuel si vous avez besoin d’IPv6.
Maintenant nous sommes prêts à paramétrer le service DHCP que nous exécuterons pour nos différents PC et dispositifs attachés aux différents LAN. Avant, assurons-nous de lire et de comprendre les différentes options de la page du manuel dhcp.conf. Prenons aussi le temps de regarder la page de manuel dhcp-options à propos des options que prend en charge dhcpd.
Nous avons une option pour cacher des adresses IP à de PC ou dispositifs spécifiques qui se connectent sur nos différents ports. Cela est nécessaire si nous voulons rediriger le trafic qui vient d’Internet vers quelque chose comme un serveur web. Nous pouvons cacher une adresse IP spécifique vers un PC spécifique via l’adresse MAC de l’interface réseau de la machine concernée.
Dans ce cas, je réserverais toutes les adresses IP dans un ensemble allant de 10 à 254 pour le DHCP, tandis que je laisserais les autres qui restent pour les éventuelles adresses fixes dont je pourrais avoir besoin.
Éditer le fichier /etc/dhcpd.conf
avec votre éditeur de texte favori et
adapter le à vos besoins.
subnet 192.168.1.0 netmask 255.255.255.0 {
option domain-name-servers 192.168.1.1;
option routers 192.168.1.1;
range 192.168.1.10 192.168.1.254;
}
subnet 192.168.2.0 netmask 255.255.255.0 {
option domain-name-servers 192.168.2.1;
option routers 192.168.2.1;
range 192.168.2.10 192.168.2.254;
}
subnet 192.168.3.0 netmask 255.255.255.0 {
option domain-name-servers 192.168.3.1;
option routers 192.168.3.1;
range 192.168.3.10 192.168.3.254;
host web.example.com {
fixed-address 191.168.3.2;
hardware ethernet 61:20:42:39:61:AF;
option host-name "webserver";
}
}
La ligne option domain-name-servers
spécifie le serveur DNS que nous allons
faire fonctionner sur notre routeur.
De plus l’ordinateur qui est notre serveur web sur le LAN publique a une adresse IP fixe et un nom d’hôte fixé.
De même, si vous ne voulez pas segmenter le réseau en différentes parties, mais que vous avez seulement besoin d’un LAN alors vous pouvez juste laisser de côté les autres sous-réseaux pour avoir juste cela :
subnet 192.168.1.0 netmask 255.255.255.0 {
option domain-name-servers 192.168.1.1;
option routers 192.168.1.1;
range 192.168.1.10 192.168.1.254;
}
Ensuite, nous avons simplement besoin de nous assurer d’activer et de démarrer
le service dhcpd
:
# rcctl enable dhcpd
# rcctl start dhcpd
domain-name
dans DHCP afin d’éviter à avoir à écrire le FQDN à chaque fois que vous
en avez besoin.
Ce chapitre vous montrera aussi comment vous pouvez éviter d’avoir à vous
souvenir des adresses IP si votre LAN a de multiples ordinateurs ou
dispositifs connectés.Un pare-feu filtrant examine chaque paquet qui croise le pare-feu et décide quel paquet accepter ou refuser, selon l’examen des champs dans l’IP et les entêtes de protocole du paquet, et selon l’ensemble des règles que vous spécifiez.
Le filtrage de paquets fonctionne par inspection des adresses IP et du port source et de destination contenus dans chaque paquet du protocole TCP/IP (Transmission Control Protocol / Internet Protocol). Les ports TCP/IP sont des numéros assignés à des services spécifiques qui identifie pour quel service chaque paquet est destiné.
Une faiblesse commune des pare-feux simples à filtrage de paquets est que le pare-feu examine chaque paquet de manière isolée sans tenir compte des paquets qui ont déjà traversé le pare-feu et de ceux qui pourraient le suivre. Ils sont appelés pare-feu “sans état”. Exploiter un filtrage de paquets sans état est assez facile. PF d’OpenBSD n’est pas un pare-feu sans états, c’est un pare-feu à états.
Un pare-feu à états garde trace des connexions ouvertes et permet seulement le trafic correspondant à une connexion existante ou ouvre une nouvelle connexion permise. Quand l’état est spécifié par une règle correspondante, le pare-feu génère dynamiquement des règles internes pour que chaque paquet anticipé puisse être échangé durant la session. Il a suffisamment de capacité de correspondance pour déterminer si un paquet est valide pour une session. Tout paquet qui ne correspond pas au modèle de session sera automatiquement rejeté.
Un des avantages du filtrage à états est que c’est très rapide. Il vous permet de vous focaliser sur le fait de bloquer ou laisser passer de nouvelles sessions. Si une nouvelle session est passée, tous les paquets conséquents sont automatiquement alloués et tout paquet imposteur sera automatiquement rejeté. Si une nouvelle session est bloquée, aucun des paquets conséquents n’est autorisé. Le filtrage à états fournit aussi des capacités avancées de correspondance capables de se défendre contre le flood de différentes méthodes d’attaques employées par des attaquants.
La Traduction d’Adresse Réseau (NAT) permet à un réseau privé derrière le pare-feu de partager une adresse IP publique unique. La NAT permet à chaque ordinateur du réseau privé d’avoir un accès à Internet, sans avoir besoin de comptes multiples à Internet, ou de multiples adresses IP publiques. La NAT traduira automatiquement l’adresse IP du réseau privé pour les ordinateurs et dispositifs sur le réseau vers l’unique adresse IP publique lorsque les paquets sortent du pare-feu vers Internet. La NAT assume aussi la traduction inverse pour les paquets de retour. Avec la NAT, vous pouvez rediriger un trafic spécifique, couramment déterminé par un numéro de port ou un ensemble de numéros de port, entrant depuis votre adresse IP publique depuis Internet vers le ou les serveurs spécifiques localisés quelque part dans votre réseau local.
PF - Packet Filter est le système de pare-feu d’OpenBSD pour le filtrage du trafic TCP/IP et faisant de la NAT. PF est aussi capable de normaliser ou conditionner le trafic TCP/IP, aussi bien que gérer le contrôle de la bande passante ou la priorisation de paquets.
PF est activement maintenu et développé par l’entière équipe d’OpenBSD.
Avant que nous commencions, je présume que vous avez lu à la fois et le Guide de l’Utilisateur de PF et la page du manuel pf.conf, spécifiquement la page du manuel qui est très importante. Même si vous ne comprenez pas toutes les différentes options, assurez-vous de lire la documentation ! Lisez la page du manuel pf pour avoir une complète compréhension en profondeur de ce que PF peut faire.
De plus, laissez-moi commencer par vous dire que même si la syntaxe de PF est très lisible, il est très facile de faire des erreurs lors de l’écriture des règles de pare-feu. Même des seniors et des administrateurs systèmes expérimentés font des erreurs lors de l’écriture des règles de pare-feu.
Écrire des règles de pare-feu requiert que vous ayez planifié vos buts avec attention, compris comment implémenter les différentes règles avant d’obtenir le résultat attendu, et en même temps de prendre vos précautions afin de vous éviter de vous tromper et de vous déconnecter accidentellement :) Je pense que nous l’avons tous fait à un moment ou l’autre, que ce soit dans la précipitation, la fatigue ou simplement par erreur. J’ai vécu cela de nombreuses fois.
La partie la plus importante est de ne pas faire de suppositions. Testez toujours vos règles de manière approfondie. Si quelque chose ne fonctionne pas, essayez de supprimer autant de règles que possible pour ne garder que le strict minimum. Puis introduisez une règle à la fois jusqu’à trouver la règle qui pose problème. Enfin, continuez avec le paramétrage étape par étape.
La partie réellement difficile est de se souvenir de comment les paquets arrivent sur une interface, comment ils sont rediriger vers une machine sur une autre interface, et de relier correctement ce “voyage” aux termes pass in, pass out, block in, block out, from et to. Souvent, ces termes ne fonctionnent pas exactement comme nous avons tendance à le penser.
Je tiens à démarrer en clarifiant certains des paramètres communs par défaut et des mots clés dans PF.
Quand nous parlons du traffic pass in ou pass out, une bonne manière de se rappeler ce dont il s’agit est de penser en terme de paquets de données. Nous utilisons pass in pour les paquets de données entrants qui viennent d’ordinateurs vers une interface réseau (les ordinateurs étant rattachés à ce périphérique réseau) et pass out pour les paquets de données venant de l’interface réseau vers les ordinateurs.
Le format est soit que nous filtrons les paquets de données sur la destination :
from source IP to destination IP [on] port
Soit que nous filtrons les paquets de données sur la source :
from source IP [on] port to destination
Veuillez noter que la partie [on]
n’est pas une partie de la syntaxe.
quick
pass
, block
ou match
avec
le critère quick
, le paquet est passé sans inspection des règles de
filtrage conséquentes.
La règle avec le critère quick
devient la dernière règle correspondante.keep state
keep state
pour des
règles spécifiques pass
ou block
.
La première fois où un paquet correspond à une règle pass
ou block
,
un état d’entrée est créé par défaut.
Seulement si aucune règle ne correspond au paquet, l’action par défaut
est de passer le paquet sans créer d’état.on
interface/any
on any
correspondra à toute interface existante, exceptée
celles de bouclage loopback.inet
/inet6
inet
et inet6
signifie que cette règle s’applique
seulement aux paquets entrants, ou passant au-travers ce domaine
particulier de routage, soit IPv4, soit IPv6.
Vous pouvez appliquer des règles pour des domaines particuliers de routage
sans spécifier l’interface réseau. Dans de ce cas, la règle correspondra
à tout trafic de toute nature sur toutes les interfaces réseaux. En
spécifiant inet
, vous adressez explicitement le trafic IPv4 seulement.proto
in
et out
in
et out
s’applique aux paquets entrants
et sortants au-travers du port Ethernet physique auquel est attaché
le câble Ethernet. Si rien n’est spécifié, la règle correspondra
aux paquets dans les deux directions.
in
et out
ne sont jamais utilisé pour gérer le trafic venant
d’ une interface réseau vers une autre, ce qui est fait par la NAT, en
utilisant les options nat-to
et rdr-to
. in
et out
gèrent
seulement le trafic entrant et sortant du port Ethernet physique
d’une même carte.from
et to
from
et to
s’appliquent seulement aux paquets avec
une adresse et des ports source et destination spécifiés.
Des deux, du nom d’hôte ou de l’adresse IP, ou du port, voire les
spécifications OS sont optionnels.
Quand nous avons affaire avec un routeur ayant de multiples interfaces
réseaux, il est facile de penser cela :
Je veux passer les paquets entrants depuis l’interface externe
(l’interface réseau attachée à Internet) puis qu’ils aillent sur la
première interface LAN et de là vers un PC spécifique sur le LAN
signifiant que nous suivront le “chemin des données” dans notre esprit,
et alors nous écrivons quelque chose comme cela :
pass in on $ext_if from $ext_if to $dmz port 80
.
Mais cela ne fait pas apparaître “par magie” le trafic HTTP sur le port 80
au PC ayant l’adresse IP spécifique sur le LAN. Il nous faudrait aussi une
règle pass out
spécifique et déterminer exactement sur quelle machine
nous voulons que les données arrivent.
À moins que vous n’ayez affaire à une exigence très spécifique, vous
n’aurez jamais besoin d’une telle règle dans votre jeu de règles !
Les fonctionnalités uRPF (Unicast Reverse Path Forwardint)
de PF protégeront votre réseau interne aussi bien avec un paramétrage
de base de NAT, avec l’option nat-to
et une redirection avec l’option
rdr-to
, PF gérera les paquets venant de l’intérieur vers l’extérieur
et vice-versa.
Le paramètre all
est équivalent à l’écriture from any to any
.
Sans une direction explicitement déclarée, la règle par défaut est
from any to any
. Cette règle : pass in on $p_lan proto udp to port dns
se traduit par : pass in on em3 inet proto udp from any to any port = 53
.
Il n’est pas non plus nécessaire d’utiliser to any port dns
, la
partie any
étant celle par défaut. Vous avez cependant besoin de
to port dns
.nat-to
et rdr-to
nat-to
spécifie que les adresses IP ont été changées car
le paquet traverse l’interface donnée.
Cette technique permet à une ou plusieurs adresses IP sur l’hôte traduisant
(le routeur OpenBSD) de prendre en charge le trafic réseau pour un ensemble
plus grand de machines sur le réseau interne, tel qu’un LAN.
L’option nat-to
est habituellement appliqué à la sortie, signifiant
redirigé depuis le réseau interne vers Internet.
nat-to
vers une adresse IP locale n’est pas pris en charge.
L’option rdr-to
est appliquée généralement à l’entrée, signifiant
redirigé depuis Internet vers le réseau interne.Liste d’éléments et d’ensemble d’adresses et de ports
port { 53 853 }
ou port { 53, 853 }
.
Un ensemble d’adresses est spécifié en utilisant l’opérateur -
.
e.g. 192.168.1.2 - 192.168.1.10
signifie toutes les adresses IP
de 192.168.1.2 à 192.168.1.10, incluant les deux.
Un ensemble de ports a de multiples paramètres ; regardez la page du
manuel pf.conf et cherchez le texte
“Ports and ranges of ports are specified using these operators”.block
et pass
, la dernière règle correspondante décide
de quelle action prise.
Si aucune règle ne correspond au paquet, l’action par défaut est de laisser
passer le paquet sans créer d’état.
Pour match
, les règles sont évaluées chaque fois qu’elles correspondent.Si vous décidez d’utiliser des noms d’hôtes et/ou des noms de domaines dans votre paramétrage de PF, vous avez besoin de savoir que la résolution de tout nom de domaine ou d’hôte est faite au moment du chargement du jeu de règles. Cela signifie que quand l’adresse IP d’un hôte ou d’un nom de domaine change, le jeu de règles doit être rechargé pour que le changement soit pris en compte par le noyau. Il n’est pas possible qu’à chaque fois qu’une règle s’applique, pour un nom d’hôte ou de domaine listé, que PF fasse une nouvelle requête DNS pour ce nom d’hôte ou de domaine particulier. La requête DNS s’effectue seulement lors du chargement du jeu de règles.
Cela signifie aussi que vous devez vous assurer que le serveur DNS que vous utiliser soit actif et fonctionnel avant que PF ne démarre, autrement PF échouera à charger le jeu de règles car il ne peut résoudre le nom d' hôte ou de domaine.
Sur OpenBSD, PF démarre avant Unbound ou tout autre service DNS installé, ce qui est la bonne manière de faire d’un point de vue de la sécurité.
Je vous conseille d’éviter l’utilisation de noms d’hôtes ou de noms de domaines lorsque vous utilisez les règles PF et de privilégier les adresses IP, si possible. Il est possible d’utiliser les noms d’hôtes et noms de domaines, mais l’adressage d’IP directement est de loin le plus facile et le plus sûr.
C’est une bonne idée de tester votre jeu de règles sur une machine de test. Il y a presque toujours plus d’une manière de faire pour arriver au même résultat. Selon mon humble avis, la meilleure manière est celle qui vous permet d’être le plus clair (i.e. facile à comprendre).
Essayez de trouver comment vous pouvez faire en sorte que vos règles soient
aussi claires et simples que possible, en utilisant les valeurs par
défaut, quand c’est possible.
N’ayez pas peur de spécifier des critères qui rendent les règles plus
claires à comprendre, quand bien même ils sont identiques aux valeurs par
défaut.
Une valeur par défaut peut être any to any
, et vous pouvez laisser cela
de côté, mais il serait plus facile de comprendre une règle particulière
quand il est écrit any to any
textuellement dans le fichier de configuration.
Vous pouvez toujours analyser le jeu de règles et vérifier les erreurs
sans qu’il soit déployé avec la commande pfctl -nf /etc/pf.conf
.
Une fois que vous avez chargé le jeu de règles avec la commande pfctl -f /etc/pf.conf
,
vous pouvez voir comment le jeu de règles a été traduit par PF avec la
commande pfctl -s rules
, que je vous conseille d’utiliser régulièrement.
Je préfère organiser mon jeu de règles par section et commentaires, je ferais ainsi dans cet exemple.
Utilisez votre éditeur de texte favori et ouvrez le fichier /etc/pf.conf
.
En premier, nous paramétrons quelques macros pour mieux se souvenir quelles interfaces réseaux nous utilisons. Utiliser des macros pour les interfaces réseaux rend aussi plus facile le changement du nom du pilote de la carte si vous achetez une nouvelle carte, ou de multiples nouvelles cartes.
#---------------------------------#
# Macros
#---------------------------------#
ext_if="em0" # Interface externe connectée au modem du FAI (Internet).
g_lan="em1" # LAN PC Adultes
c_lan="em2" # LAN PC Enfants
p_lan="em3" # LAN Publique.
Ensuite, nous paramétrons une table pour les adresses IP non routable. Nous faisons cela, car une mauvaise configuration réseau courante est celle qui permet du trafic avec des adresses non routable vers Internet. Nous utiliserons la table dans notre jeu de règles afin de bloquer tout essai d’initier un contact avec les adresses non routable au-travers de l’interface externe du routeur.
#---------------------------------#
# Tables
#---------------------------------#
# Ceci est une table d'adresses IP privées non routables.
table <martians> { 0.0.0.0/8 10.0.0.0/8 127.0.0.0/8 169.254.0.0/16 \
172.16.0.0/12 192.0.0.0/24 192.0.2.0/24 224.0.0.0/3 \
192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 \
203.0.113.0/24 }
/etc/pf.conf
.Alors, commençons avec une politique de blocage par défaut et activons une série de fonctionnalités de protection.
#---------------------------------#
# Protect and block by default
#---------------------------------#
set skip on lo0
# Protection vs l'usurpation d'adresses sur toutes les interfaces réseaux.
block in from no-route
block in quick from urpf-failed
# Bloquage des adresses privées non routable.
# Utilisation du paramétre "quick" pour que cette règle soit la dernière traversée.
block in quick on $ext_if from <martians> to any
block return out quick on $ext_if from any to <martians>
# Bloquage par défaut de tout trafic sur toutes les interfaces réseaux.
block return in on { $g_lan $c_lan $dmz }
# Bloquage par défaut de tout trafic sur l'interface reliée à Internet
# avec journalisation
block drop in log on $ext_if
# Autoriser ICMP.
match in on $ext_if inet proto icmp icmp-type {echoreq } tag ICMP_IN
block drop in on $ext_if proto icmp
pass in proto icmp tagged ICMP_IN max-pkt-rate 100/10
# Autoriser le routeur à accéder à Internet, au-travers de son interface réseau dédiée
pass out inet from $ext_if
Les adresses IP contenues dans la macro martians
constituent les adresses
référencées dans la RFC1918 qui ne
doivent pas être utilisées sur Internet.
Le trafic venant ou allant vers de telles adresses doit être abandonné
sur l’interface externe du routeur.
Dans les précédentes versions de ce guide (avant la version 1.5.0), j’avais
l’habitude d’utiliser l’instruction scrub
dans le paramétrage ci-dessus, toutefois après avoir consulté l’équipe
OpenBSD avec Henning Brauer (Merci à Henning !)
et fais de plus amples recherches, j’ai décidé de la supprimer car elle
ne traite que des cas très spécifiques (veuillez lire la documentation).
Vous aurez besoin de la règle scrub
seulement si un hôte sur votre réseau
génére des paquets fragmentés avec le drapeau “dont-fragment”.
Le comportement par défaut de PF sans la règle scrub
est mieux adapté
à un usage général.
La FAQ d’OpenBSD contient
un exemple de paramétrage pour un routeur très basique, avec certaines
valeurs spécifiques pour scrub
, mais ma recommandation est d’utiliser
seulement scrub
là où vous savez en avoir besoin.
Si vous n’en avez pas besoin, insérez-la dans la configuration après la
règle set skip
pour l’interface de bouclage locale, tel que :
set skip on lo0
match in all scrub
Et ensuite ajoutez les paramètres à la règle scrub
dont vous avez besoin.
J’utilisais aussi la règle antispoof suivante dans la section de protection contre l’usurpation :
antispoof quick for { $g_lan $c_lan $dmz }
J’ai depuis supprimé la règle antispoof
puisque la fonctionnalité
uRPF (Unicast Reverse Path Forwarding)
que PF fournit a la même fonctionnalité, et en tant que tel nous n’en avons
plus besoin, à la place nous utilisons juste la règle block in quick from urpf-failed
.
L’information suivante à-propos du critère antispoof
est gardée à des
fins d’éducation.
L’usurpation est lorsque quelqu’un fabrique une adresse IP. Le critère
antispoof
s’étend à un ensemble de règles de filtrage qui empêcheront
tout trafic avec une adresse IP source du réseau (directement connecté
à l’interface spécifiée) entrant sur le système par une autre interface.
Cela est parfois appelé “bleeding over” ou “bleeding through”.
La directive antispoof
est traduite par PF par ce qui suit :
block drop in quick on ! em1 inet from 192.168.1.0/24 to any
block drop in quick inet from 192.168.1.1 to any
block drop in quick on ! em2 inet from 192.168.2.0/24 to any
block drop in quick inet from 192.168.2.1 to any
block drop in quick on ! em3 inet from 192.168.3.0/24 to any
block drop in quick inet from 192.168.3.1 to any
Si nous prenons, e.g., la règle block drop in quick on ! em1 inet from 192.168.1.0/24 to any
de l’interface réseau em1
qui signifie alors : bloque tout trafic venant
du réseau ayant une adresse IP comprise entre 192.168.1.1 et 192.168.1.255,
qui n’est pas originaire depuis l’interface em1 elle-même, et qui va ailleurs.
Puisque l’interface em1
est l’interface réseau en charge de toutes les
adresses IP dans cet ensemble spécifique, alors aucun trafic avec de telles
adresses IP ne pourra être originaire de toute autre interface réseau.
antispoof
doit être restreinte aux interfaces qui
ont une adresse IP assignée, ce qui signifie que si vous avez des interfaces
réseaux inutilisées, ou des ports d’une interface réseau, assurez-vous
d’assigner une adresse IP à chacune ou de ne pas les inclure dans l’option
antispoof
.Ainsi que je l’ai mentionnée, j’ai supprimé la règle antispoof
et nous
utiliserons à la place la vérification stricte d’uRPF.
Lorsqu’un paquet passe dans la vérification d’uRPF, l’adresse IP source
du paquet est recherchée dans la table de routage.
Si l’interface de sortie est trouvée dans la table de routage et que l’entrée
est la même que l’interface du paquet qui vient juste d’entrer, alors la
vérification d’uRPF autorise.
Autrement, il est possible que le paquet ait son adresse IP source usurpée
ainsi il sera bloqué.
Nous allons permettre ICMP dans notre paramétrage, quand bien même des administrateurs réseaux bloquent complètement ICMP. La plupart des personnes bloquent complètement ICMP à cause d’actions injustifiées telles que les attaques par découverte de réseaux, les canaux de communication, le ping sweep, le ping flood, le tunnel d’ICMP, et la redirection d’ICMP. Toutefois, ICMP est bien plus que répondre à des ping. Si nous bloquons complètement ICMP, les diagnostics, la fiabilité, et la performance réseau peuvent être défectueuses puisque des mécanismes importants sont désactivés lorsque le protocole ICMP est restreint.
Voici certaines raisons pour lesquelles ICMP ne devrait pas être bloqué :
Dans le paramétrage ci-dessus, nous permettons ICMP, mais nous mettons une
“limite de taux” du nombre de requêtes ping auxquelles le routeur répondra.
Avec le critère max-pkt-rate 100/10
, le routeur arrêtera de répondre aux
ping si nous en avons plus de 100 en 10 secondes.
Maintenant paramétrons le segment LAN pour les adultes de la maison.
#---------------------------------#
# Paramétrage du réseau LAN adulte
#---------------------------------#
# Autoriser tout ordinateur ou dispositif sur le LAN adulte à envoyer des
# paquets de données entrants dans l'interface réseau. Cela signifie que
# tout ordinateur attaché à cette interface réseau peut envoyer des données
# partout, i.e. sur Internet ou tout ordinateur attaché au routeur.
pass in on $g_lan
# Toujours bloquer les requêtes DNS non adressées à notre serveur DNS.
block return in quick on $g_lan proto { udp tcp } to ! $g_lan port { 53 853 }
# J'ai une imprimante réseau et je ne veux pas qu'elle "téléphone maison".
# L'imprimange réseau à l'adresse IP 192.168.1.8.
block in quick on $g_lan from 192.168.1.8
# Autoriser les paquets de données venant du routeur à sortir par l'interface
# réseau vers les ordinateurs et dispositifs attachés à l'interface du
# réseau Adultes.
# Sans cela nous ne pouvons même pas pingués les ordinateurs attachés à
# l'interface du réseau Adultes depuis le routeur lui-même.
pass out on $g_lan inet keep state
Dans cet exemple, j’ai une imprimante réseau attachée au réseau des adultes et je ne veux pas qu’elle accéde à Internet ou ailleurs (juste en cas où il y aurait une sorte de micrologiciel espion). Nous le faisons en disant : bloque toutes les données entrantes sur em1 venant de l’adresse IP 192.168.1.8 allant vers toute adresse IP.
De plus, nous nous assurons que toutes les requêtes DNS sur les ports 53 (DNS régulier) et 853 (DNS sur TLS) soient toujours bloquées si elles ne viennent pas de notre serveur DNS.
return
ou drop
, la requête prenant un délai sur le client,
ce qui avait pour conséquence que beaucoup de clients obtenaient un délai
sur la réponse.
Depuis j’ai changé cela en block parce que je crois que c’est une meilleure
approche.
Tous les clients DNS ont besoin de réaliser que la communication sur le
port 53 est bloqué, à moins qu’elle ne soit adressée à notre serveur DNS.
C’est aussi important quand nous avons des problèmes sur notre réseau.
Si nous avons une réponse redirigée vers notre serveur DNS, nous pourrions
ne pas être averti que nous avons été redirigé.Le réseau LAN pour les enfants est très similaire.
#---------------------------------#
# Paramétrage LAN enfants
#---------------------------------#
# Autoriser tout PC du LAN Enfant à envoyer des données au-travers du port
# de l'interface réseau
pass in on $c_lan
# Toujours bloquer les requêtes DNS qui ne sont pas adressées à notre
# serveur DNS.
block return in quick on $c_lan proto { udp tcp} to ! $c_lan port { 53 853 }
# Autorise les paquets de données à passer venant du routeur au-travers
# l'interface réseau vers les ordinateurs ou dispositifs attachés au
# LAN Enfants.
# Sans cela, nous ne pourrions même pas pingués les ordinateurs depuis
# le routeur lui-même
pass out on $c_lan inet keep state
Actuellement les deux réseaux Adultes et Enfants ont le même accès à Internet. Un paramétrage plus restrictif est mentionné dans le chapitre “Liste Blanche pour enfants ”.
Occupons nous alors de la DMZ, i.e. de l’interface réseau qui répond publiquement au serveur web. Puisque nous avons un serveur web publique, nous allons définir un certain nombre de restrictions. Si le serveur web est compromis, l’intrus aura du mal à trouver ce qui est localisé dans notre réseau interne.
Nous bloquons tous les accès excepté le DHCP, afin que le serveur web ait une adresse IP depuis notre routeur, et alors d’ouvrir seulement manuellement certaines choses pour quand nous avons besoin de mettre à jour la machine ou quoi que ce soit d’autres. J’ai commenté les options dont nous avons besoins, quand nous avons besoin de telles choses, laissant les parties restreintes actives. Quand vous aurez besoin de mettre à jour le serveur, ouvrez l’accès DNS et l’accès général à Internet.
#---------------------------------#
# Paramétrage DMZ
#---------------------------------#
# Autorise tout ordinateur ou dispositif attaché à l'interface réseau DMZ
# à obtenir une adresse IP venant du DHCP depuis le routeur
pass in on $dmz inet proto udp from any port 67
# Autorise tout ordinateur ou dispositif attaché à l'interface réseau DMZ
# à faire des requêtes DNS. (décommentez si besoin)
#pass in on $dmz inet proto udp from any port 53
# Toujours bloquer les requêtes DNS non adressées à notre serveur DNS.
block return in quick on $dmz proto { udp tcp} to ! $dmz port { 53 853 }
# Pour autoriser tout ordinateur attaché à l'interface réseau DMZ à accéder
# à Internet, décommentez la ligne ci-dessous.
# (Cela est pertinent pour les màj)
#pass in on $dmz inet
# No matter what, we do not want the DMZ segment to reach any of the other
# network segments so we explicitly use a block last.
#
# We have several options. If we use this:
#
# block drop in on $dmz to 192.168/16
#
# Then we block for all subnets, but this also means that the computers
# attached to the DMZ NIC cannot do DNS queries when they need to be upgraded.
#
# In my opinion it is much better to be explicit and block the specific
# segments we want blocked.
#
# Bloque les ordinateurs depuis l'interface réseau DMZ essayant d'atteindre
# les autres sur les deux autres segments réseaux
block drop in on $dmz to { $g_lan:network $c_lan:network }
# En dernier, autorisons les paquets à sortir s'ils viennent de l'interface
# réseau DMZ vers les ordinateurs attachés, autrement pas de "discussion".
# Sans cela nous ne pouvons même pas pinguer les ordinateurs attachés à
# l'interface réseau DMZ depuis le routeur lui-même
pass out on $dmz inet keep state
Maintenant, occupons nous de la NAT.
C’est là où le routeur route les paquets venant d’un segment du réseau
vers un autre, dans le cas spécifique venant de notre réseau interne vers
Internet, et alors toute réponse venant d’Internet, à destination de
l’initiateur de la transmission.
Je préfère le paramètre :network
qui traduit le(s) réseau(x)
attaché(s) à l’interface, et je préfère être spécifique avec une règle
pour chaque segment concerné.
#---------------------------------#
# NAT
#---------------------------------#
pass out on $ext_if inet from $g_lan:network to any nat-to ($ext_if)
pass out on $ext_if inet from $c_lan:network to any nat-to ($ext_if)
pass out on $ext_if inet from $dmz:network to any nat-to ($ext_if)
PF gardera une trace de tout le trafic, et quand, e.g. un navigateur web sur le LAN Adultes demandera une page web de certains sites sur Internet, la réponse venant du serveur web depuis Internet sera routé au-travers de l’interface externe vers l’interface interne du LAN Adultes, et alors directement vers le PC qui a initié la requête.
Enfin, occupons-nous de la partie relative à la redirection dans notre jeu de règles. C’est là où nous permettons le trafic venant d’Internet vers notre serveur web publique sur l’interface réseau DMZ. Vous devriez, bien sûr, laisser cette partie si vous n’avez pas de serveurs publiques qui nécessitent de redirection. Dans cet exemple, j’ai seulement permis le trafic IPv4.
#---------------------------------#
# Redirects
#---------------------------------#
# Our web server - let the Internet access it.
pass in on $ext_if inet proto tcp to $ext_if port { 80 443 } rdr-to 192.168.3.2
C’est tout concernant le paramétrage basique de nos règles filtrantes.
Si vous voulez bloquer tout Internet pour les enfants, exceptés peut être quelques sites web ou certains serveurs de jeux, vous avez besoin de connaître quelles adresses IP ces services ont et de créer une liste blanche utilisant ces adresses IP.
Si c’est un simple site web avec une adresse IP unique, c’est très facile et vous pouvez le faire avec cette règle placée en dernier dans le bloc pour enfants (vous devez remplacer la partie x.x.x.x avec l’adresse IP pertinente) :
#---------------------------------#
# Childrens LAN Setup
#---------------------------------#
# Allow any computer or device attached to the childrens NIC to get an IP
# address from DHCP on the router.
pass in on $c_lan inet proto udp from any port 67
# Allow any computer or device attached to the childrens NIC to make DNS
# queries.
pass in on $c_lan inet proto udp from any port 53
# Always block DNS queries not addressed to our DNS server.
block return in quick on $c_lan proto { udp tcp} to ! $c_lan port { 53 853 }
# Then allow any computer or device attached on the childrens LAN to reach
# the IP address x.x.x.x only.
pass in on $c_lan to x.x.x.x
Si le site web a de multiples adresses IP, nous devons comprendre lesquelles. Parfois une requête de nom de domaine peut révéler toutes les adresses IP concernées en une fois. D’autres fois, nous avons besoin de répéter de multiples fois les requêtes à différentes intervalles de la journée avant d’obtenir l’ensemble complet des adresses IP. Vous pouvez faire cela en mettant en place un script automatisé.
Parfois, nous aurons besoin de contacter l’entreprise en question et de
demander si nous pouvons avec l’ensemble des adresses IP pour notre liste
blanche (certaines compagnies publient publiquement l’information, d’autres
refusent de livrer l’information par peur d’un usage malicieux).
Une fois que vous avez déterminé quel est l’ensemble d’adresses IP, vous
pouvez faire une table
PF pour l’utiliser.
Dans cet exemple, nous ajoutons une nouvelle table dans la section table des règles et nous changeons les paramètres des règles pour enfants.
#---------------------------------#
# Tables
#---------------------------------#
…
# Whitelist for the children.
table <whitelist> { x.x.x.x y.y.y.y z.z.z.z }
Et ensuite dans la section pour enfants, changez :
pass in on $c_lan to x.x.x.x
en :
pass in on $c_lan to <whitelist>
Il n’est pas toujours possible d’avoir toutes les adresses IP dans une liste blanche en une fois, mais en surveillant le réseau, en utilisant e.g. tcpdump, quand le jeu essaye d’accéder au serveur, vous pouvez établir une liste, bit après bit. J’ai fait cela avec les serveurs de connexion Mojan et Minecraft et de multiples autres serveurs de jeux.
Une autre approche pour collecter les IP est d’utiliser une table persistante
en combinaison avec /etc/rc.local
et les requêtes de noms de domaine.
/etc/rc.local
est seulement exécuté après que PF soit démarré ainsi
les problèmes de résolution de DNS n’entraîneront pas des problèmes pour
PF.
Si vous souhaitez utiliser la solution des tables persistantes, vous pouvez
le faire en ajoutant une table persistante dans la section des tables
dans /etc/pf.conf
:
table <whitelist> persist
Dans la section pour enfants, nous avons besoin de passer les données qui viennent de la liste blanche ci-dessus :
pass in on $c_lan to <whitelist>
Alors, dans /etc/rc.local
, nous pouvons ajouter la commande suivante :
pfctl -t whitelist -T add example.com
Où example.com
est le domaine que PF doit chercher.
Quand vos enfants ne peuvent pas avoir accès parce que l’adresse IP valide pourrait avoir changé, vous pouvez vous connecter au pare-feu et alors mettre à jour manuellement la table avec plus d’adresses IP en exécutant la commande :
pfctl -t whitelist -T add examples.com
Si vous voulez voir ce qui a été ajouté à cette liste, vous pouvez faire ceci :
# pfctl -t whitelist -T show
74.6.143.25
74.6.143.26
74.6.231.20
74.6.231.21
98.137.11.163
98.137.11.164
216.58.208.110
2001:4998:24:120d::1:0
2001:4998:24:120d::1:1
2001:4998:44:3507::8000
2001:4998:44:3507::8001
2001:4998:124:1507::f000
2001:4998:124:1507::f001
2a00:1450:400e:80e::200e
Éventuellement, vous pouvez ajouter toutes les adresses IP que vous collectez
(avant qu’elles ne soient purgées) dans un fichier physique afin que l’option
persist
prenne en entrée ce fichier, tel que :
table <whitelist> persist file "/etc/pf-whitelist.txt"
add
à pfctl
.
Une table persistante réside soit en mémoire, soit dans un fichier, mais
l’option add
ne peut écrire sur le disque, seulement dans la mémoire.
Une table persistante depuis un fichier est ce dont vous avez besoin afin
de l’éditer manuellement depuis un éditeur de texte.Une fois que vous avez fini de paramétrer votre jeu de règles, vous pouvez le tester avec :
# pfctl -nf /etc/pf.conf
Si tout est bon, chargez votre jeu de règles en supprimant l’option -n
:
# pfctl -f /etc/pf.conf
Regardez le résultat traduit avec :
# pfctl -s rules
Ceci est un exemple de sortie venant du journal de PF des essais bloqués accédant à l’interface externe, selon mon paramétrage. J’ai nettoyé la sortie et supprimé quelques données spécifiques, et bien sûr 0.0.0.0 n’est pas mon adresse IP publique, mais vous savez déjà cela ;)
# tcpdump -n -e -ttt -r /var/log/pflog
23:11:12 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3422: S 1501043655:1501043655(0) win 1024
23:11:12 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3481: S 311078394:311078394(0) win 1024
23:11:31 rule 14/(match) block in on em0: 176.214.44.229.25197 > 0.0.0.0.23: S 2084440900:2084440900(0) win 33620
23:11:33 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3431: S 2774981044:2774981044(0) win 1024
23:11:43 rule 14/(match) block in on em0: 81.68.114.52.17191 > 0.0.0.0.23: S 1346864438:1346864438(0) win 26375
23:12:08 rule 14/(match) block in on em0: 193.27.229.26.53865 > 0.0.0.0.443: S 1057596009:1057596009(0) win 1024
23:12:31 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.4186: S 1233742605:1233742605(0) win 1024
23:12:44 rule 14/(match) block in on em0: 74.120.14.70.65509 > 0.0.0.0.9125: S 1836577847:1836577847(0) win 1024 <mss 1460> [tos 0x20]
23:12:44 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.4128: S 2112968453:2112968453(0) win 1024
23:13:15 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3669: S 3627248539:3627248539(0) win 1024
23:13:19 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3654: S 3889665614:3889665614(0) win 1024
23:13:29 rule 14/(match) block in on em0: 45.129.33.129.42239 > 0.0.0.0.4997: S 2249816896:2249816896(0) win 1024
23:13:37 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3612: S 3797528151:3797528151(0) win 1024
23:14:03 rule 14/(match) block in on em0: 190.207.89.17.64372 > 0.0.0.0.445: S 1097568353:1097568353(0) win 8192 <mss 1460,nop,wscale 2,nop,nop,sackOK> (DF)
23:14:15 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.4219: S 2834775769:2834775769(0) win 1024
23:14:39 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.3702: S 1855726637:1855726637(0) win 1024
23:14:39 rule 14/(match) block in on em0: 45.129.33.4.45980 > 0.0.0.0.4210: S 3052103070:3052103070(0) win 1024
Comme vous pouvez le voir, il est un peu occupé, d’autant que je n’ai rien en cours d’exécution qui soit publiquement sur Internet dans ce paramétrage.
Vous pouvez aussi monitorer PF en temps réel avec :
# tcpdump -n -e -ttt -i pflog0
DNS (Domain Name Service) est utilisé pour traduire un nom de domaine dans une adresse IP ou vice-versa. Par exemple, quand vous écrivez wikipedia.org dans la barre d’adresse de votre navigateur web, un serveur DNS faisant autorité traduit le nom de domaine “wikipedia.org” en une adresse IPv4, telle que 91.198.174.192, et/ou une adresse IPv6, telle que 2620:0:862:ed1a::1.
DNS est aussi utilisé, en plus d’autres choses, pour stocker des informations sur les serveurs de messagerie appartenant à un nom de domaine particulier, le cas échéant.
Si vous utilisez un système d’exploitation de type UNIX, vous pouvez
démarrer un terminal et essayer de faire une recherche manuelle de nom
de domaine avec host
:
$ host wikipedia.org
wikipedia.org has address 91.198.174.192
wikipedia.org has IPv6 address 2620:0:862:ed1a::1
wikipedia.org mail is handled by 10 mx1001.wikimedia.org.
wikipedia.org mail is handled by 50 mx2001.wikimedia.org.
host
n’est pas installé, ce qui dépend de votre plateforme, vous aurez
besoin d’installer bind ou dnsutils
.
Vous pouvez aussi utiliser quelque chose comme dig,
qui vient de bind, ou drill
venant de ldns.La liste qui suit décrit certains des termes associés à DNS :
Forward DNS
Reverse DNS
Resolver
Root zone
Ceci est un exemple de zone :
.
(un point) est la manière dont la zone racine est habituellement
référée dans la documentation.org.
est le TLD (Top-Level Domain)
sous la zone root.wikipedia.org.
est la zone sous le TLD org.
.1.168.192.in-addr.arpa
est la zone référençant toutes les adresses IP
qui sont dans l’espace d’adresse IP 192.168.1.*
.Quand un ordinateur sur Internet a besoin de résoudre un nom de domaine, le résolveur découpe le nom dans ses labels de la droite vers la gauche. Le premier composant, le TLD, est demandé en utilisant un serveur racine pour obtenir le serveur faisant autorité responsable. Les requêtes pour chaque label retournent des serveurs de noms plus spécifiques jusqu’à ce qu’un serveur de noms renvoie la réponse à la requête originale.
Même si un serveur DNS local peut implémenter ses propres serveurs de noms
racines privés, le terme “serveur racine de noms” est utilisé pour décrire
les 13 serveur racines de noms bien connus
qui mettent en œuvre le domaine de l’espace racine des noms pour la mise
en œuvre mondiale officielle du système de noms de domaine d’Internet.
Les résolveurs utilisent un petit fichier nommé root.hints
de 3 Ko,
publié par Internic pour amorcer
cette liste initiale d’adresses des serveurs racines.
Pour beaucoup de logiciels, incluant Unbound, cette liste est intégrée à
l’intérieur du logiciel.
Sur la base de données de la zone racine, vous pouvez chercher les détails de délégation des domaines TLD, incluant des TLD tels que .com, .org, et des TLD ayant des codes de pays, tels que .uk, .de.
Il y a deux types de configuration de serveur DNS :
Autorité
Récursif
Un serveur de noms peut être à la fois faisant autorité et récursif, mais il n’est pas recommandé de combiner la configuration des deux types. Pour être en mesure d’effectuer leur travail, les serveurs faisant autorité doivent être disponibles à tous les clients, tout le temps. D’un autre côté, étant donné que la requête récursive prend plus de temps qu’une réponse faisant autorité, les serveurs récursifs devraient être restreints à un nombre de clients seulement, car ils sont enclins à des attaques par déni de service distribué (DDoS).
Unbound est un résolveur DNS Open Source récursif, cache et validant avec les fonctionnalités suivantes :
Unbound est conçu pour être rapide et sécurisé et incorpore des fonctionnalités modernes basées sur des normes ouvertes. Fin 2019, Unbound a été rigoureusement audité.
Dans notre paramétrage avec Unbound, une requête pour un domaine tel que “wikipedia.org” ressemblera à ceci :
Vous pouvez essayer de faire une trace
DNS par vous-mêmes pour voir le
propos ci-dessus. J’utilise drill
dans cet exemple avec l’option trace
activée.
# drill -T wikipedia.org
. 518400 IN NS l.root-servers.net.
. 518400 IN NS k.root-servers.net.
. 518400 IN NS e.root-servers.net.
. 518400 IN NS a.root-servers.net.
. 518400 IN NS m.root-servers.net.
. 518400 IN NS h.root-servers.net.
. 518400 IN NS i.root-servers.net.
. 518400 IN NS f.root-servers.net.
. 518400 IN NS c.root-servers.net.
. 518400 IN NS b.root-servers.net.
. 518400 IN NS g.root-servers.net.
. 518400 IN NS d.root-servers.net.
. 518400 IN NS j.root-servers.net.
org. 172800 IN NS a0.org.afilias-nst.info.
org. 172800 IN NS a2.org.afilias-nst.info.
org. 172800 IN NS b0.org.afilias-nst.org.
org. 172800 IN NS b2.org.afilias-nst.org.
org. 172800 IN NS c0.org.afilias-nst.info.
org. 172800 IN NS d0.org.afilias-nst.org.
wikipedia.org. 86400 IN NS ns0.wikimedia.org.
wikipedia.org. 86400 IN NS ns1.wikimedia.org.
wikipedia.org. 86400 IN NS ns2.wikimedia.org.
wikipedia.org. 600 IN A 91.198.174.192
Le blocage par DNS, appelé aussi filtrage ou usurpation DNS, est le processus qui vous permet de fournir une “fausse” réponse au client qui effectue la requête. Nous bloquons une requête pour une adresse IP valide soit en répondant avec un NXDOMAIN, signifiant nom de domaine inexistant, ou soit en redirigeant vers une autre adresse IP que celle prévue par le propriétaire du domaine.
Cela nous oblige à créer une liste, ou des listes multiples, de domaines que nous voulons bloquer et plutôt que de fournir à l’utilisateur l’adresse IP correcte pour un certain domaine, nous renvoyons le message que le domaine est “inexistant”, ce qui bloquera toute communication vers la destination prévue pour l’application.
Normalement, toutes les requêtes DNS sont envoyés vers le port 53 soit sur le protocole UDP, soit TCP, lors de la mise en place du serveur DNS, ce que nous faisons avec Unbound, et en s’assurant que tout le trafic du port 53 atteigne notre serveur DNS ou autrement soit bloqué ; nous pouvons nous assurer que toutes les réponses DNS viennent de notre serveur Unbound interne à notre routeur OpenBSD.
Quand nous voulons bloquer un domaine en utilisant DNS, nous pouvons choisir entre différentes méthodes, mais les deux plus populaires sont soit de rediriger la requête DNS vers une adresse IP locale, tel que 127.0.0.1 ou 0.0.0.0, ou de répondre par une définition NXDOMAIN. NXDOMAIN est une norme de réponse pour un “nom de domaine Intranet ou Internet non existant”. Si le nom de domaine est incapable d’être résolu en utilisant DNS, une condition appellée NXDOMAIN est obtenue.
Nous pouvons essayer de résoudre un domaine non existant avec la commande
host
:
$ host a1b7c3n9m3b0.com
Host a1b7c3n9m3b0.com not found: 3(NXDOMAIN)
Puisque le nom de domaine “a1b7c3n9m3b0.com” n’est enregistré par personne (au moins pas durant le temps où j’écris cela), nous obtenons une réponse “NXDOMAIN”.
Nous pouvons aussi utiliser drill
. L’information pertinente depuis la
sortie de drill
est le champ rcode
dans la section “HEADER” :
$ drill a1b7c3n9m3b0.com
;; ->>HEADER<<- opcode: QUERY, rcode: NXDOMAIN, id: 39710
…
Ou si vous préférez dig
, alors l’information pertinente est localisée
dans le champ status
dans la section “HEADER” :
$ dig a1b7c3n9m3b0.com
; <<>> DiG 9.16.8 <<>> +search a1b7c3n9m3b0.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 48858
…
Utiliser une réponse NXDOMAIN n’est pas seulement la manière correcte de bloquer un domaine, en accord avec la RFC8020, mais c’est aussi la meilleure manière de le faire puisque une redirection vers une adresse IP, telle que 127.0.0.1 ou 0.0.0.0 fera simplement que le client qui initie la requête DNS se parlera à lui-même.
Il se peut que le navigateur réponde avec quelque chose comme :
Firefox can't establish a connection to the server at 0.0.0.0.
.
Toutefois, puisque l’adresse IP 0.0.0.0 se traduit simplement par notre
machine locale, nous pouvons toujours envoyé un ping à cette adresse, car
elle est synonyme d’un ping à 127.0.0.1 :
$ ping 0.0.0.0
PING 0.0.0.0 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.019 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.049 ms
Et puisque je recommande que vous utilisiez une réponse NXDOMAIN, c’est ce que nous allons utiliser dans ce tutoriel.
Avec l’introduction de DoH (DNS over HTTPS), le blocage par DNS est devenu beaucoup plus difficile, et, bien que j’ai un certain respect pour l’idée originale derrière la promotion de DoH du point de vue de la confidentialité, DoH est mal construit d’un point de vue de la sécurité, et c’est une MAUVAISE approche.
Avec le nombre déjà croissant de serveurs DNS publiques capable de servir du DNS sur HTTPs, toute application peut maintenant utiliser DoH et contourner complétement le blocage par DNS au niveau privé et entreprise. Non seulement cela, mais DoH a ouvert une large porte pour les dévelopeurs d’application afin de paramétrer leurs propres serveurs DoH et de les utiliser dans leurs applications au lieu du serveur DNS régulier attaché au réseau interne. C’est spécifiquement un problème pour le logiciel propriétaire dont nous ne pouvons pas voir le code source, mais dont nous ne pouvons pas aussi changer les paramétres DoH.
À cause de DoH, nous ne pouvons plus bloquer simplement des domaines, tels que les publicitaires ou le porno, nous devons aussi commencer à bloquer les serveurs DoH publiques via le pare-feu. Toutefois, bien que garder une liste croissante d’un nombre d’adresses IP de serveurs DoH publique soit assez problèmatique, garder une liste de serveurs DoH publiques inconnus, qui peuvent être utilisé par du logiciel propriétaire, tel que du micro-logiciel dans des dispositifs IoT, est impossible.
DoH est aussi un complet cauchemard pour les entreprises car il rend basiquement possible de surpasser les paramétres DNS imposés centralement. Cela rend impossible de fournir des solutions de filtrage, telle que celle que nous faisons, pour bloquer la publicité et le porno, et rend impossible pour les administrateurs systèmes de surveiller les paramétres DNS du système d’exploitation afin de prévenir les attaques de manipulation DNS. Avoir de multiples applications qui ont leur unique paramétre DoH est un cauchemar.
DoH gène complétement l’analyse réseau et la surveillance du trafic DNS à des fins de sécurité. En 2019, Godlua, un bot Linux DDoS, était le premier logiciel malveillant vu à utiliser DoH pour cacher son trafic DNS.
De plus, et c’est peut-être l’aspect le plus important, DoH n’empêche aucunément le suivi des utilisateurs. Certaines parties de la connection HTTPS ne sont pas chiffrées, tels que les champs SNI (mais on y arrive lentement), les connexions OCSP, et bien sûr les adresses IP de destination, ce qui à mon humble avis est le point le plus crucial de la communication qui a besoin d’être caché !
Les personnes qui ont vraiment besoin de confidentialité, tels que les journalistes dans des pays ayant une politique de confidentialité compromise, ne peuvent faire confiance à DoH ! L’adresse IP du serveur de destination ne peut pas être caché avec DoH, même si tout le trafic est lui-même chiffré. Si quelqu’un a vraiment besoin de chiffrer la communication, il a besoin d’une stratégie complétement différente de DoH.
Cela me fait me demander qui a pensé que DoH était une bonne idée au départ ?! Ne comprennent-ils pas les bases derrière les communications avec HTTPS, ou peut-être est-ce l’agenda poussé par quelques entreprises privées de service DNS, tel que Cloudflare, qui tire profit en collectant davantage de données utilisateurs ?
Certains fournisseurs de service DNS publique status que d’un point de vue de la confidentialité, DoH est meilleur que d’autres alternatives, telle DoT (DNS over TLS), puisque les requêtes DNS sont cachées dans le large flux du trafic HTTPS. Cela donne aux administrateurs réseaux moins de visibilité mais fournit aux utilisateurs plus de confidentialité.
Ce message est problématique. Bien qu’il soit vrai que la recherche initiale d’un nom de domaine soit caché dans le trafic HTTPS, l’adresse IP de destination fournit par le serveur DoH ne l’est pas. Quand l’application cliente visite l’adresse IP de destination, les deux adresses IP, celle de source et celle de destination, sont journalisées au niveau du FAI (et possiblement à de multiples autres niveaux, aussi bien).
Bien qu’il ne soit pas immédiatement possible de déterminer exactement quel nom de domaine l’utilisateur essaye d’atteindre, spécifiquement si le serveur web fait fonctionner de multiples domaines sur la même adresse IP, ce n’est définitivement pas impossible voire n’est même pas difficile.
Paramètrer Unbound est très facile, car Unbound est fourni avec les meilleurs paramètres par défaut, mais est aussi très bien documenté. Avant que nous commencions, je vous recommande de regarder les pages des manuels OpenBSD pour unbound, unbound-checkconf et unbound.conf.
Du fait qu’Unbound soit chrooté
sur OpenBSD, le fichier de configuration unbound.conf
ne réside pas
dans /etc
, là où il devrait être normalement, mais à la place réside
dans /var/unbound/etc/
.
Copiez le fichier de configuration existant d’Unbound :
# mv /var/unbound/etc/unbound.conf /var/unbound/etc/unbound.conf.backup
Ensuite, utilisez votre éditeur texte favori et créer un nouveau fichier
/var/unbound/etc/unbound.conf
et remplissez-le avec le contenu suivant :
server:
# Logging (default is no).
# Uncomment this section if you want to enable logging.
# Note enabling logging makes the server (significantly) slower.
# verbosity: 2
# log-queries: yes
# log-replies: yes
# log-tag-queryreply: yes
# log-local-actions: yes
interface: 127.0.0.1
interface: 192.168.1.1
interface: 192.168.2.1
interface: 192.168.3.1
# In case you need Unbound to listen on an alternative port, this is the
# syntax:
# interface: 127.0.0.1@5353
# Control who has access.
access-control: 0.0.0.0/0 refuse
access-control: ::0/0 refuse
access-control: 127.0.0.0/8 allow
access-control: ::1 allow
access-control: 192.168.1.0/24 allow
access-control: 192.168.2.0/24 allow
access-control: 192.168.3.0/24 allow
# "id.server" and "hostname.bind" queries are refused.
hide-identity: yes
# "version.server" and "version.bind" queries are refused.
hide-version: yes
# Cache elements are prefetched before they expire to keep the cache up to date.
prefetch: yes
# Our LAN segments.
private-address: 192.168.0.0/16
# We want DNSSEC validation.
auto-trust-anchor-file: "/var/unbound/db/root.key"
# Enable the usage of the unbound-control command.
remote-control:
control-enable: yes
control-interface: /var/run/unbound.sock
J’ai commenté les options ci-dessus, mais si vous avez besoin d’explications plus profondes concernant la configuration, regardez la page du manuel unbound.conf.
La journalisation est faite par défaut vers syslog. Si vous voulez changer cela, vous pouvez créer un fichier log dans le chroot d’Unbound et ainsi avoir le journal d’Unbound :
# mkdir /var/unbound/log
# touch /var/unbound/log/unbound.log
# chown -R root._unbound /var/unbound/log
# chmod -R 774 /var/unbound/log
Et, dans le fichier unbound.conf
, ajoutez les options suivantes vers la
section de journalisation :
logfile: "/log/unbound.log"
use-syslog: no
log-time-ascii: yes
logfile
ci-dessus, le fichier log se retrouve dans
/var/unbound/log/unbound.log
.Puis, redémarrez Unbound :
# rcctl restart unbound
Dans les paramétres ci-dessus, j’ai autorisé Unbound à écouter l’interface
loopback (127.0.0.1) en premier afin que les applications réseaux locales
soient capables de faire des recherches si besoin.
Dans le fichier etc/resolv.conf
de notre routeur OpenBSD, j’ai listé
notre serveur DNS Unbound, car je ne veux rien sur le routeur qui interroge
les serveurs DNS du FAI :
nameserver 127.0.0.1
Si vous utilisez DHCP sur l’interface externe (l’interface connecté au
modem ou routeur de votre FAI), vous devez vous assurez que dhclient
ne change pas la configuration du fichier /etc/resolv.conf
.
Éditez le fichier /etc/dhclient.conf
et ajoutez :
supersede domain-name-servers 127.0.0.1;
Cela permettra de s’assurer que nous avons notre serveur DNS local listé.
Activez Unbound avec :
# rcctl enable unbound
Lorsque vous changez la configuration d’Unbound, vous pouvez soit juste redémarrer Unbound avec :
# rcctl restart unbound
ou simplement recharger les options de configuration (ce qui purge aussi le cache) :
# unbound-control reload
Vous pouvez lister avec quels paramétres Unbound est démarré par la commande suivante (qui est fourni pour tout service sous OpenBSD) :
# rcctl get unbound
Si vous voulez avec certaines statitiques des données, vous pouvez exécuter :
# unbound-control stats_noreset
thread0.num.queries=2056
thread0.num.queries_ip_ratelimited=0
thread0.num.cachehits=678
thread0.num.cachemiss=1378
thread0.num.prefetch=15
thread0.num.expired=0
…
Vous pouvez aussi avoir un dump du cache :
# unbound-control dump_cache|less
Si vous voulez voir quelles sont les requêtes du serveur de nom Unbound fait pour un domaine spécifique, vous pouvez faire cela avec :
# unbound-control lookup wikipedia.org
Si vous voulez purger le cache pour un domaine spécifique, vous pouvez faire cela avec :
# unbound-control flush example.com
Prenez le temps de regarder la page du manuel d’unbound-control pour les autres options et commandes.
Une chose qui crée une grande nuisance est le paramétrage de certaines personnes sur des valeurs TTL ridiculeusement basses pour leurs domaines. Pour certaines raisons, il est presque tendance d’avoir une valeur par défaut de 60 secondes.
Le problème avec un TTL très bas est que cela rend complétement inutile le DNS cache. Une requête utilisera seulement la réponse en cache aussi longtemps que le TTL ne soit pas expiré. Même au-travers des RFC qui disent qu’un TTL doit être respecté, de telles valeurs basses rend le DNS extrêmement inefficace. Je recommande toutefois que vous surchargiez le paramétrage TTL par celui d’une heure par défaut. Une autre amélioration dans la vitesse de requête de DNS est de réduire la latence en se servant des enregistrements périmés avant de les mettre à jour d’une autre manière au lieu de faire l’inverse.
cache-min-ttl: 3600
serve-expired: yes
Un problème théorique avec l’augmentation du TTL est que le domaine pourrait obtenir une nouvelle adresse IP qui ne peut pas être résolu puisque l’ancienne entrée est dans le cache. Toutefois, dans la pratique le risque de fonctionner sur un domaine périmé est minime et ça vaut la peine d’améliorer l’utilisation du cache en fixant un TTL d’une heure minimum par défaut.
Maintenant, intéressons-nous à la partie du blocage de domaines.
J’ai créé un simple script shell appelé DNSBlockBuster qui télécharge automatiquement un jeu de fichiers hosts depuis diverses sources en-ligne, les concaténant ensemble en une seule, la nettoyant, et convertissant le résultat en une liste de blocage de domaines pour Unbound et dnsmasq. Elle bloque principalement les publicités, les sites de porno et de pistage.
Avec DNSBlockBuster, vous avez l’option de créer une liste blanche, si pour vous l’un des domaines listés dans les fichiers hosts est un faux positif, et vous pouvez ajouter votre propre liste de blocage dans le cas où vous voulez bloquer manuellement certains domaines qui ne sont pas listés dans les fichiers hosts. Vous pouvez facilement ajouter de nouvelles listes de blocage ou supprimer l’une des listes de blocage fournies.
Bien sûr, vous n’avez pas besoin d’utiliser mon script, mais je l’utiliserais dans ce tutoriel.
Actuellement le script créé une énorme liste de domaines avec plus de deux millions de domaines listés et Unbound prend près de 705 Mo de mémoire au total quand la liste de blocage est chargée en entier.
Afin d’éviter qu’Unbound tombe en panne lors du chargement de la liste,
éditez /etc/rc.conf.local
et ajoutez ce qui suit :
unbound_timeout=240
Puis redémarrez Unbound :
# rcctl restart unbound
Regardez la section Usage dans la documentation de DNSBlockBuster pour savoir comment l’utiliser. C’est simple et facile.
Une fois que vous avez créé votre liste de blocage pour Unbound, placez
la dans /var/unbound/etc/
et éditez le fichier de configuration d’Unbound
/var/unbound/etc/unbound.conf
pour insérer quelque chose comme :
include: "/var/unbound/etc/unbound-blocked-hosts.conf"
Maintenant rechargez Unbound avec :
# unbound-control reload
Si vous exécutez la commande top
dans un autre terminal, vous remarquerez
qu’Unbound consomme pas mal de ressources CPU lors du chargement initial
de la liste.
Remarquez aussi la consommation mémoire.
Vous pouvez maintenant tester notre blocage DNS en faisant une requête vers un domaine bloqué de la liste :
$ drill 3lift.com
;; ->>HEADER<<- opcode: QUERY, rcode: NXDOMAIN, id: 55906
…
Essayez le même avec le serveur DNS de Cloudflare :
$ drill 3lift.com @1.1.1.1
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 48771
…
Comme nous pouvons le voir, notre serveur DNS bloque l’accès au domaine 3lift.com en répondant avec un NXDOMAIN, alors que le serveur DNS de Cloudflare répond avec l’adresse IP correcte.
La sécurité DNS est un vaste sujet. Dans cette section, nous allons discuter de certains des sujets qui nous concernent plus particulièrement à propos de notre propre serveur DNS.
Le protocole DNS n’est pas chiffré et ne tient, par défaut, aucun compte de la confidentialité, de l’intégrité ou de l’authentification. Si vous utilisez un réseau non fiable, ou un FAI malveillant, vos requêtes DNS peuvent être écoutées et les réponses manipulées. En outre, les FAI peuvent procéder à des détournements de DNS.
Le détournement de DNS signifie que les requêtes DNS que vous faites sont redirigées vers un autre serveur DNS. C’est typiquement fait en redirigeant tout le trafic sur le port 53 à destination d’un autre.
Un des manières les plus simples pour déterminer si votre FAI détourne votre trafic DNS est d’interroger directement un serveur DNS faisant autorité.
Nous pouvons utiliser de multiples outils pour cela.
Dans cet exemple, nous utiliserons en premier drill
.
Ces options, dans cet exemple, sont les mêmes pour dig
.
Nous utiliserons encore le domaine “wikipedia.org”.
En premier, nous avons besoin d’avoir les serveurs faisant autorité. Ils apparaîtront dans la section “ANSWER SECTION” :
$ drill NS wikipedia.org
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 28789
;; flags: qr rd ra ; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; wikipedia.org. IN NS
;; ANSWER SECTION:
wikipedia.org. 85948 IN NS ns2.wikimedia.org.
wikipedia.org. 85948 IN NS ns0.wikimedia.org.
wikipedia.org. 85948 IN NS ns1.wikimedia.org.
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 1 msec
;; SERVER: 127.0.0.1
;; WHEN: Thu Nov 5 07:53:19 2020
;; MSG SIZE rcvd: 95
Alors nous devons interroger l’un de ses serveurs faisant autorité directement.
Le champ important auquel nous devons faire attention est flags dans le
champ “HEADER”.
Pour que la réponse fasse autorité, le drapeau aa
doit être listé.
$ drill @ns1.wikimedia.org wikipedia.org
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 57611
;; flags: qr aa rd ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; wikipedia.org. IN A
;; ANSWER SECTION:
wikipedia.org. 600 IN A 91.198.174.192
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 127 msec
;; SERVER: 208.80.153.231
;; WHEN: Thu Nov 5 07:56:10 2020
;; MSG SIZE rcvd: 47
Cela montre que la réponse que nous avons n’a pas été détournée puisque la réponse fait autorité. Essayons de l’obtenir depuis le serveur DNS publique de Cloudflare avec la même requête :
$ drill @1.1.1.1 wikipedia.org
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 40562
;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; wikipedia.org. IN A
;; ANSWER SECTION:
wikipedia.org. 555 IN A 91.198.174.192
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 3 msec
;; SERVER: 1.1.1.1
;; WHEN: Thu Nov 5 08:02:58 2020
;; MSG SIZE rcvd: 47
Notez que le drapeau aa
est manquant dans le champ “HEADER”.
Cela signifie que la réponse ne fait pas autorité.
Un autre outil simple est nslookup. En premier interrogeons les serveurs de noms faisant autorité :
nslookup -querytype=NS wikipedia.org
Server: 127.0.0.1
Address: 127.0.0.1#53
Non-authoritative answer:
wikipedia.org nameserver = ns1.wikimedia.org.
wikipedia.org nameserver = ns2.wikimedia.org.
wikipedia.org nameserver = ns0.wikimedia.org.
Essayons alors d’interroger notre propre serveur DNS pour le domaine :
$ nslookup wikipedia.org
Server: 127.0.0.1
Address: 127.0.0.1#53
Non-authoritative answer:
Name: wikipedia.org
Address: 91.198.174.192
Server: ns2.wikimedia.org
Address: 91.198.174.239#53
Name: wikipedia.org
Address: 91.198.174.192
Le message Non-authoritative
montre clairement que la réponse n’est pas
faite depuis un serveur DNS faisant autorité.
C’est très bien, puisque nous avons interrogé notre propre serveur DNS.
Essayons d’interroger un des serveurs faisant autorité directement :
$ nslookup wikipedia.org ns0.wikimedia.org
Server: ns0.wikimedia.org
Address: 208.80.154.238#53
Name: wikipedia.org
Address: 91.198.174.192
Le message Non-authoritative
n’est plus là, la réponse que nous avons
obtenu faisait autorité, ce qui signifie que notre requête DNS n’a pas
été détournée.
J’ai maintenant activé un service VPN que je connais pour intercepter les requêtes DNS afin de protéger les clients contre la fuite DNS puis je fais une requête à nouveau vers les serveurs faisant autorité :
$ nslookup wikipedia.org ns0.wikimedia.org
Server: ns0.wikimedia.org
Address: 208.80.154.238#53
Non-authoritative answer:
Name: wikipedia.org
Address: 91.198.174.192
Name: wikipedia.org
Address: 2620:0:862:ed1a::1
Comme attendu la réponse ne fait pas autorité quand bien même j’ai interrogé directement le serveur faisant autorité. Le trafic DNS a été détourné et la réponse a été redirigé depuis un autre serveur DNS inconnu.
Le détournement DNS, qu’il soit effectué par un FAI ou par quelqu’un d’autre, est hautement problèmatique. Tout d’abord, nous ne pouvons avoir pleinement confiance aux réponses que nous obtenons depuis le serveur DNS. En second, même si la réponse DNS fournit des données non falsifiées, le trafic DNS a été détourné pour une raison inconnue, qui peut être de la collecte et de l’enregistrement de données, ou pour une raison complètement différente.
Si vous avez découvert que votre trafic DNS sur le port 53 est détourné, vous avez basiquement seulement trois options afin de vous protéger :
L’usurpation de DNS, aussi appelé empoisonnement du cache DNS, est différent du détournement de DNS. Alors que le trafic est redirigé d’une destination vers une autre dans une attaque de détournement de DNS, c’est la donnée elle-même qui est manipulée dans une attaque d’usurpation DNS. Souvent ces deux stratégies d’attaques sont combinées.
Dans une attaque d’usurpation de DNS, la donnée manipulée est introduite dans le cache du résolveur DNS, résultant que le serveur de nom retourne un résultat incorrect, e.g. une mauvaise adresse IP.
Ce type d’attaque peut être atténuée au niveau de la couche transport ou de la couche application en effectuant une validation de bout en bout une fois qu’une connexion est établie. Un exemple courant de cela est l’utilisation de TLS et des signatures digitales.
DNSSEC utilise des signatures digitales cryptographiques avec un certificat de clé publique de confiance pour déterminer l’authenticité des données. DNSSEC peut protéger contre l’usurpation de DNS, toutefois beaucoup d’administrateurs DNS ne l’ont pas encore implémenté.
À partir de 2020, tous les TLD originaux prennent en charge DNSSEC, comme le font les TLD de code de pays, mais de nombreux TLD de code de pays ne le font toujours pas.
Je veux illustrer le fait que DoH ne fournit pas réellement une véritable confidentialité autant de l’adresse IP source que celle de destination, qui peuvent être vues clairement dans la communication HTTPS.
En premier, je m’assure que DoH soit désactivé dans Firefox, sur un des
ordinateurs du LAN pour adultes, et je surveille le trafic sur l’interface
em1
par l’utilisation de tcdump.
J’ai aussi activé la journalisation dans Unbound, juste pour éviter de
remplir inutilement syslog avec trop de bruits DNS, et j’ai utilisé
tail pour surveiller le journal.
J’irais sur “wikipedia.org” dans le navigateur et voir ce que révèle la surveillance sur le routeur.
# tcpdump -n -i em1 src host 192.168.1.5 and not arp
tcpdump: listening on em1, link-type EN10MB
23:30:33.494352 192.168.1.5.55724 > 192.168.1.1.53: 58136+ A? wikipedia.org.(31) (DF)
23:30:33.774439 192.168.1.5.58372 > 192.168.1.1.53: 58448+ A? www.wikipedia.org.(35) (DF)
23:30:34.184287 192.168.1.5.46639 > 192.168.1.1.53: 15167+ A? www.wikipedia.org.(35) (DF)
…
# tail -f /var/unbound/log/unbound.log
Nov 05 23:30:33 unbound[12636:0] query: 192.168.1.5 wikipedia.org. A IN
Nov 05 23:30:33 unbound[12636:0] reply: 192.168.1.5 wikipedia.org. A IN NOERROR 0.097209 0 47
Nov 05 23:30:33 unbound[12636:0] query: 192.168.1.5 www.wikipedia.org. A IN
Nov 05 23:30:33 unbound[12636:0] reply: 192.168.1.5 www.wikipedia.org. A IN NOERROR 0.154989 0 80
Nov 05 23:30:34 unbound[12636:0] query: 192.168.1.5 www.wikipedia.org. A IN
Nov 05 23:30:34 unbound[12636:0] reply: 192.168.1.5 www.wikipedia.org. A IN NOERROR 0.000000 1 80
…
Naturellement nous avons vu la requête autant dans le trafic de l’interface que dans le journal d’Unbound.
J’ai activé alors DoH et désactivé le DNS régulier dans Firefox, en
paramétrant la valeur de network.trr.mode
à 4
.
J’ai alors changé les paramétres réseaux
et paramétré Cloudflare en
tant que fournisseur DoH.
Si vous activez juste DoH via les préférences, Firefox utilisera toujours
le DNS régulier comme solution de repli.
Avant de forcer Firefox à utiliser seulement DoH, vous devez paramétrer
la value de network.trr.mode
.
Écrivez about:config
dans la barre d’adresses et pressez la touche
Entrée pour accéder au panneau de configuration caché de Firefox.
Étape 2 : Cherchez le paramétre network.trr.mode
.
Il contrôle la prise en charge de DoH.
Ce paramétre a 4 valeurs :
Étape 3 : Cherchez le paramétre network.trr.bootstrapAddress
.
Il contrôle l’adresse IP numérique de votre serveur DoH.
Entrez la valeur 1.1.1.1
et appuyez sur la touche Entrée.
Cette fois, je visiterais “freebsd.org”.
# tcpdump -n -i em1 src 192.168.1.5 and not arp
tcpdump: listening on em1, link-type EN10MB
00:21:10.944243 192.168.1.5.32856 > 1.1.1.1.443: P 2223446146:2223446202(56) ack 157857007 win 501 (DF)
00:21:10.948719 192.168.1.5.46584 > 96.47.72.84.80: S 922508523:922508523(0) win 64240 <mss 1460,sackOK,timestamp 1673624773 0,nop,wscale 7> (DF)
00:21:11.133801 192.168.1.5.33298 > 96.47.72.84.443: S 3275123911:3275123911(0) win 64240 <mss 1460,sackOK,timestamp 1673624958 0,nop,wscale 7> (DF)
…
# tail -f /var/unbound/log/unbound.log
Nov 05 23:30:33 unbound[12636:0] query: 192.168.1.5 wikipedia.org. A IN
Nov 05 23:30:33 unbound[12636:0] reply: 192.168.1.5 wikipedia.org. A IN NOERROR 0.097209 0 47
Nov 05 23:30:33 unbound[12636:0] query: 192.168.1.5 www.wikipedia.org. A IN
Nov 05 23:30:33 unbound[12636:0] reply: 192.168.1.5 www.wikipedia.org. A IN NOERROR 0.154989 0 80
Nov 05 23:30:34 unbound[12636:0] query: 192.168.1.5 www.wikipedia.org. A IN
Nov 05 23:30:34 unbound[12636:0] reply: 192.168.1.5 www.wikipedia.org. A IN NOERROR 0.000000 1 80
…
Cela révèle, depuis la surveillance de l’interface réseau, qu’une connexion
a été faite vers le serveur DNS de Cloudflare à l’adresse 1.1.1.1 sur le
port 443 (HTTPS) et que nous avons visité l’adresse IP de destination
96.47.72.84 juste après.
Dans le même temps, rien n’est arrivé dans le journal d’Unbound, tail
nous montrant juste toujours la requête précédente.
Si nous faisons une requête au DNS régulier sur le serveur, nous pouvons vérifier que l’adresse IP 96.47.72.84 est bien l’adresse IP de “freebsd.org”.
De plus, dans cet exemple spécifique, nous pouvons même accéder au site web de “freebsd.org” en écrivant juste l’adresse IP de destination 96.47.72.84 dans le champ de la barre d’adresse du navigateur.
Cela démontre que même si DoH bypasse la requête d’un DNS régulier, il n’est pas capable de cacher l’adresse IP de destination qui est toujours présente en clair dans le trafic de la communication.
Auparavant, le script DNSBlockBuster comportait certains noms de domaines DoH dans la liste, que j’avais ajouté aléatoirement, mais j’ai depuis supprimé le blocage DoH du serveur DNS, car il faut vraiment que cela soit géré au niveau du pare-feu.
Bloquer DoH via les noms de domaine n’a pas beaucoup de sens à mon humble opinion car un nom de domaine peut être cherché en premier lieu. La plupart des clients qui utilisent DoH ont l’adresse IP de l’hôte du serveur DoH encodé directement dans leur code source.
J’ai cherché sur de multiples sites sur Internet, mais aucun n’a trouvé une simple manière de mettre à jour la liste des serveurs publiques DoH, ainsi j’ai décidé de faire ma propre liste appelée DoHBlockBuster. Toutefois c’est une tâche énorme, dont je sais que je n’aurais pas le temps de tenir à jour à l’avenir, à moins que d’autres personnnes ne s’y mettent ; alors si vous avez du temps libre, aidez à tenir à jour les listes (en faisant une demande de retrait ou en m’envoyant un courriel). En outre, cette liste n’est en aucun cas exhaustive.
Si vous n’utilisez pas IPv6, vous pouvez bloquer tout le trafic IPv6, et
utilisez alors seulement la liste IPv4 de DoHBlockBuster.
Changez le paramétre pass out
, dans la section “Default protect and block”
de /etc/pf.conf
en pass out inet
.
C’est la manière pour permettre seulement le trafic IPv4 sortant, sans
avoir à bloquer spécifiquement les adresses IPv6 relatives à DoH.
Téléchargez les listes depuis DoHBlockBuster et éditez les selon vos besoins et enregistrez les quelque part sur le disque.
J’ai fait un sous-répertoire à /etc/pf-block-lists
où j’ai placé toutes
les listes de blocage dont j’ai besoin pour PF.
Créez alors un fichier persistant pour PF dans la section “Tables” de
/etc/pf.conf
:
# Public DoH servers.
table <block_doh> persist file "/etc/pf-block-lists/dohblockbuster-ipv4.txt"
Si vous avez besoin d’IPv6, ajoutez alors cela aussi :
table <block_doh> persist file "/etc/pf-block-lists/dohblockbuster-ipv4.txt" file "/etc/pf-block-lists/dohblockbuster-ipv6.txt"
Et, alors ajoutez un block
à la section “Protect and block by default”
du pare-feu :
# Let's block DoH.
block in quick on { $g_lan $c_lan $dmz } to <block_doh>
Rechargez PF :
# pfctl -f /etc/pf.conf
Vérifiez la liste avec :
# pfctl -vvt block_doh -T show
Si - après quelques temps - vous voulez voir quelles adresses IP sont actuellement bloquées, vous pouvez filtrer la sortie :
# pfctl -vvt block_doh -T show | awk '/\[/ {p+=$4; b+=$6} END {print p, b}'
Comme mentionné précédemment, cette solution ne prend pas en considération les serveurs DoH inconnus. De plus afin que la liste soit efficace, elle a besoin d’être tenue à jour.
Si nous paramétrons notre réseau de telle manière que tous les ordinateurs
et dispositifs aient leurs adresses IP fixes et noms d’hôtes, beaucoup
d’outils ne fonctionneront pas nativement avec ces noms d’hôtes sans ajouter
un nom de domaine au serveur DNS.
Cela est dû à des outils tel que host
qui s’attend à ce que la recherche
vers un nom d’hôte soit
un nom de domaine pleinement qualifié (FQDN).
Disons que j’ai paramétré un ordinateur sur mon LAN ayant pour nom d’hôte “foo” et l’adresse IP fixée à 192.168.1.7. Je ne me souviens peut être pas que “foo” est l’ordinateur avec telle adresse, ou je ne me souviens pas quel hôte a l’adresse IP 192.168.1.7 associée.
Avec un FQDN, nous pouvons faire une recherche telle que :
$ host foo.example.com
foo.example.com has address 192.168.1.7
Alors nous pouvons faire :
# host 192.168.1.7
7.1.168.192.in-addr.arpa domain name pointer foo.example.com
Toutefois, il est ennuyeux de devoir écrire le nom de domaine complet à
chaque fois.
Si nous ajoutons l’option domain-name
à /etc/resolv.conf
le nom de domaine sera automatiquement ajouté.
Ainsi, nous pouvons faire juste cela :
$ host foo
foo.example.com has address 192.168.1.7
Certaines personnes recommandent d’enregistrer un nom de domaine et de
l’utiliser en interne sur votre LAN, et bien que ce soit certainement
fonctionnel, ce n’est pas intéressant du tout.
Pour l’utilisation à la maison, vous pouvez utilisez les TLD .intranet
,
.home
ou .lan
, en accord avec la
RFC 6762 sans aucun
problème.
Toutefois, n’utilisez pas .local
.
Démarrons en faisant quelques changements dans la configuration de /etc/dhcpd.conf
.
Juste pour faire simple, j’utiliserais le serveur web de notre LAN publique
en exemple, mais vous pouvez étendre cela à tout segment où vous le désirez,
et vous pouvez aussi l’utiliser sur plusieurs segments si besoin.
Dans notre paramétrage actuel, nous avons déjà le domaine example.com
attaché à notre serveur web ainsi nous pouvons juste l’utiliser.
Mais si vous n’avez pas de serveur publique qui a un réel nom de domaine,
changez-le juste par quelque chose comme net.home
.
J’ai changé le nom de notre serveur web par “lilo” (oui, de Lilo & Stitch,
parce que c’est plus cool que “Luke” ou “Yoda” !).
subnet 192.168.1.0 netmask 255.255.255.0 {
option domain-name-servers 192.168.1.1;
option domain-name "example.com";
option routers 192.168.1.1;
range 192.168.1.10 192.168.1.254;
}
subnet 192.168.2.0 netmask 255.255.255.0 {
option domain-name-servers 192.168.2.1;
option domain-name "example.com";
option routers 192.168.2.1;
range 192.168.2.10 192.168.2.254;
}
subnet 192.168.3.0 netmask 255.255.255.0 {
option domain-name-servers 192.168.3.1;
option domain-name "example.com";
option routers 192.168.3.1;
range 192.168.3.10 192.168.3.254;
host lilo.example.com {
fixed-address 191.168.3.2;
hardware ethernet 61:20:42:39:61:AF;
option host-name "lilo";
}
}
Si vous préférez utiliser de multiples domaines plutôt qu’un seul, dites-vous
que example.com
est pour votre développement web professionnel, et que
net.home
pour votre LAN privé, vous pouvez faire une recherche de domaine
avec l’option domain-search
dans /etc/dhcpd.conf
au lieu de l’option
domain-name
.
La différence entre les deux est qu’avec domain-name
, seulement un seul
domaine est ajouté, alors qu’avec l’option domain-search
, de multiples
domaines peuvent être ajoutés et sont alors “cherchés” un par un jusqu’à
ce que l’hôte soit trouvé.
L’option domain-search
ressemble à ceci :
option domain-search "example.com", "net.home"
Alors nous avons besoin de paramétrer Unbound pour gérer nos adresses IP
fixes.
Dans cet exemple, nous avons seulement le serveur web, mais nous pouvons
utiliser autant d’hôtes que nécessaires.
Vous pouvez juste éditer le fichier de configuration principale d’Unbound,
mais je préfére mettre cela dans un fichier séparé et l’inclure dans le
fichier principal.
Créez un nouveau fichier appelé tel que /var/unbound/etc/unbound-local.conf
,
par exemple, et paramétrez vos hôtes :
local-data: "lilo.example.com IN A 192.168.3.2"
local-data-ptr: "192.168.3.2 lilo.example.com"
Ou, si vous utilisez la version net.home
:
local-data: "lilo.net.home IN A 192.168.3.2"
local-data-ptr: "192.168.3.2 lilo.net.home"
Notez comment l’adresse IP dans le champ local-data-ptr
est retourné,
ce qui n’est pas une erreur.
Ajoutez alors ce qui suit à notre /var/unbound/etc/unbound.conf
:
private-address: 192.168.0.0/16
private-domain: example.com # Use net.home instead if you need that.
include: "/var/unbound/etc/unbound-local.conf"
Redémarrez dhcpd et Unbound :
# rcctl restart dhcpd
# rcctl restart unbound
Si vous retirez le câble Ethernet de l’un des ordinateurs connectés à l’un
des LAN et le connectez à nouveau, vous serez notifié que /etc/resolv.conf
a ajouté l’option domain
:
domain example.com
nameserver 192.168.1.1
Vous pouvez étendre cet exemple ci-dessus à de multiples domaines et de multiples dans tous les segments.
Lorsque vous avez paramétré votre routeur OpenBSD, je vous encourage fortement à paramétrer pf-badhost !
pf-badhost est un script de sécurité léger fait par Jordan Geoghegan qui bloque les plus grandes choses irritantes d’Internet. Les désagréments tels les brute-forceurs SSH et SMTP sont largement éliminés par ce script.
pf-badhost ajoute périodiqument des addresses IP depuis des bases de données de spammeurs d’IP bien connus, tel Spamhaus, Firehol, Emerging Threats and Binary Defense, où ces mauvaises adressses IP sont fréquemment journalisées. pf-badhost les ajoute alors aux adresses IP collectées vers le pare-feu PF dans une table qui est bloquée par défaut.
Veuillez considérer de contribuer si vous avez n’importe quel commentaire, correction, ou changement que vous considéré comme approprié.
Vous pouvez aussi juste envoyer un courriel.
Veuillez noter que les traductions listées ici sont commitées par d’autres personnes contribuant généreusement à ce guide. De fait, je ne suis pas responsable de garder à jour ces traductions.
Créé et maintenu par
Le Guide du Routeur OpenBSD est sous licence Creative Commons Attribution 4.0 International.
Si vous trouvez ce contenu utile, soutenez-moi sur Patreon.
Cette version traduite du Guide du Routeur OpenBSD est faite par mes soins.
Vous pouvez contribuer au-travers de mon dépôt Framagit.org.
Par facilité, cette traduction est placée aussi sous licence Creative Commons Attribution 4.0 International.
Vous pouvez soutenir mon effort de traduction en me payant un bon café à l'italienne comme je les <3 … :D
Retrouvez sur cette page mes différentes participations et autres traductions que j’ai faites, soit par mes propres soins, soit en collaborant avec des équipes :
La plupart de ces traductions diverses sont hébergés sur le wiki de la communauté “OpenBSD pour Tous” !
⇒ Date inconnue : l’article “Comprendre Unix en 10 Minutes” de feu site Freeenginer.org
⇒ 2017
⇒ 2018
⇒ 2019
En Mars, traduction du site Why OpenBSD Rocks !
En Décembre, relecture pour le site de Gilles Chehade, de deux articles - cf PR #30 et #32
⇒ 2020
En Février, différentes relectures pour le site Disroot - pour les remercier de m’avoir aidé - cf les PR #31 et #32
Traduction :
⇒ 2018
⇒ 2019
Courant Mars, sur les pages :
En Avril, à-propos :
Collaborer avec cette communauté est extrêmement simple : il suffit de s’enregistrer et de s’y mettre. Un régal !
⇒ 2019
En Mai, j’ai fait de la relecture :
En Juin, relecture :
Collaborez avec cette communauté est sympa, mais le processus est assez lourd.
⇒ Depuis fin 2016, étant co-fondateur de la communauté OpenBSD pour Tous, principal administrateur, et traducteur :
⇒ 2017 : Courant mai, commencé un gros travail de traduction sur :
⇒ 2020
En Mai, sur les pages des projets :
En Juin, sur les pages du site OpenBGPD.org
Je m’efforce de maintenir principalement la traduction des pages du site OpenBSD et de ses différentes FAQ, très régulièrement.
Auprès de la communauté python-docs-fr :
⇒ 2019
le 2 Juin, j’ai fait remonté ma première participation #805 ; le but étant de tester la collaboration avec l’équipe, fusionnée le même jour !
le 10 Juin, j’ai commencé mon premier travail de traduction sur la library/thread, fusionné deux jour plus tard - PR #813.
le 12 Juin, j’ai commencé un long travail sur la library/bz2 - qui pour diverses raisons, a pris environ 6 mois - fusionné le 1 Février 2020 - PR #818.
le 12 Juin (encore), j’ai fait une proposition de modification du fichier README, qui a été accepté mais intégré différement - PR #820.
le 29 Octobre, une proposition sur le fichier Dict qui finalement a été repoussé - PR #911.
C’est clairement la communauté que j’ai le plus aimé ; collaboré avec Seluj ou deronnax est un régal.
]]>Historiquement, pour ajouter une clé GPG pour l’outil apt, on utilisait
la commande apt-key
. Or, cette commande est déclarée obsolète !
Quand vous utilisez la commande, vous avez le droit à ce message d’erreur :
Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).
Il est maintenant recommandé de déposer la clé dans le répertoire /etc/apt/keyrings/
!
Pour me simplifier la vie, je me suis créé ce petit script add-apt-k.sh
,
que je symlink vers mon répertoire personnel ~/bin/
- ainsi je peux
l’appeler où que je sois dans la racine du système :
dir_keys="/etc/apt/keyrings/"
name=""
url=""
read -p "Quel est le nom du projet ? " name
read -p "Où est l'URL de la clé GPG (à ajouter pour l'outil apt) ? " url
# creation du repertoire local de clés
[ ! -d "${dir_keyrs}" ] && mkdir -p "${dir_keys}"
# recupération de la clé du projet
curl -fsSL "${url}" | gpg --dearmor | tee "${dir_keys}/${name}.gpg" > /dev/null
status="$?"
if [ "${status}" -eq 0 ]; then
printf '%s : %s\n' "OK" "La clé GPG pour le projet '${name}' a bien été ajoutée."
else
printf '%s : %s\n' "KO" "Il semble y avoir un soucis pour ajouter la clé GPG du projet '${name}' !"
fi
Ensuite :
$ chmod 0700 $HOME/repertoire/add-apt-key.sh
$ ln $HOME/repertoire/add-apt-key.sh $HOME/bin
Puis appel du script : $ sudo ~/bin/add-apt-key.sh
Ensuite utilisation de l’outil apt pour éditer les sources et mise à jour de la base de données d’apt puis installation du binaire.
Plus d’informations sur le forum Debian-fr.org : https://www.debian-fr.org/t/apt-ajout-correct-dune-cle-gpg/85278
Enjoy-ID!
Enjoy-IT!
OpenBSD et quoi ?!
Soyons sérieux !
En fait, depuis 2014, la pile Bluetooth a été supprimé d’OpenBSD ; écriture du code “moyen-âge”, pas assez sécurisé et personne ne veut s’y mettre !
Oui, mais…
Officieusement, cela fonctionne grâce à un dongle USB Récepteur Audio Bluetooth, tel les Creative BT-W2, BT-W3 ou le Jabra Evolve 2 85 !
Vous l’avez ? Connectez-le tout simplement !
Astuce : Au cas où… vérifiez dans le Bios, que le paramétrage du mode USB 3, soit bien actif, et non pas en mode auto ou désactivé !
(…)
uaudio0 at uhub0 port 2 configuration 1 interface 1 "Creative Labs Creative Bluetooth Audio W2"
rev 2.00/1.00 addr 2
uaudio0: class v1, full-speed, sync, channels: 2 play, 1 rec, 0 ctls
audio1 at uaudio0
uhidev0 at uhub0 port 2 configuration 1 interface 3 "Creative Labs Creative Bluetooth Audio W2"
rev 2.00/1.00 addr 2
uhidev0: iclass 3/0, 3 report ids
uhid0 at uhidev0 reportid 1: input=2, output=0, feature=0
uhid1 at uhidev0 reportid 2: input=18, output=18, feature=0
uhid2 at uhidev0 reportid 3: input=64, output=64, feature=0
Vous avez ce genre de messages, la led bleue clignote : c’est OK !
Pressez le bouton du récepteur audio Bluetooth, la led bleu va clignoter très rapidement. Il reste plus qu’à activer l’appairage de votre périphérique audio.
Attachez votre dongle USB au serveur audio sndiod
:
# rcctl set sndiod flags "-f rsnd/0 -F rsnd/1"
# rcctl restart sndiod
L’outil natif sndioctl
permet de contrôler le volume, tel que :
$ sndioctl output.level=+0.05
$ sndioctl output.level=-0.05
Installez
le
paquet aucatctl
et utilisez-le en mode console, tel que :
$ aucatctl master=20
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Par défaut, OpenWRT est livré avec Dropbear. Bien que ce serveur SSH utilise seulement la version 2 du protocole SSH, et soit léger, il comporte quelques lacunes :
# opkg update
# opkg install openssh-server openssh-moduli
/etc/ssh/moduli
est un fichier contenant les nombres premiers
et les générateurs à utiliser par le serveur SSH dans la méthode d’échange
des clés de groupe DH
. Préférez l’installer…Mieux vaut laisser Dropbear sur le port par défaut.
Néanmoins, vous pouvez le reconfigurer soit par l’interface LuCI, soit en mode console - ce qui peut se faire ainsi :
# uci set dropbear.@dropbear[0].Port=xxx
# uci commit dropbear
# /etc/init.d/dropbear restart
où xxx
est le numéro de port que vous choisirez !
puis connectez-vous au serveur sur ce nouveau numéro de port.
/etc/ssh/sshd_config
Les recommandations de bases suivantes s’appliquent ABSOLUMENT :
Nous allons en profitez pour durcir la configuration par défaut :
Pour finir, ne configurez pas le service sur le port 22 ; en cas de problème, Dropbear pourra toujours vous être utile, même s’il faut le réactiver !
Si vous avez installé le paquet openssh-moduli, il serait préférable de n’accepter que les échanges de clés de groupe DH supérieure ou égale à 3072 bits.
Avant de le modifier, sauvegardons le fichier, au cas où…
# cp /etc/ssh/moduli /etc/ssh/moduli.bckp
# chmod 0400 /etc/ssh/moduli.bckp
Ensuite, il faut le recréer
Si vous avez configuré correctement un utilisateur ayant des droits sudo :
# sudo awk '$5 >= 3071' /etc/ssh/moduli | sudo tee /etc/ssh/moduli.safe
# mv /etc/ssh/moduli.safe /etc/ssh/moduli
Voici un exemple minimaliste du fichier de configuration du serveur :
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,
HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
PermitRootLogin no
MaxAuthTries 3
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
PermitEmptyPasswords no
Subsystem sftp /usr/lib/sftp-server
Et, voilà, maintenant, il ne vous reste plus qu’à vous connecter… après avoir testé la configuration puis activé et démarré le service :
# sshd -t
Si la configuration est valide :
# /etc/init.d/sshd enable
# /etc/init.d/sshd start
Vous pouvez vous connecter au service d’OpenSSH, sans soucis ? Maintenant, vous pouvez arrêter et désactiver le service :
# /etc/init.d/dropbear stop
# /etc/init.d/dropbear disable
Normalement, le répertoire /etc/ssh
et ce qu’il contient est inclus
dans la sauvegarde système par l’outil sysupgrade
.
Pour le vérifier : # sysupgrade -l | grep ssh
Si ce n’est pas le cas, éditez le fichier /etc/sysupgrade.conf
et ajoutez
le répertoire.
⇒ Impossible de se connecter après un redémarrage :
Avez-vous paramétré l’option ListenAdress
dans le fichier de configuration
du service ?
Si oui, désactivez la ligne correspondante . Du fait d’une situation de compétition, le démarrage du service OpenSSH ne peut pas s’effectuer.
Si vous spécifiez l’option ListenAddress, OpenSSH s’exécutera lorsque vous le démarrerez. Néanmoins, au redémarrage de la machine, OpenSSH échouera à démarrer car il ne trouvera pas les interfaces réseau !
Donc, évitez de spécifier cette option et configurez le parefeu pour n’autoriser que sur l’interface de votre LAN.
Par défaut, même sous OpenBSD, la configuration de SSH n’est pas des plus sécurisées.
Les algorithmes NISTP - susceptibles d’être une porte dérobée de la NSA ; mais attention, ce n’est qu’une rumeur -, voire du SHA1, sont encore utilisés.
/etc/ssh/sshd_config
Bien sûr, hormis le fait de :
$ cd /etc/ssh
# rm ssh_host_*
# ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N ""
# ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key -N "" -o -a 64
Ne mettez pas de passphrases lors de la génération, autrement le serveur ne sera pas capable de les lire…
De toute facon, le fichier /var/log/auth
vous le dira !
Ensuite, il faut veillez aux choses ci-dessous :
Commentez les déclarations HostKey
pour ne garder que celles
relatives au chiffrement RSA et ED25519.
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
Les chiffrements à autoriser sont :
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
Les algorithmes d’échanges de clé à privilégier sont :
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
Les algorithmes de clé d’Hôte sont :
HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com
Les algorithmes des Codes d’Authentification de Messages sont :
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
Le fichier moduli est un fichier contenant les nombres premiers et les générateurs à utiliser par le serveur SSH dans la méthode d’échange des clés de groupe DH .
Depuis 2017, le bogue #2793 explique que dans certains contextes le bon fonctionnement échoue, suite aux recommandations ci-dessous.
Si vous n’arrivez plus à vous connecter, envisagez de revenir en arrière sur cette modification !
Il est recommandé de le recréer de telle manière :
awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.safe
mv /etc/ssh/moduli.safe /etc/ssh/moduli
S’il est possible de le créer ainsi :
ssh-keygen -G /etc/ssh/moduli -b 3072
attention, la génération sera longue et dépend très fortement de la puissance machine de votre serveur.
Néanmoins, sachez que depuis quelques années/versions, le fichier est déjà
généré et se trouve être : /etc/moduli
Pour en savoir plus, lisez le manpage moduli(5)
Cette option est obsolète depuis la version 7.5.
Veillez à ne plus l’utiliser !
Voici un exemple minimaliste du fichier de configuration sécurisée côté serveur :
Port 22
ListenAddress 192.168.xxx.yyy
ListenAddress fd00:abcd:efg0::1
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com
PermitRootLogin no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
Si vous avez l’erreur suivante :
/etc/ssh/sshd_config line 26: Bad key types 'ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com'
Enlevez les deux déclarations suivantes sk-ssh-ed25519@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com
et testez
à nouveau, puis si c’est OK, relancez
le service.
Du fait de générer des clés RSA + PKBDF, ou ed25519, si vous avez paramétré
l’option LoginGraceTime
, pour la diminuer au strict minimum, pensez à
augmenter sa valeur, sinon vous aurez le droit à ne pas pouvoir vous
connecter, sans aucun message d’erreur dans le log d’authentification.
# sshd -t
Pour tester la configuration de votre serveur, il existe un outil nommé
ssh-audit
. Installez-le et exécutez à l’encontre de votre serveur SSH :
$ ssh-audit adresse-ip-serveur-ssh
Il est possible de tester la valeur de la configuration de votre serveur sur le site sshaudit : https://www.sshaudit.com
La touche Compose
, dite touche de composition est une touche suivi
d’un ensemble d’une ou plusieurs touches qui permet d’imprimer les
caractères Unicode
de
manière pratique.
Il faut “voir” la touche de composition comme un raccourci à la combinaison des touches.
Sous X, souvent le DE permet de définir une touche Compose. Une fois que vous avez fait vos modifications systèmes, il est nécessaire de redémarrer votre session !
Il existe plusieurs moyens de configurer la touche de composition :
la configuration des fichiers .XCompose , .Xmodmap et .xsession n’est utile que pour les sessions terminales, en mode console, voire les environnements graphiques différents des bureaux graphiques.
Menu “Préférences” > option “Position de la touche compose”
Menu “Paramètres” (Alt+F2) > “Régions et langues”, puis choisir l’option “Avancé” dans “Disposition du clavier”. Puis parmi les options Xkb, cherchez “position de la touche compose”.
Depuis Xfce 4.14, le sélecteur est renommé : “Touche de composition”.
C’est dans “Paramètres” > “Clavier” : onglet “Disposition”, puis définir le sélecteur “Touche composée”.
Le fichier ~/.XCompose
sert à définir vos combinaisons de touche
personnalisées.
Pour exemple :
<Multi_key> <at> <v> : "✓" U2713 # CHECK MARK
<Multi_key> <at> <at> <v> : "✔" U2714 # HEAVY CHECK MARK
<Multi_key> <at> <X> : "✗" U2717 # BALLOT X
<Multi_key> <at> <at> <X> : "✘" U2718 # HEAVY BALLOT X
<Multi_key> <Multi_key> <t> <e> <l> : "☎" U260E # BLACK TELEPHONE
Dans cet exemple, la touche <Multi_key>
est votre touche de
composition ; la touche <at>
correspond à la touche @ et
les autres correspondent à vos lettres que vous retrouvez sur votre
clavier.
Pour la gestion de cette fonction, en mode terminal ou dans une console,
il faut créer le fichier ~/.Xmodmap
et définir dedans :
# key Compose : Touche Window
keycode 115 = Multi_key
Ajouter à votre fichier ~/.xsession
:
# Gestion des touches clavier
xmodmap $HOME/.Xmodmap
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Cet article est la traduction de l’article anglais "What happens when…" d’Alex Gaynor. De même que l’article original est sous licence CC0, ainsi est la traduction de cet article.
Ce dépôt est une tentative pour répondre à cette vieille question d’interview “Que se passe-t-il quand vous écrivez google.com dans la barre d’adresse de votre navigateur web et que vous appuyez sur la touche Entrée ?”
Hormis l’habituel histoire, nous allons essayer de répondre à cette question avec autant de détails que possible. Rien ne sera négligé.
Ceci est un processus collaboratif, alors svp creusez et essayez d’aider ! Il y a des tonnes de détails manquants qui n’attendent que vous pour les ajouter ! SVP, envoyez-nous vos requêtes !
Tout ceci est sous les termes de la licence Creative Commons Zero
Vous pouvez lire ceci en 简体中文 (Chinois simplifié), 日本語 (Japonais) et 한국어 (Coréen). NOTE : ces traductions n’ont pas été examinées par les responsables de alex/what-happens-when.
La section suivante explique les actions physiques du clavier et les interruptions du système d’exploitation. Lorsque vous appuyez sur la touche g, le navigateur reçoit l’événement et les fonctions d’autocomplétion s’enclenchent.
Selon l’algorithme de votre navigateur et si vous êtes en mode privé, ou non, diverses suggestions vous seront présentées dans un menu déroulant sous la barre d’URL . La plupart des algorithmes trient et priorisent les résultats selon la recherche historique, les marques-pages, les cookies, et les recherches populaires sur Internet.
Lorsque vous écrivez google.com, de nombreux blocs de code s’exécutent et les suggestions seront affinées à chaque appui sur une touche. Il peut même vous suggérer “google.com” avant que vous ayez fini de l’écrire.
Pour commencer, choisissons l’appui sur le bas de la touche Entrée.
À ce moment, un circuit électrique spécifique à la touche est verrouillée (soit directement, soit de manière capacitive). Ceci permet à une petite quantité de courant de circuler dans le circuit logique du clavier, qui analyse l’état de l’interrupteur de chaque touche, élimine le bruit électrique de la fermeture intermittente rapide de l’interrupteur et le convertit en un entier de code de touche, en l’occurrence 13.
Le contrôleur du clavier encode alors le code de touche pour le transport vers l’ordinateur. Actuellement, c’est presque universellement au-travers d’une connexion USB ou par Bluetooth, mais historiquement c’était des connexions de type PS /2 ou ADB .
Dans le cas d’un clavier USB :
Le circuit USB du clavier est alimenté par l’alimentation 5V fournit sur la broche 1 du contrôleur USB de l’ordinateur.
Le code de touche généré est enregistré par la mémoire du circuit interne du clavier dans un registre appelé “endpoint”.
Le contrôleur USB analyse ce registre “endpoint” environ toutes les 10 millisecondes (valeur minimum déclarée par le clavier), ainsi il enregistre la valeur du code de touche.
Cette valeur parvient au moteur d’interface série USB SIE afin d’être converti dans un ou plusieurs paquets USB selon le protocole USB de bas niveau.
Ces paquets sont envoyés par un signal électrique différentiel sur les connecteurs D+ et D- (entre 2) à la vitesse maximale de 1.5 Mo/s , puisqu’un dispositif IHM est toujours déclaré en tant que “dispositif à faible vitesse” (en conformité avec la norme USB 2.0).
Ce signal en série est alors décodé par le contrôleur USB de l’ordinateur, puis interprété par le pilote du dispositif universel de clavier IHM de l’ordinateur. La valeur de la touche est passée au-travers de la couche d’abstraction matérielle du système d’exploitation.
Dans le cas d’un clavier virtuel (de même pour les écrans tactiles) :
Quand l’utilisateur pose son doigt sur un écran tactile capacitif moderne, une quantité infime de courant est transmise au doigt. Cela complète le circuit par le champ électrostatique de la couche conductrice et crée une chute de tension à cet endroit de l’écran. Le contrôleur de l’écran lève une interruption rapportant les coordonnées de la touche pressée.
Alors le système d’exploitation mobile notifie à l’application en cours de l’événement de pression d’un des éléments de son interface (qui sont les boutons de l’interface virtuelle de l’application de clavier).
Le clavier virtuel peut maintenant lever une interruption logicielle afin d’envoyer un message de ’touche pressée’ au système d’exploitation.
Cette interruption notifie l’application en cours d’un événement de ’touche pressée'.
Le clavier envoie des signaux sur sa ligne de requêtes d’interruption (IRQ
),
qui correspond à un entier interrupt vector
du contrôleur d’interruption.
Le processeur (UCT
) utilise
la table de descripteurs d’interruptions (IDT
)
qui correspond aux vecteurs d’interruptions vers les fonctions (interrupt handlers
)
qui sont fournis par le noyau. Lorsqu’une interruption arrive, l’UCT indexe
l’IDT avec le vecteur d’interruptions et exécute le gestionnaire approprié.
Ainsi, le noyau est introduit.
WM_KEYDOWN
est envoyé à l’applicationLe transport IHM envoie l’événement de touche pressée au pilote KBDHID.sys
qui convertit l’utilisation de l’IHM vers un code d’analyse.
Dans ce cas, le code d’analyse est VK_RETURN
(0x0D
).
Le pilote KBDHID.sys
s’interface avec KBDCLASS.sys
(un pilote de classe clavier).
Ce pilote est responsable de toutes les entrées de clavier et clavier numérique de
manière sécurisée. Il les appelle ensuite dans Win32K.sys
(après avoir
passer le message dans les filtres de clavier tiers installés).
C’est tout ce qui se passe dans le noyau.
Win32K.sys
détermine quelle fenêtre est active au-travers de l’API
GetForegroundWindow()
. Cette API fournit la capture de la fenêtre à
la boite d’adresse du navigateur.
La fenêtre principale “message pump” appelle alors SendMessage(hWnd, WM_KEYDOWN, VK_RETURN, lParam)
.
lParam
est un masque binaire qui indique des informations complémentaires
à la pression de touche : compteur de répétition (0
dans ce cas), le code d’analyse actuel
(peut être dépendant du fabriquant, mais ne l’est pas généralement pour VK_RETURN
),
quelque soit la touche étendue (e.g. alt, shift, ctrl) qui soit aussi
appuyée (elles ne l’étaient pas), ou dans un autre état.
L’API Windows SendMessage
est une fonction simple qui ajoute le message
à une queue d’un gestionnaire de fenêtres particulier (hWnd
). Plus tard,
la fonction principale de traitement des messages (appelée WindowProc
)
assignée à hWnd
est appelée afin de traiter chaque message dans la queue.
La fenêtre (hWnd
) qui est active est en fait un contrôleur d’édition,
et le WindowProc
dans ce cas est un gestionnaire de messages pour WM_KEYDOWN
.
Ce code cherche un paramètre tiers qui est passé à SendMessage
(wParam
),
parce que VK_RETURN
sait qu’un utilisateur a appuyé sur la touche Entrée.
KeyDown
est envoyé à l’applicationLe signal d’interruption déclenche un événement d’interruption dans le pilote
du Kit d’Entrée/Sortie (I/O) kext du clavier. Le pilote traduit le signal
dans un code de touche qui est passée au process d’OS X WindowServer
.
Pour résultat, le WindowServer
envoie un événement à toute application
appropriée (e.g. active ou écoutant) au-travers du port Mach qui est placé
dans la queue d’événements. Les événements peuvent alors être lus depuis
cette queue par des “fils” (appelés threads) disposant des privilèges
suffisants appelant la fonction mach_ipc_dispatch
.
Cela arrive généralement au-travers d’une boucle de gestion principale NSApplication
le gérant, via un événement NSEvent
d’un type d’événement NSEventType
KeyDown
.
Lorsqu’un serveur graphique X server
est utilisé, X
utilisera
le pilote d’événement générique evdev
afin d’acquérir l’événement de
pression de touche. La conversion des codes de touches en codes d’analyse
est faite à l’aide de règles et de keymaps (“cartes de claviers”) spécifiques
à X server
.
Lorsque la correspondance du code d’analyse à une touche pressée est complète,
le X server
envoie le caractère au gestionnaire de fenêtres window manager
(DWM, metacity, i3, etc), afin que le window manager
à son tour envoie
le caractère à la fenêtre en cours.
L’API graphique de la fenêtre qui reçoit le caractère affiche le symbole de police approprié dans le champ approprié ayant le focus.
Quand aucun protocole ou nom de domaine valide n’est donné, le navigateur s’occupe de récupérer le texte donné dans la boite d’adresse au moteur de recherche web par défaut du navigateur.
Dans beaucoup de cas, un texte spécial est ajouté à l’URL pour indiquer au moteur de recherche qu’il provient de la barre d’URL d’un navigateur particulier.
Le navigateur vérifie tous les caractères du nom d’hôte, qui ne soient pas
a-z
, A-Z
, 0-9
, -
, ou .
.
Puisque le nom d’hôte est google.com
, il n’y en aura pas ; mais si
c’était le cas, le navigateur appliquerait l’encodage Punycode à la
portion du nom d’hôte dans l’URL.
Le navigateur vérifie sa liste de “HSTS préchargés”. C’est une liste de sites web qui ont requis de n’être contactés seulement que sur HTTPS .
Si le site web est dans la liste, le navigateur envoie sa requête via
HTTPS plutôt qu’en HTTP. Autrement, la requête initiale est envoyée en HTTP.
(Notez qu’un site web peut toujours utiliser une politique HSTS sans
être dans la liste HSTS. La première requête HTTP au site web faite par
un utilisateur recevra une réponse demandant que l’utilisateur envoie
seulement des requêtes HTTPS. Toutefois, cette unique requête HTTP
pourrait potentiellement laisser l’utilisateur vulnérable à une attaque dite
downgrade attack
; c’est la raison pour laquelle la liste HSTS est
incluse dans les navigateurs web modernes).
Le navigateur vérifie si le domaine est dans son cache. (Pour voir le
cache DNS dans Chrome, écrivez dans la barre d’adresse
chrome://net-internals/#dns
).
S’il n’est pas trouvé, le navigateur appelle la fonction de bibliothèque
gethostbyname
(qui varie selon l’OS) afin de faire la recherche.
gethostbyname
vérifie si le nom d’hôte peut être résolu par référence
dans le fichier local hosts
(dont la localisation varie selon l’OS)
avant d’essayer de résoudre le nom d’hôte au-travers DNS
.
Si gethostbyname
ne le trouve pas dans le cache, ni dans le fichier hosts
alors elle fait une requête vers le serveur DNS configuré dans la pile
réseau. C’est typiquement le routeur local ou le serveur DNS cache du
FAI
.
Si le serveur DNS est sur le même sous-réseau, la bibliothèque réseau
suit le processus ARP
décrit ci-dessous pour le serveur DNS.
Si le serveur DNS est sur un sous-réseau différent, la bibliothèque réseau
suit le processus ARP
décrit ci-dessous pour l’adresse IP de la
passerelle par défaut.
Avant d’envoyer une diffusion ARP , la bibliothèque de la pile réseau a besoin de l’adresse IP cible à rechercher. Elle doit aussi connaître l’adresse MAC de l’interface qu’elle utilisera pour envoyer la diffusion ARP.
Le cache ARP est vérifié en premier pour trouver une entrée ARP de notre IP cible. Si elle est dans le cache, la bibliothèque retourne le résultat : IP cible = MAC.
Si l’entrée n’est pas dans le cache ARP :
La table de routage est recherchée, pour voir si l’adresse IP ciblée est dans le sous-réseau de la table de routage local. Si elle y est, la bibliothèque utilise l’interface associée au sous-réseau. Si elle n’y est pas, la bibliothèque utilise l’interface qui est dans le sous-réseau de notre passerelle par défaut.
L’adresse MAC de l’interface réseau sélectionnée est recherchée.
La bibliothèque réseau envoie une requête ARP de la Couche de Liaison 2 (trame de liaison d’adressage physique du modèle OSI) :
interface:mac:address:here
interface.ip.goes.here
FF:FF:FF:FF:FF:FF
(Broadcast)target.ip.goes.here
Cela dépend du type de matériel qui est entre l’ordinateur et le routeur :
⇒ Directement connecté :
⇒ Par un Hub :
⇒ Par un commutateur :
Si l’ordinateur est connecté à un commutateur, le commutateur vérifiera sa table MAC pour savoir sur quel port est diffusé l’adresse MAC recherchée. Si le commutateur n’a pas d’entrée pour l’adresse MAC, il rediffusera la requête ARP vers tous les autres ports.
Si le commutateur a une entrée dans la table MAC, il enverra une requête ARP au port correspondant à l’adresse MAC recherchée.
Si le routeur est sur la même “interface”, il répondra avec une “réponse ARP ” (lire ci-dessous)
target:mac:address:here
target.ip.goes.here
interface:mac:address:here
interface.ip.goes.here
Le protocole ARP est nécessaire au fonctionnement d’IPv4, utilisé par dessus un réseau de type Ethernet. En IPv6, les fonctions ARP ont été reprises dans le processus de découverte NDP
Maintenant que la bibliothèque réseau a l’adresse IP, soit de notre serveur DNS, soit de la passerelle par défaut, elle peut reprendre son processus DNS :
Une fois que le navigateur reçoit l’adresse IP du serveur de destination,
il la prend ainsi que le numéro de port donné dans l’URL (par défaut, le
protocole HTTP a le port 80, et HTTPS le port 443), puis fait un appel à
la fonction de la bibliothèque système nommée socket
et requiert un
flux de socket TCP - AF_INET/AF_INET6
et SOCK_STREAM
.
Cette requête est en premier passé à la Couche de Transport où un segment
TCP est créé. Le port de destination est ajouté à l’entête, et le port
source est choisi parmi une plage de port dynamique du noyau
(ip_local_port_range
dans Linux).
Ce segment est envoyé vers la Couche Réseau, qui enveloppe une entête IP additionnelle. L’adresse IP du serveur cible aussi bien que celle de la machine courante est insérée pour former un paquet.
Le paquet suivant arrive sur la Couche de Liaison. Une entête de trame est ajouté qui inclut l’adresse MAC de l’interface réseau de la machine ainsi que l’adresse MAC de la passerelle (le routeur local). Tout comme avant, si le noyau ne connaît pas l’adresse MAC de la passerelle, il doit diffuser une requête ARP pour la trouver.
À partir de ce point, le paquet est prêt à être transmis, soit au-travers :
Pour la plupart des connexions à Internet depuis une maison, ou pour de petites entreprises, le paquet passera de votre ordinateur, possiblement au-travers du réseau local, puis vers un modem qui convertit les 0 et 1 numériques en signal analogique adapté à la transmission par téléphone, câble ou connexions de téléphonie sans fil.
À l’autre extrémité de la connexion se trouve un autre modem qui reconvertit le signal analogique en données numériques qui seront traitées par le prochain nœud de réseau où les adresses de départ et d’arrivée seront analysées plus en détail.
La plupart des grandes entreprises et certaines connexions résidentielles plus récentes disposeront de connexions en fibre optique ou de connexions Ethernet directes, auxquels cas les données restent numériques et sont transmises directement au prochain nœud de réseau pour y être traitées.
Éventuellement, le paquet atteindra le routeur gérant le sous-réseau local. Depuis là, il continuera à voyager vers l’AS au-delà du routeur, vers d’autres AS, et finalement atteindra le serveur de destination.
Chaque routeur, le long du chemin, extrait l’adresse de destination de l’entête d’IP et la dirige vers le prochain saut approprié.
Le champ TTL dans l’entête de l’IP est décrémenté de un à chaque routeur traversé. Le paquet sera supprimé si le champ TTL atteint zéro ou si le routeur en cours n’a plus d’espace dans sa queue (cela peut être dû à une congestion du réseau).
Cet envoi et cette réception arrive de nombreuses fois suivant le flux de connexion TCP :
L’ordinateur client envoie un message ClientHello
au serveur avec sa
version de TLS
, une liste
d’algorithmes de chiffrement et de méthodes de compression disponibles.
Le serveur répond avec un message ServerHello
au client avec la version
TLS, le chiffrement choisi, les méthodes de compression sélectionnées et
le certificat public signé par une AC
du serveur.
Le certificat contient une clé publique qui sera utilisée par le client
pour chiffrer le reste de la poignée de main jusqu’à ce qu’une clé symétrique
puisse être convenue.
Le client vérifie que le certificat numérique du serveur soit dans sa liste d’AC de confiance. Si la confiance peut être établie, basée sur l’AC, le client génère une chaîne d’octets pseudo-aléatoires et la chiffre avec la clé publique du serveur. Ces octets aléatoires peuvent être utilisés pour déterminer la clé symétrique.
Le serveur déchiffre les octets aléatoires en utilisant sa clé privée puis utilise ces octets pour générer sa propre copie de la clé symétrique maître.
Le client envoie un message Finished
au serveur, chiffrant un hash
de la transmission jusqu’à ce point avec la clé symétrique.
Le serveur génère son propre hash, puis déchiffre le hash envoyé par le
client pour vérifier la correspondance. Si elle existe, il envoie son
propre message Finished
au client, le chiffrant aussi avec sa clé
symétrique.
À partir de maintenant la session TLS transmet les données de l’application (HTTP) chiffrées avec la clé symétrique agréée.
Si le navigateur web utilisé été écrit par Google, au lieu d’envoyer une requête HTTP pour récupérer la page, il enverra une requête pour négocier avec le serveur une “mise à jour” du protocole HTTP vers le protocole SPDY .
Si le client utilise le protocole HTTP mais ne prend pas en charge SPDY, il envoie une requête au serveur de la forme :
où [autres entêtes]
référent à une série de paire de clé et valeur séparée
par le symbole deux points ‘:’, formatées selon la spécification HTTP et
séparées par d’uniques nouvelles lignes.
(Cela suppose que le navigateur web utilisé n’ait pas de bogues violant la
spécification HTTP. Cela suppose aussi que le navigateur web utilise HTTP/1.1
,
autrement il ne pourrait pas inclure l’entête Host
dans la requête ;
la version spécifiée dans la requête GET
serait soit HTTP/1.0
ou HTTP/0.9
.)
HTTP/1.1 définit l’option de “fermeture” de la connexion pour que l’expéditeur signale que la connexion sera fermée après l’achèvement de la réponse. Par exemple :
Connection: close
Les applications HTTP/1.1 qui ne prennent pas en charge les connexions persistantes DOIVENT inclure l’option de “fermeture” de connexion dans chaque message.
Après l’envoi de la requête et des entêtes, le navigateur web envoie une unique nouvelle ligne vierge pour indiquer au serveur que le contenu de la requête est fait.
Le serveur répond avec un code de réponse dénotant le statut de la requête et avec une réponse de la forme :
Suivies d’une unique nouvelle ligne, il envoie alors la charge du contenu
HTML de www.google.com
. Le serveur peut alors soit fermer la connexion,
soit si les entêtes envoyées par le client le demande, garder la connexion
ouverte afin d’être réutilisées pour de prochaines requêtes.
Si les entêtes HTTP envoyées par le navigateur web comportent des informations
suffisantes pour que le serveur web détermine si la version du fichier en
cache dans le navigateur web n’a pas été modifié depuis la dernière récupération
(tel que si le navigateur web inclut une entête ETag
), il peut alors
répondre par une requête de la forme :
il n’y aura pas charge utile, et le navigateur web récupérera le HTML depuis son cache.
Après l’analyse du HTML, le navigateur web (ainsi que le serveur) répétera
ce processus pour chaque ressource (image, CSS, favicon.ico, etc) référencée
dans la page HTML, excepté que la requête sera GET /$(URL relative à www.google.com) HTTP/1.1
au lieu de GET / HTTP/1.1
.
Si le HTML référence une ressource sur un domaine différent que www.google.com
,
le navigateur web reprendra les étapes invoquées pour résoudre l’autre domaine,
et suivra toutes les mêmes étapes jusqu’à ce point pour ce domaine.
L’entête Host
dans la requête sera paramétrée vers le nom du serveur
approprié plutôt que google.com
.
Le serveur HTTPD (Service HTTP) est un gestionnaire de requêtes et de réponses côté serveur. Les serveurs HTTPD des plus communs sont Apache ou nginx pour Linux et IIS pour Windows.
GET
, HEAD
, POST
, PUT
,
PATCH
, DELETE
, CONNECT
, OPTIONS
, ou TRACE
). Dans
le cas où l’URL est entrée directement dans la barre d’adresse, elle
sera GET
.Une fois que le serveur délivre les ressources (HTML, CSS, JS, images, etc) au navigateur, il est soumis au processus suivant :
La fonction du navigateur est de présenter la ressource web que vous avez choisi, en la demandant à un serveur et en l’affichant dans la fenêtre du navigateur. La ressource est habituellement un document HTML, mais peut être aussi un PDF, une image, ou tout autre type de contenu. L’endroit de la ressource est spécifié par l’utilisateur selon une URI .
La manière dont le navigateur interprète et affiche les fichiers HTML est spécifiée dans les spécifications HTML et CSS. Ces spécifications sont maintenues par le W3C , qui est l’organisation des standards du web.
Les interfaces utilisateur de navigation ont beaucoup en commun entre elles. Parmi les éléments communs de l’interface utilisateur, on peut citer :
Structure de Haut Niveau du Navigateur
Les composants des navigateurs sont :
Le moteur de rendu démarre l’obtention des contenus du document demandé depuis la couche réseau. Cela se fait habituellement par morceaux de 8 Ko.
Le premier travail de l’analyseur HTML est d’analyser le langage HTML dans une arborescence.
La sortie de l’arborescence (“l’arborescence analysée”) est une arborescence des éléments du DOM et des nœuds d’attributs. DOM est l’abréviation de Document Object Model. C’est la présentation objet du document HTML et l’interface des éléments HTML au monde extérieur tel JavaScript. La racine de l’arborescence est l’objet “Document”.
Avant toute manipulation par script, le DOM a une relation quasi-univoque avec le balisage.
Algorithme d’Analyse
Le HTML ne peut être analysé par des analyseurs habituels.
Les raisons sont :
document.write()
)
peut ajouter des jetons supplémentaires ; le processus d’analyse en cours
modifie alors l’entrée.Si le navigateur est incapable d’utiliser les techniques d’analyses régulières, il utilisera un analyseur personnalisé pour l’analyse HTML. L’algorithme d’analyse est décrit en détail par la spécification HTML5.
L’algorithme consiste en deux phases : mise en jeton et construction de l’arborescence.
Les Actions lorsque l’Analyse est terminée
Le navigateur commence par récupérer les ressources externes liées à la page (CSS, images, fichiers JavaScript, etc).
Lors de cette étape, le navigateur marque le document comme interactif et démarre les scripts d’analyse qui sont dans le mode “différé” : tout ce qui doit être exécuté après le document est analysé. L’état du document est paramétré sur “complet” et un événement “charge” est levé.
Notez qu’il n’y a jamais d’erreur “Invalid Syntax” sur une page HTML. Les navigateurs corrigent tout contenu invalide et l’envoie.
Analyse des fichiers CSS, du contenu des balises <style>
, et des
valeurs des attributs style
en utilisant la “syntaxe de grammaire et champ lexical CSS”.
Chaque fichier CSS est analysé dans un StyleSheet object
, où chaque
objet contient les règles CSS avec les sélecteur et les objets correspondant
à la grammaire CSS.
Un analyseur CSS peut être descendant ou ascendant lorsqu’un générateur d’analyse spécifique est utilisé.
Crée une “Arborescence d’Image” ou une ‘Arborescence de Rendu" en traversant les nœuds du DOM, et en calculant les valeurs du style CSS pour chaque nœud.
Calcul la largeur préférée de chaque nœud de l’arbre du cadre de bas en haut en additionnant la largeur préférée des nœuds enfants et les marges horizontales, les bordures et le padding du nœud.
Calcul la largeur actuelle de chaque nœud de haut en bas en allouant à chaque nœud disponible la largeur de ses enfants.
Calcul la hauteur de chaque nœud de bas en haut en appliquant un habillage de texte et en additionnant les hauteurs des nœuds enfants, les marges, les bordures et le padding du nœud.
Calcul les coordonnées de chaque nœud en utilisant l’information calculée ci-dessus.
Des étapes plus compliquées sont menées lorsque les éléments sont positionnés
en floated
, absolutely
ou relatively
, ou lorsque d’autres
fonctionnalités plus complexes sont utilisées. Pour avoir plus de détails, voir
http://dev.w3.org/csswg/css2/ et http://www.w3.org/Style/CSS/current-work
Crée des calques pour décrire quelles parties de la page peuvent être animées en tant que groupe sans être re-traitées. Chaque objet d’image ou de rendu peut être assigné à un calque.
Des textures sont allouées à chaque calque de la page.
Les objets d’image ou de rendu pour chaque calque sont parcourus et des commandes de dessein sont exécutées pour leur calque respectif. Ils doivent être traités par le CPU ou dessinés par le GPU en utilisant directement D2D/SkiaGL.
Toutes les étapes ci-dessus peuvent réutilisées les valeurs calculées depuis la dernière fois où la page web a été rendue, ainsi les changements incrémentaux demandent moins de travail.
Les calques de page sont envoyés au processus de composition où ils sont combinés avec les calques d’autres contenus visibles, tel que le chrome du navigateur, les iframes, et les panneaux d’extension.
Les positions de calque final sont calculés et les commandes de composition sont émises via Direct3D/OpenGL. Les tampons de commande du GPU sont vidés vers le GPU pour le rendu asynchrone et l’image est envoyée au serveur de fenêtrage.
Durant le processus de rendu, les calques de calcul graphique peuvent
utilisés aussi bien le CPU
que le processeur graphique GPU
.
Lors de l’utilisation du GPU
pour le calcul du rendu graphique, les
calques du logiciel graphique découpe la tâche en de multiples pièces,
ainsi il peut utiliser avantageusement le parallélisme massif du GPU
pour le calcul de virgule flottante requis pour le processus de rendu.
Après que le rendu soit complet, le navigateur exécute le code JavaScript grâce à un mécanisme de temporisation (tel qu’une animation Google Doodle) ou à une interaction de l’utilisateur (écrivant une requête dans une boîte de recherche et recevant des suggestions).
Des plugins tels que Flash ou Java peuvent aussi être exécutés, mais actuellement pas depuis la page d’accueil de Google. Des scripts peuvent causer des requêtes réseaux additionnelles, modifier la page ou sa mise en page, entraînant un nouveau cycle de rendu et de dessin de la page.
Les sources “officielles” de la traduction de cet article sont disponibles sur mon espace de dépôt GitHub. Si vous voyez des erreurs de traduction, de sens, si en tant qu’experts/utilisateurs confirmés, vous souhaitez apporter des précisions/corrections, n’hésitez pas à lever une issue, voire mieux à fournir une PR ;-)
OpenWRT a un outil pour faire la mise à niveau d’une version à une autre nommé sysupgrade. Il est possible de l’invoquer depuis l’interface web d’administration LuCI.
Si le procédé vous intéresse plus que le faire par CLI, lisez la note en question : Flash depuis LuCI
Le procédé suivant explique pas-à-pas la mise à niveau tout en mode CLI, tout en préservant la configuration utilisateur…
La première chose à laquelle nous veillons est d’installer l’outil curl
,
car par défaut le binaire wget
nativement installé ne supporte pas TLS.
# opkg install curl
Le script opkgscript.sh
permet de sauvegarder la liste des paquets
installés en sus de la base.
⇒ Récupèrons le depuis opkgscript.sh :
$ curl -O https://raw.githubusercontent.com/richb-hanover/OpenWrtScripts/master/opkgscript.sh
⇒ Donnons les droits d’exécution nécessaire :
# chmod 0700 opkgscript.sh
⇒ Sauvegardons la liste des paquets installés - pour pouvoir restaurer après la mise à niveau système :
# ./opkgscript.sh -v write
Le script écrit la liste dans un fichier /etc/config/opkg.installed
.
Depuis le répertoire /tmp
, récupèrons la nouvelle version du firmware :
# v="23.05.3"
⇒ pour le routeur Ubiquiti EdgeRouter X :
# curl -O https://downloads.openwrt.org/releases/"${v}"/targets/ramips/mt7621/{openwrt-"${v}"-ramips-mt7621-ubnt-erx-squashfs-sysupgrade.bin,sha256sums}
⇒ pour le Xiaomi Redmi Router AC2100 :
# curl -O https://downloads.openwrt.org/releases/"${v}"/targets/ramips/mt7621/{openwrt-"${v}"-ramips-mt7621-xiaomi_redmi-router-ac2100-squashfs-sysupgrade.bin,sha256sums}
Puis, nous vérifions la somme de contrôle afin de nous assurer du firmware :
$ sha256sum -c sha256sums 2> /dev/null | grep OK
⇒ Résultat correct pour le routeur Xiaomi Redmi Router AC2100 :
openwrt-23.05.2-ramips-mt7621-xiaomi_redmi-router-ac2100-squashfs-sysupgrade.bin: OK
ATTENTION : Si la vérification échoue, allez en discuter sur le forum !
Ne cherchez pas à mettre à jour avec un micro-logiciel corrompu !!!
L’étape suivante est de vérifier la configuration de la sauvegarde :
# sysupgrade -l
Si nécessaire, il faut éditer le fichier pour ajouter certains répertoires/fichiers,
ainsi dans le cas où un utilisateur a été ajouté correctement au groupe `sudo`
,
il faudra ajouter ce qui suit dans le fichier /etc/sysupgrade.conf
:
Vérifions à nouveau - et sauvegardons la configuration :
# sysupgrade -b /tmp/backup-${HOSTNAME}-$(date +%F).tar.gz
/etc/config/opkg.installed
précédemment créé avec
le script opkgscript.sh
.Puis, il faut récupèrer cette sauvegarde :
$ scp root@openwrt:/tmp/backup*.tar.gz $(pwd)
(où ‘openwrt’ est l’adresse IP de votre routeur…)
Si vous avez le message d’erreur suivant :
ash: /usr/libexec/sftp-server: not found
Merci de lire la note suivante À-propos de SSH v9.0 et supérieure
La note À-propos de la libération de la mémoire peut-être intéressante à lire, mais peu utile dans le contexte des deux routeurs mis en exemple, tel que le Ubiquiti EdgeRouter X ou le Xiaomi Redmi Router AC2100 car dans leur cas est embarquée une RAM conséquente.
Passons à la mise à niveau système, tel que :
# sysupgrade -v openwrt-"${v}"-*-sysupgrade.bin
⇒ Exemple, pour le routeur Ubiquiti EdgeRouter X :
# sysupgrade -v openwrt-"${v}"-ramips-mt7621-ubnt-erx-squashfs-sysupgrade.bin`
(date) upgrade: Saving config files...
etc/config/dhcp
etc/config/dhcp-opkg
etc/config/dropbear
etc/config/firewall
etc/config/https-dns-proxy
etc/config/https-dns-proxy-opkg
etc/config/luci
etc/config/luci-opkg
etc/config/network
etc/config/openssl
etc/config/opkg.installed
etc/config/rpcd
etc/config/system
etc/config/travelmate
etc/config/ubootenv
etc/config/ucitrack
etc/config/ucitrack-opkg
etc/config/uhttpd
etc/config/uhttpd-opkg
etc/config/unbound
etc/config/unbound-opkg
etc/config/wifi_schedule
etc/config/wifi_schedule-opkg
etc/config/wireless
etc/crontabs/root
etc/dropbear/authorized_keys
etc/dropbear/dropbear_ed25519_host_key
etc/dropbear/dropbear_rsa_host_key
etc/fw_env.config
etc/group
etc/hosts
etc/inittab
etc/luci-uploads/.placeholder
etc/nftables.d/10-custom-filter-chains.nft
etc/nftables.d/README
etc/opkg/keys/0b26f36ae0f4106d
etc/opkg/keys/1035ac73cc4e59e3
etc/opkg/keys/2f8b0b98e08306bf
etc/opkg/keys/4d017e6f1ed5d616
etc/opkg/keys/5151f69420c3f508
etc/opkg/keys/72a57f2191b211e0
etc/opkg/keys/792d9d9b39f180dc
etc/opkg/keys/9ef4694208102c43
etc/opkg/keys/b2d571e0880ff617
etc/opkg/keys/b5043e70f9a75cde
etc/opkg/keys/c10b9afab19ee428
etc/opkg/keys/dace9d4df16896bf
etc/opkg/keys/dd6de0d06bbd3d85
etc/opkg/keys/f94b9dd6febac963
etc/passwd
etc/profile
etc/rc.local
etc/shadow
etc/shells
etc/shinit
etc/sudoers
etc/sysctl.conf
etc/sysupgrade.conf
etc/unbound/unbound.conf
(date) upgrade: Commencing upgrade. Closing all shell sessions.
Normalement votre session SSH va se fermer et le routeur démarrer !
Lors de la reconnexion au routeur depuis votre client SSH, il peut
arriver que la connexion soit empêchée avec le message d’erreur suivant :
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED
.
Si c’est le cas, merci de lire la note adéquate :
À-propos de l’identification de l’hôte à distance par SSH
Si jamais vous faites une migration depuis 19.07.x vers 21.02.x ou supérieure, veuillez lire impérativement la note ad hoc : À-propos de la Migration vers ≥ 21.02.0
Après le reboot, il peut arriver que le routeur n’ait plus accès à Internet.
Merci de vérifier le fichier /etc/resolv.conf
et de le reconfigurer si
besoin.
À partir du moment où vous pourrez vous connecter à nouveau à votre routeur, vous retrouverez l’information relative à votre nouvelle version :
BusyBox v1.36.1 (2024-03-22 22:09:42 UTC) built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
OpenWrt 23.05.3, r23809-234f1a2efa
-----------------------------------------------------
À ce moment de l’étape, il est possible que vous ne puissiez plus
communiquer avec l’extérieur, car le fichier /etc/resolv.conf
est
toujours configuré pour la résolution de noms en interne, tel que :
# cat /etc/resolv.conf
search huc.home
nameserver 127.0.0.1
nameserver ::1
Dans ce cas, éditez le fichier pour ajouter un serveur DNS à interroger,
tel que ceux de la FDN : 80.67.169.12
et/ou 80.67.169.40
.
Par exemple :
# sed -i -e 's/127.0.0.1/80.67.169.12/' /etc/resolv.conf
Sur les routeurs ayant moins de 4 Mo de NVRAM, les mises à jour peuvent ne pas avoir lieu correctement ; il est nécessaire de s’assurer d’avoir au moins 600 Ko de libre.
Essayez de libérer de la mémoire …
Ce n’est pas le cas, ni du Ubiquiti EdgeRouter X, ni du Xiaomi Redmi AC2100; le premier en a 256 Mo, le second 128 Mo.
⇒ Effectuons la mise à niveau des paquets tiers :
# opkg update && opkg list-upgradable
Normalement suite à la mise à niveau, il ne devrait pas y en avoir.
S’il y en a, exécutez la commande suivante :
# for name in `opkg list-upgradable | awk '{print $1}'`; do opkg upgrade "${name}"; done
Pour restaurer le profil utilisateur, on répète les étapes d’installation
de l’outil curl, puis du script opkgscript.sh
.
Et une fois installé et les droits d’exécution attribués, on l’exécute pour qu’il complète l’installation du “profil utilisateur” :
# ./opkgscript.sh -v install
Pour finir, mieux vaut redémarrer !
Ensuite, vérifier la configuration de votre routeur :
Voilà…
Normalement, tout devrait fonctionner correctement en suivant ce processus de mise à niveau.
Retrouvez ci-dessous différentes notes d’informations utiles, seulement dans certains contextes.
Depuis le menu “System” > “Backup / Flash firmware” de l’interface web LuCI :
1/ Il est utile d’aller à l’onglet ‘Configuration’ pour modifier la liste des fichiers personnalisés à sauvegarder aussi… Si les fichiers et autres répertoires relatifs à l’installation de binaires tiers ne sont pas écrits ici, rien ne sera sauvegardé !
2/ Faites une sauvegarde de votre configuration d’OpenWRT depuis l’onglet ‘Actions’, section ‘Backup’.
3/ Lors du processus pour flasher une nouvelle image de mise à niveau :
⇒ Pensez à utiliser les options :
Si ces cases ne sont pas cochées, vous perdrez toute votre configuration lié à OpenWRT.
De même les binaires tiers seront dans tous les cas à réinstaller, voire à reconfigurer.
Gardez à l’esprit QUE des changements induits par les mises à niveau vers une version majeure peuvent poser des soucis lors de la migration. Il peut y avoir des changements critiques.
Si votre client SSH est de version ≥ 9.0 :
À partir de la version 9.0 de SSH, le comportement de scp
a changé.
Dans l’état, la commande ci-dessus échouera avec le message d’erreur suivant :
scp router:/tmp/backup-***-2022-04-21.tar.gz .
ash: /usr/libexec/sftp-server: not found
scp: Connection closed
Dans les faits, Dropbear ne peut plus discuter avec…
Ajoutez l’option -O
à la commande scp
, tel que :
$ scp -O root@openwrt:/tmp/backup*.tar.gz $(pwd)
(cela rétablit l’ancien comportement SFTP de scp)
Une autre astuce est d’installer le serveur OpenSSH en lieu et place de Dropbear .
Cette section est surtout utile si le système de fichier /tmp
n’est pas
assez grand pour enregistrer l’image d’OpenWRT. Les actions ci-dessous
vont permettre de libérer temporairement de l’espace dans la RAM.
Par acquis de conscience, assurons-nous de l’espace mémoire et disque
avec les commandes free
et df
, voire cat /proc/meminfo
; le but
est de vérifier que la taille de RAM libre est plus importante que la
taille de l’image téléchargée. Si c’est le cas, nous pouvons continuer
le processus, sinon, nous avons un sérieux problème et il faut en discuter
sur le forum d’OpenWRT.
Prenons un exemple pour mieux comprendre :
⇒ la taille du binaire d’upgrade de la version ci-dessus :
$ ll -h
(…)
-rw-rw-r-- 1 root root 6.7M Sep 10 13:53 openwrt-22.03.0-ramips-mt7621-xiaomi_redmi-router-ac2100-squashfs-sysupgrade.bin
(…)
elle est donc de 6.7 Mo.
⇒ L’espace disponible dans /tmp
:
# df -h
Filesystem Size Used Available Use% Mounted on
/dev/root 3.8M 3.8M 0 100% /rom
tmpfs 59.7M 540.0K 59.1M 1% /tmp
/dev/ubi0_1 97.2M 7.8M 84.7M 8% /overlay
overlayfs:/overlay 97.2M 7.8M 84.7M 8% /
tmpfs 512.0K 0 512.0K 0% /dev
Dans le contexte du Xiaomi Redmi AC2100, à ce jour, l’espace disponible est de 59.1 Mo, ce qui est largement suffisant pour récupèrer l’image de mise à niveau et la gérer.
⇒ De même, l’espace libérée de mémoire :
# free -m
total used free shared buff/cache available
Mem: 122220 40532 61400 540 20288 46700
Swap: 0 0 0
Dans ce contexte, l’espace libre en mémoire est de d’environ 60 Mo. Là, encore, il y a assez d’espace pour gérer l’image de mise à niveau.
Si ainsi, dans votre contexte, l’espace totale disponible, soit celle de
la mémoire plus celle en /tmp
n’est pas assez grande, il est possible
d’essayer ce qui suit - supprimer ce qui devient désormais inutile :
# rm -r /tmp/opkg-lists/
# sync && echo 3 > /proc/sys/vm/drop_caches
# rm /etc/modules.d/*{80211,ath9k,b43}*
/etc/modules.d
, si c’est le cas, détruisez-les, ce qui libérera de
la RAM au prochain démarrage, puis redémarrez absolument OpenWRT
avant de faire la mise à niveau.Lors de la nouvelle connexion par SSH, il est normalement possible que vous ayez le droit au message d’erreur suivant :
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:0atP7BnQQ98EVJciOCBDYAUD245lKm2tbau8BgWMpQ0.
Please contact your system administrator.
Add correct host key in /home/you/.ssh/known_hosts to get rid of this message.
Offending RSA key in /home/you/.ssh/known_hosts:93
remove with:
ssh-keygen -f "/home/you/.ssh/known_hosts" -R "192.168.xyz.1"
ED25519 host key for 192.168.xyz.1 has changed and you have requested strict checking.
Host key verification failed.
Ne paniquez pas, c’est normal ! Ayant changé de version de système d’exploitation, l’identification de l’hôte a changé aussi. Appliquez la commande ssh-keygen, telle que donnée, dans votre cas, pour supprimer l’ancienne identification d’hôte. Puis retentez votre connexion.
Après la mise à niveau, il est très probable que les machines derrière le routeur n’aient plus accès correctement à Internet. C’est une phase normale ; ne pas paniquer !
En effet, ne pas oublier que sysupgrade
supprime toute configuration utilisateur.
L’étape suivante va d’être de restaurer le “profil utilisateur”.
Vous avez choisi de migrer vers la version 21.02.0-*** depuis 19.07.***, c’est bien !
Mais avant de faire toute autre action, connectez-vous à l’interface web, puis sur le menu “Interfaces” ; il va vous être proposé de faire une migration de la configuration, faites-la !
Puis, redémarrez !
Comme vous pourrez le lire dans la documentation du wiki OpenWRT, il y a d’autres méthodes ; celle que je vous propose me semble la plus pertinente…
Retrouvez ci-dessous la traduction EN → FR de l’article “How to build a malware scan server”, écrit par Bruno Flückiger.
Date : 2020-05-16
Récemment, j’ai eu la tâche de construire, au travail, un serveur de scan de malware supportant ICAP. Actuellement, nous utilisons RedHat Enterprise Linux. Mais c-icap n’est pas disponible en tant que paquet dans un des dépôts de confiance, alors j’ai décidé d’utiliser OpenBSD pour cette tâche.
Le serveur de scan de malware utilise ClamAV en tant que scanner de malware et c-icap en tant que serveur ICAP, fournissant une interface pour chaque produit qui supporte ICAP tel Squid.
C’est une tâche très simple, un seul paquet s’occupe de tout :
$ doas pkg_add -i c-icap-clamav
Ce paquet contient le module c-icap pour ClamAV qui installe c-icap et clamav en dépendances.
Deux des trois démons installés par ClamAv sont d’intérêt : freshclam et clamd. En premier, configurez freshclam afin de vous assurer que la base de données des malware de ClamAV reste à jour.
Le fichier /etc/freshclam.conf
contient les paramètres suivants :
LogTime yes
LogSyslog yes
LogFacility LOG_DAEMON
DatabaseMirror db.ch.clamav.net
DatabaseMirror database.clamav.net
NotifyClamd /etc/clamd.conf
Maintenant, activez et démarrez freshclam afin qu’il mette à jour la signature de la base de donnée de ClamAV :
$ doas rcctl enable freshclam
$ doas rcctl start freshclam
Ensuite, configurez clamd. Dans le fichier /etc/clamd.conf
, les lignes
suivantes sont paramétrées :
LogTime yes
LogSyslog yes
LogFacility LOG_DAEMON
TemporaryDirectory /tmp
LocalSocket /var/clamav/clamd.sock
TCPSocket 3310
TCPAddr 127.0.0.1
User _clamav
DetectPUA yes
AlertEncrypted yes
AlertEncryptedArchive yes
AlertEncryptedDoc yes
AlertOLE2Macros yes
AlertPhishingSSLMismatch yes
AlertPhishingCloak yes
MaxRecursion 12
La dernière partie de configuration est à-propos de c-icap. Deux fichiers de configurations ont besoin de modifications avant de permettre à c-icap d’utiliser ClamAV en tant que scanner de malware.
Le premier est /etc/c-icap/c-icap.conf
. Ajoutez les lignes suivantes :
Include /etc/c-icap/clamd_mod.conf
Include /etc/c-icap/virus_scan.conf
Vous devriez changer les valeurs suivantes dans ce fichier de manière significative et différente :
ServerAdmin admin@example.org
ServerName scanner.example.org
TmpDir /tmp
Il y a un défaut dans le fichier de configuration à-propos de la
journalisation. L’option Logger
est paramétrée vers sys_logger
.
Mais le module sys_logger
requis est chargé seulement plus tard dans
le fichier de configuration. Si vous voulez utiliser sys_logger
, vous
devez charger le module avant de paramétrer l’option Logger
. Cela
empêchera c-icap de démarrer, bien que rcctl(8)
retournera ok. Soit vous changez l’option Logger
vers file_logger
soit vous déplacez les blocs dans le fichier de configuration pour
utiliser sys_logger
.
Dans le fichier /etc/c-icap/clamd_scan.conf
, faites les paramétrages
suivants :
clamd_mod.ClamdHost 127.0.0.1
clamd_mod.ClamdPort 3310
Puisque toute la configuration est faite, c’est maintenant le moment d’activer et de démarrer les services :
$ for s in clamd c_icap ; do
> rcctl enable $s
> rcctl start $s
> done
Soyez patient avec clamd. Il prend du temps à démarrer parce qu’il vérifie la base de données des signatures.
Tester votre démarrage est facile parce que c-icap est fourni avec un client ICAP pour cette tâche : c-icap-client. Appellez-le sans arguments effectuera un simple appel d’OPTIONS pour vérifier si le server fonctionne :
$ c-icap-client
ICAP server:localhost, ip:127.0.0.1, port:1344
OPTIONS:
Allow 204: Yes
Preview: 1024
Keep alive: Yes
ICAP HEADERS:
ICAP/1.0 200 OK
Methods: RESPMOD, REQMOD
Service: C-ICAP/0.5.6 server - Echo demo service
ISTag: CI0001-XXXXXXXXX
Transfer-Preview: *
Options-TTL: 3600
Date: Sat, 16 May 2020 10:02:03 GMT
Preview: 1024
Allow: 204
X-Include: X-Authenticated-User, X-Authenticated-Groups
Encapsulated: null-body=0
Avec l’aimable autorisation de Bruno Flückiger !
Cette page est la traduction de la page How to build a malware scan server du site BSDHowto.ch.
J’ai écrit historiquement cette traduction sur le wiki de la communauté “OpenBSD Pour Tous”.
help
en ligne de commande 8-)
Ce document a pour but de familiariser les nouveaux utilisateurs et administrateurs systèmes avec OpenBSD et, si nécessaire, avec UNIX en général.
En premier, une mine d’informations est contenue dans les pages de manuel système. Dans UNIX, la commande man(1) est utilisée pour les voir. Écrivez man man pour avoir les instructions à-propos de comment l’utiliser correctement. Prêtez une attention spéciale à l’option -k.
D’autres références à OpenBSD incluent la FAQ (Foire aux Questions) localisée à https://www.openbsd.org/faq/, qui est plus à l’attention des administrateurs et qui présume que le lecteur possède une certaine connaissance d’UNIX. Il y a aussi des listes de diffusion en place où des questions sont posées aux développeurs d’OpenBSD et à d’autres utilisateurs ; voir https://www.openbsd.org/mail.html.
Les administrateurs systèmes devraient toujours lire la page de manuel afterboot(8) qui explique une variété de tâches qui sont typiquement assumées après le premier démarrage du système. Durant la configuration du système, considérez en premier toutes implications de sécurité possibles qui peuvent résulter de vos changements.
Après être connecté, certains messages systèmes sont typiquement affichés, ensuite l’utilisateur est capable d’entrer des commandes à exécuter par le programme shell. Le shell est un interpréteur en ligne de commande qui lit les entrées utilisateur (normalement depuis un terminal) et exécute des commandes. Différents shells sont disponibles ; OpenBSD est fourni avec csh(1), ksh(1), et sh(1). Chaque shell utilisateur est indiqué dans le dernier champ correspondant à l’entrée dans le fichier système password (/etc/passwd).
man interface aux pages de manuel système. Concernant toutes les commandes listées ci-dessous, écrivez man command pour obtenir l’information détaillée sur ce qu’elle fait et comment l’utiliser.
pwd imprime le chemin en cours. Les fichiers sont organisés en hiérarchie (voir hier(7) appelée arborescence. Cette commande indiquera dans quel répertoire vous êtes actuellement localisé.
cd change le chemin de travail. Utilisez cette commande pour naviguer au-travers de la hiérarchie fichier. Par exemple, écrivez cd / pour changer de répertoire de travail vers root.
ls liste le contenu du répertoire. Écrivez ls -l pour une liste détaillée.
cat bien qu’il est plusieurs utilisations possibles, cat filename affichera le contenu d’un fichier texte à l’écran.
vi édite les fichiers textes. Par exemple, vi filename. Voir aussi mg(1).
mkdir crée un répertoire. Par exemple, mkdir dirname.
rmdir supprime un répertoire.
rm supprime des fichiers. Les fichiers sont généralement supprimés par leurs propriétaires. Voir la commande chmod(1) pour avoir les informations sur les permissions de fichier.
chmod change les modes de fichier, incluant les permissions. L’utilisation n’est pas immédiatement évidente ; veuillez lire sa page de manuel avec attention, à-propos des permissions de fichiers, spécifiquement sur les fichiers systèmes, qui sont vitaux pour maintenir la sécurité et l’intégrité.
cp copie des fichiers.
mv déplace et renomme des fichiers.
ps liste les processus actifs. La plupart des systèmes basés sur UNIX, incluant OpenBSD, sont multi-tâches, ce qui signifie que beaucoup de programment partagent les ressources systèmes en même temps. Un usage commun est ps -auxw, qui affichera les informations à-propos de tous les processus actifs.
kill tue les processus. Utilisé la plupart du temps pour arrêter des programmes ne s’exécutant pas normalement, mais aussi pour signaler des programmes demandant certaines opérations (e.g., relire leur configuration).
date affiche la date et l’heure système actuelle.
mail accède à la boite mail.
exit se déconnecte du système.
Quand une commande est entrée, il est vérifié en premier si elle est interne au shell. Si ce n’est pas le cas, le shell parcours tout répertoire contenu dans la variable d’environnement PATH (voir environ(7)). Si la commande n’est pas trouvée, un message d’erreur est affiché. Autrement, le shell exécute la commande, passant les arguments spécifiés dans la ligne de commande.
Les commandes internes au shell n’ont pas leur propre page de manuel, il est ainsi nécessaire de lire la page de manuel du shell utilisateur. Des outils tels que which(1) et “whence”, une commande interne à ksh(1), peuvent être utilisés pour voir les commandes en cours d’exécution.
Cette page de manuel a été écrite par Aaron Campbell aaron@openbsd.org et est apparue la première fois dans OpenBSD 2.6.
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
SSHGuard protège les hôtes des attaques par force brute. Il supporte IPv6, gère des listes blanches et journalise l’authentification ; il s’interface avec les plus grands systèmes pare-feu, a un analyseur de journaux remarquablement intelligent, et est indépendant, rapide et léger puisqu’écrit en C.
www : http://www.sshguard.net
Installez
le
paquet sshguard
.
man 7 sshguard-setup
less /usr/local/share/doc/[[#pkg-readme|pkg-readmes]]/sshguard
less /usr/local/share/examples/sshguard/sshguard.conf.sample
sshguard [-hv] [-a threshold] [-b threshold:blacklist_file] [-i pidfile] [-p blocktime] [-s detection_time] [-w address | whitelist_file] [file …]
sshguard protège les hôtes des attaques par force brute contre SSH et d’autres services. Il aggrége les journaux systèmes et bloque les récidives en utilisant un des nombreux backend pare-feu.
sshguard peut surveiller les fichiers des journaux ou lire les messages depuis l’entrée standard. Les messages sont analysés ligne par ligne selon des patterns reconnus. Une attaque est détectée lorsque plusieurs patterns correspondent dans une intervalle de temps définie. Les attaquants sont bloqués temporairement mais peuvent aussi être bannis de manière semi-permanente en utilisant l’option blacklist.
-a threshold (default 30) Bloque les attaquants lorsque leur score d’attaque cumulée excède un seuil. La plupart des attaques ont un score de 10.
-b threshold:blacklist_file Blackliste un attaquant lorsque son score excède le seuil. Les adresses blacklistées sont chargées et ajoutées dans un fichier de blackliste.
-i pidfile Écrit le PID de sshguard vers le fichier pidfile.
-p blocktime (default 120) Bloque les attaquants selon un temps de blocage en seconde après avoir atteint le seuil. Les blocages suivants sont incrémentés d’un facteur de 1.5. sshguard débloque les attaques à intervalles aléatoires, ainsi les temps de blocages actuels seront plus longs.
-s detection_time (default 1800) Se souvenir de potentiels attaquants durant un temp de détection en secondes avant de réinitialiser leur score.
[-w address | whitelist_file] Une liste blanche est une simple adresse, ou un bloc d’adresse. Cette option peut être utilisée plusieurs fois. Alternativement, il est possible de fournir un chemin absolu vers une fichier de liste blanche contenant des adresses. Voir la section Liste Blanche
-h affiche l’information d’utilisation puis sort.
-v affiche l’information de version puis sort.
/usr/local/share/examples/sshguard/sshguard.conf.sample
.Les adresses en liste blanche ne sont jamais bloquées. Les adresses peuvent être spécifiées depuis la ligne de commande ou être enregistrées dans un fichier.
En ligne de commande, écrivez l’option -w une ou plusieurs fois avec une adresse IP, un bloc d’adresses CIDR, ou un nom d’hôte en argument. Les noms d’hôtes sont résolus une fois lors du démarrage. Si un nom d’hôte résoud de multiples adresses, elles sont toutes mises en liste blanches.
Par exemple :
sshguard -w 192.168.1.10 -w 192.168.0.0/24 -w friend.example.com
-w 2001:0db8:85a3:0000:0000:8a2e:0370:7334
-w 2002:836b:4179::836b:0000/126
Si l’argument donné à -w commence avec un ‘/’ ou un ‘.’, l’argument est traité en tant que chemin vers une fichier de liste blanche.
Le fichier de liste blanche contient des commentaires (des lignes commençant avec ‘#’), des adresses, des blocs d’adresses, ou des noms d’hôtes, un par ligne.
2.3, 9 Janvier 2017, SSHGUARD(8)
Pour utiliser sshguard avec pf(4), ajouter quelque chose de similaire à
ce qui suit dans votre fichier /etc/pf.conf
:
table <sshguard> persist
block in quick on egress proto tcp from <sshguard> \
to any port ssh label "ssh bruteforce"
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Il y a quelques mois, j’ai écrit ce premier article pour obtenir un
moteur de recherche basique en s’aidant de la méthode autocomplete()
de
JQueryUI :
Hugo Search : un moteur de recherche interne (JQueryUI Autocomplete)
Et, puis je me suis rappelé que, parmi les flux de syndication, j’en génère
un au format JSON, le bien nommé feed.json, disponible à partir
de la page d’accueil. Je me suis demandé si je pouvais réutiliser mon
code, et je découvre que notre fameux SSG
Hugo a une fonction native getJSON
.
Reprenons le code…
Je construis une variable $feed
qui injectera la valeur du chemin absolu
de mon fichier feed.json.
{{- $baseURL := site.BaseURL | absLangURL -}}
{{- $feed := urls.JoinPath $baseURL "/feed.json" | absLangURL -}}
La partie du code JQuery est sensiblement la même, à la différence près
est que la fonction range
d’Hugo va directement appeler le contenu retourné
par la fonction getJSON
. La suite du traitement est faite par la méthode
autocomplete()
de JQuery, ni plus ni moins.
Voici le code :
{{- with resources.Get $feed -}}
<!-- Javascript -->
<script>
$(function() {
var projects = [
{{- range .items -}}
{
value: "{{ safeHTML .title }}",
label: "{{ safeHTML .summary }}",
url:"{{ safeURL .url }}"
},
{{- end -}}
];
$("#search").autocomplete({
minLength: 0,
source: projects,
focus: function( event, ui ) {
$("#search").val( ui.item.label );
return false;
},
select: function( event, ui ) {
$("#search").val( ui.item.label );
$("#replyer").val( ui.item.value );
return false;
}
})
.data('ui-autocomplete')._renderItem = function(ul, item) {
return $('<li>')
.append('<a href="' + item.url + '" alt="'+ item.label + '">' + item.value + '</a>' )
.appendTo(ul);
};
});
</script>
{{- end -}}
La partie de code HTML est toujours aussi simple :
<input class="form-control" id="search" placeholder="{{ T "searchHolderTitle" }}">
<input aria-hidden="true" id="replyer" class="hidden">
L’ensemble du code :
<div id="search">
<input class="form-control" id="search" placeholder="{{ T "searchHolderTitle" }}">
<input aria-hidden="true" id="replyer" class="hidden">
{{- $baseURL := site.BaseURL | absLangURL -}}
{{- $feed := urls.JoinPath $baseURL "/feed.json" | absLangURL -}}
{{- with resources.Get $feed -}}
<!-- Javascript -->
<script>
$(function() {
var projects = [
{{- range .items -}}
{
value: "{{ safeHTML .title }}",
label: "{{ safeHTML .summary }}",
url:"{{ safeURL .url }}"
},
{{- end -}}
];
$("#search").autocomplete({
minLength: 0,
source: projects,
focus: function( event, ui ) {
$("#search").val( ui.item.label );
return false;
},
select: function( event, ui ) {
$("#search").val( ui.item.label );
$("#replyer").val( ui.item.value );
return false;
}
})
.data('ui-autocomplete')._renderItem = function(ul, item) {
return $('<li>')
.append('<a href="' + item.url + '" alt="'+ item.label + '">' + item.value + '</a>' )
.appendTo(ul);
};
});
</script>
{{- end -}}
</div>
Voilà !
Q
: Lors de la génération en local, vous avez une
multitude d’erreur, telle que la suivante et le serveur s’arrête
tout seul :
ERROR 2020/08/27 08:16:41 Failed to get JSON resource “http://localhost:1313/fr/feed.json”: Get “http://localhost:1313/fr/feed.json”: dial tcp [::1]:1313: connect: connection refused
R : En environnement local, le serveur n’est pas capable d’appeler une donnée qui n’est pas encore générée.
getJSON
: Hugo Documentation : Templates > Data templates
- lien en anglaisautocomplete()
: https://jqueryui.com/autocomplete - lien en anglaisRetrouvez ci-dessous la traduction EN → FR de l’article “How to build a name server with DNS over TLS (DoT)”, écrit par Bruno Flückiger.
Date : 2020-08-25
Cet article est en rapport avec la configuration de nsd(8) en tant que serveur de noms public pour votre propre domaine, fournissant DNS-over-TLS (DOT). Tout ce qui faut pour cette tâche est inclus dans l’installation de base d’OpenBSD. Vous n’avez besoin d’installer aucun paquet additionnel pour cela.
Tout fournisseur de certificats qui supporte le protocole ACME peut être utilisé. Personnellement, j’utilise le plus populaire actuellement : Let’s Encrypt.
Les challenges reçus du fournisseur de certificats seront utilisés par
httpd(8) en configurant /etc/httpd.conf
,
similaire à ceci :
server "ns1.example.net" {
listen on egress port http
root "/"
location "/.well-known/acme-challenge/*" {
request strip 2
root "/acme"
}
}
types {
include "/usr/share/misc/mime.types"
}
Testez votre configuration, puis activez et démarrez httpd(8) :
$ doas httpd -n
$ doas rcctl enable httpd
$ doas rcctl start httpd
L’étape suivante est de configurer acme-client(1). Je vous suggère
d’utiliser /etc/examples/acme-client.conf
en tant que source à
sauvegarder puis à modifier conséquemment. Le fichier acme-client.conf
résultant devrait être sauvegardé dans /etc
et ressemblait à :
authority letsencrypt {
api url "https://acme-v02.api.letsencrypt.org/directory"
account key "/etc/acme/letsencrypt-privkey.pem"
}
authority letsencrypt-staging {
api url "https://acme-staging.api.letsencrypt.org/directory"
account key "/etc/acme/letsencrypt-staging-privkey.pem"
}
domain ns1.bsdhowto.ch {
domain key "/etc/ssl/acme/private/ns1.bsdhowto.ch.key"
domain certificate "/etc/ssl/acme/ns1.bsdhowto.ch.crt"
domain full chain certificate "/etc/ssl/acme/ns1.bsdhowto.ch.fullchain.pem"
sign with letsencrypt
}
Avant d’avoir votre certificat, vous devriez vous assurer que pf(4) laisse passer les requêtes vers httpd(8). Ajoutez une règle similaire à la suivante dans votre fichier pf.conf(5) :
pass in on egress proto tcp from any to egress port http
Vérifiez la configuration dans /etc/pf.conf
puis chargez-la dans pf(4)
en utilisant les commandes suivantes :
$ doas pfctl -nf /etc/pf.conf
$ doas pfctl -f /etc/pf.conf
Maintenant vous êtes prêt à récupérer le certificat pour nsd(8). N’oubliez pas de créer le fichier OCSP aussi :
$ dest=/etc/ssl/ns1.example.net
$ doas acme-client ns1.example.net
$ doas ocspcheck -No ${dest}.ocsp ${dest}.fullchain.pem
Vous devez vous assurer que le certificat soit valide, de même pour la
réponse OCSP, et qu’ils soient renouvelés avant leurs expirations. Je
vous suggère d’ajouter quelque chose comme ceci dans /etc/daily.local
:
#!/bin/sh
dest=/etc/ssl/ns1.example.net
acme-client ns1.example.net
if [ $? -eq 0 ] ; then
ocspcheck -No ${dest}.ocsp ${dest}.fullchain.pem
rcctl restart nsd
fi
oscpcheck -i ${dest}.ocsp ${dest}.fullchain.pem
if [ $? -eq 1 ] ; then
ocspcheck -No ${dest}.ocsp ${dest}.fullchain.pem
rcctl restart nsd
fi
Le script vérifie en premier le certificat. S’il a été renouvelé , il récupère la réponse OCSP pour le nouveau certificat et redémarre nsd(8) afin de charger les nouveaux fichiers. À la seconde étape, le script vérifie si la réponse OCSP a expirée. Si c’est le cas, il récupère une nouvelle réponse OCSP et redémarre nsd(8) afin de charger la nouvelle réponse OCSP.
La configuration correcte de nsd(8) dépend du rôle de votre serveur : primaire ou secondaire. La plupart des fournisseurs de domaines requièrent que vous exécutiez au moins deux serveurs de noms, de préférence dans deux différents sous-réseaux. Je vous montre la configuration des deux.
Voici la première pour le primaire :
server:
hide-identity: yes
hide-version: yes
ip-address: 192.0.2.11
ip-address: 192.0.2.11@853
ip-address: 2001:db8:1::c000:020b
ip-address: 2001:db8:1::c000:020b@853
server-count: 1
statistics: 86400
tls-service-key: "/etc/ssl/ns1.example.net.key"
tls-service-pem: "/etc/ssl/ns1.example.net.fullchain.pem"
tls-service-ocsp: "/etc/ssl/ns1.example.net.ocsp"
remote-control:
control-enable: yes
key:
name: nskey.example.net
algorithm: sha256
secret: "IAmASecretKeyForDomainTransfers"
zone:
name: "example.net"
zonefile: "/var/nsd/zones/master/%s.dns"
notify: 198.51.100.12 nskey.example.net
notify: 2001:db8:2::c633:640c nskey.example.net
provide-xfr: 198.51.100.12 nskey.example.net
provide-xfr: 2001:db8:2::c633:640c nskey.example.net
outgoing-interface: 192.0.2.11
outgoing-interface: 2001:db8:1::c000:020b
Assurez vous que le serveur primaire et le secondaire utilise la même clé secrète pour le transfert de domaines, autrement cela ne fonctionnera pas. Vous pouvez générer le secret pour la clé de transfert de domaine en utilisant la commande suivante :
$ for i in $(jot -r -s " " 32 0 255) ; do
> echo ${i} | awk '{ printf "%c", $1 }'
> done | sha256 -b
La prochaine étape est de s’assurer que le fichier de votre zone contient certaines données valides. Soit vous avez déjà un fichier de zone valide, soit vous pouvez utiliser celui qui suit en tant que point de départ :
$ORIGIN .
$TTL 3600 ; 1 hour
example.net IN SOA ns1.example.net. hostmaster.example.net. (
1 ; serial
10800 ; refresh (3 hours)
600 ; retry (10 minutes)
241900 ; expire (4 weeks)
3600 ; minimum (1 hour)
)
NS ns1.example.net.
NS ns2.example.net.
$ORIGIN example.net.
ns1 A 192.0.2.11
AAAA 2001:db8:1::c000:020b
ns2 A 198.51.100.12
AAAA 2001:db8:2::c633:640c
La configuration du second serveur a besoin d’autres options légèrement différentes pour en faire un serveur secondaire, mais elle ressemble à celle du serveur primaire :
server:
hide-identity: yes
hide-version: yes
ip-address: 198.51.100.12
ip-address: 198.51.100.12@853
ip-address: 2001:db8:2::c633:640c
ip-address: 2001:db8:2::c633:640c@853
server-count: 1
statistics: 86400
tls-service-key: "/etc/ssl/ns2.example.net.key"
tls-service-pem: "/etc/ssl/ns2.example.net.fullchain.pem"
tls-service-ocsp: "/etc/ssl/ns2.example.net.ocsp"
remote-control:
control-enable: yes
key:
name: nskey.example.net
algorithm: sha256
secret: "IAmASecretKeyForDomainTransfers"
zone:
name: "example.net"
zonefile: "/var/nsd/zones/slave/%s.dns"
allow-notify: 192.0.2.11 nskey.example.net
allow-notify: 2001:db8:1::c000:020b nskey.example.net
request-xfr: 192.0.2.11 nskey.example.net
request-xfr: 2001:db8:1::c000:020b nskey.example.net
outgoing-interface: 198.51.100.12
outgoing-interface: 2001:db8:2::c633:640c
Sur les deux serveurs, vous devez exécuter la commande suivant pour
prendre le contrôle à distance pour que l’utilisation de nsd-control(8)
fonctionne :
$ doas nsd-control-setup
Maintenant, il faut vérifier votre configuration. Exécutez la commande
suivante sur chacun des serveurs afin de trouver des erreurs de
typographie :
$ doas nsd-checkconf /var/nsd/etc/nsd.conf
Si tout semble bon, vous êtes prêt pour activer et démarrer nsd(8) sur les deux serveurs :
$ doas rcctl enable nsd
$ doas rcctl start nsd
La dernière pièce du puzzle sont les règles pour pf(4) afin d’autoriser
l’accès externe à nsd(8). Ajoutez ces deux lignes à /etc/pf.conf
:
pass in on egress proto { tcp udp } from any to egress port domain
pass in on egress proto { tcp udp } from any to egress port domain-s
Vérifiez puis chargez la configuration changée :
$ doas pfctl -nf /etc/pf.conf
$ doas pfctl -f /etc/pf.conf
Avec l’aimable autorisation de Bruno Flückiger !
Cette page est la traduction de la page How to build a name server with DNS over TLS (DoT) du site BSDHowto.ch.
J’ai écrit historiquement cette traduction sur le wiki de la communauté “OpenBSD Pour Tous”.
Le serveur web nginx affiche une “belle page blanche” avec la mention Error 504: Gateway timeout !
Cette erreur indique que le serveur web nginx agit comme une passerelle et ne peut délivrer le contenu. Le serveur ne peut traiter dans un temps imparti la requête demandée, la connexion est alors fermée.
Il peut y avoir plusieurs raisons, un élément réseau défectueux, mais aussi un des paramètres suivants mal configurés :
Si vous utilisez PHP-FPM, vérifiez les écritures des directives :
fastcgi_*_timeout
proxy_*_timeout
send_timeout
Par défaut, toutes ces directives sont de 60 secondes. Des valeurs, en temps de secondes, trop basses impactent le serveur nginx et lui empêchent de délivrer la requête…
Exemple, augmentez dans votre contexte http
:
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
send_timeout 600;
Et, concernant le contexte location
lié à PHP, ajoutez, par exemple :
fastcgi_connect_timeout 330;
fastcgi_read_timeout 330;
fastcgi_send_timeout 330;
Ceci étant fait, redémarrez le serveur !
Il peut y avoir plusieurs raisons pour laquelle nginx affiche une erreur 403. Le serveur comprend la requête mais refuse de répondre au client web.
Les raisons :
Une mauvaise configuration du chemin vers le fichier de configuration du contexte server.
Un problème de droits sur le système de fichiers de la racine web, généralement
/var/www/
.
Par exemple, quelques lignes de log d’erreur :
2020/08/22 10:50:18 [error] 77863#0: *2 directory index of "/htdocs/" is forbidden, (…)
2020/08/22 10:52:21 [error] 890#0: *1 open() "/htdocs/robots.txt" failed (2: No such file or directory), (…)
Vérifiez :
Les écritures des chemins web. Exemple dans le fichier de configuration
principal de nginx, les include
vers sites-enabled
sont ils corrects ?
Il suffit d’une erreur de typographie…
La racine web doit avoir, normalement pour droits utilisateurs, les noms
utilisateur et groupe web… www-data:www-data
, ou www:www
sauf cas particulier, tel sous OpenBSD root:daemon
Les droits systèmes devraient être de type 0755
.
Une fois la situation rétablie, redémarrer/recharger nginx.
Sous OpenBSD, il n’y a pas encore de port du module nginx-brotli, donc la gestion de la compression au format Brotli semble compromise. Et, bien : non !
Version :
nginx et brotli ne sont pas dans le système de base, mais dans les
ports. À installer avec la commande pkg_add
…
Étant donné qu’il n’est pas recommandé d’activer la compression à la volée - sauf au doux sacrifice d’usage de techniques CSP et de contrôle absolu sur l’émetteur du contenu compressé à la volée -, dans ce mémo, nous nous concentrerons sur la délivrance de contenu compressé de fichiers statiques.
Il y a une manière assez simple de mettre en place :
La compression de fichiers se fait simplement : $ brotli -Z fichier
qui produira un fichier supplémentaire portant l’extension br
. L’option
-Z
offre le meilleur taux de compression, par défaut.
Lire le manpage installé, pour plus d’informations, si besoin… $ man brotli
Voici la fonction que j’utilise dans le cadre de mon fichier deploy
pour
mes fichiers créés avec Hugo :
Fichier : deploy
|
|
Ainsi, si le fichier statique fait plus de 1024 octets - choix totalement arbitraire - et que son extension est de type CSS, JS, JSON, HTML, SVG, TXT, ou XML, ou des fichiers de fonts de type eot, otf, ou ttf, alors la fonction compresse, dans un premier temps, au format brotli, suivi d’une compression au format gzip.
Pourquoi compresser aussi au format gzip ?
Pour les clients web qui n’ont pas la gestion du format brotli, cela permettra d’offrir un format de compression alternatif, reconnu généralement.
De même, la gestion du format brotli semble n’être efficace qu’avec l’usage du protocole HTTPS , même si votre client web lui le gère.
Passons maintenant au paramètrage du serveur web nginx. Dans le contexte server
:
set $extension "";
$extension
qui nous servira ensuite :
if ($http_accept_encoding ~ br) {
set $extension .br;
}
if (-f $request_filename$extension) {
rewrite (.*) $1$extension break;
}
location
pour
délivrer le fichier statique demandé dans sa forme compressée. Par
exemple, pour un fichier CSS :
location ~ /*.css.br$ {
add_header Content-Encoding br;
add_header Vary "Accept-Encoding";
gzip off;
types {}
default_type text/css;
}
Faire de même pour les autres formats de fichiers compressables, tels
que ceux cités ci-dessus. Remarquons :
gzip off;
puisque nous n’avons pas besoin
à ce moment de ladite compression.Voilà.
Pour finir, je vous offre les deux fichiers de déclaration que j’utilise pour mon serveur nginx sous OpenBSD :
Fichier : /etc/nginx/conf.d/brotli.conf
|
|
Fichier : /etc/nginx/conf.d/brotli-infos.conf
|
|
Sous OpenBSD depuis 6.1, pour la génération de certificats avec l’autorité de certification LE , nous avons intégré au système de base le client acme, écrit en C, reconnu pour être sécurisé.
Je ne traiterais pas de la configuration, elle est très simple, et vraiment bien documentée dans le manpage ad hoc.
Ce mémo existe pour répertorier quoi faire dans le cas de sortie en erreur.
TL;DR : Le client acme n’arrive pas à se connecter à votre serveur web. Dans les faits, il faut en passer par une investigation et une explication un peu plus poussée…
Investigation :
Par exemple, voici la fin du message verbeux d’acme :
# acme-client -v mydomain.tld
(…)
acme-client: challenge, token: L8dcjbmFhbE6N2GtSKxEi9yzhR888oSdBdgzt7GnJbc, uri: https://acme-v02.api.letsencrypt.org/acme/chall-v3/6581640382/2HdrCw, status: -1
(…)
acme-client: https://acme-v02.api.letsencrypt.org/acme/chall-v3/6460247699/ixiI9A: bad HTTP: 400
acme-client: transfer buffer: [{ "type": "urn:ietf:params:acme:error:malformed", "detail": "Unable to update challenge :: authorization must be pending", "status": 400 }] (144 bytes)
acme-client: bad exit: netproc(70635): 1
Le réflexe à avoir est de basculer en mode doublement verbeux, ce qui nous donnera plus de détail :
# acme-client -vv mydomain.tld
(…)
acme-client: transfer buffer: [{ "identifier": { "type": "dns", "value": "www.mydomain.tld" }, "status": "invalid", "expires": "2020-08-24T22:24:39Z", "challenges": [ { "type": "http-01", "status": "invalid", "error": { "type": "urn:ietf:params:acme:error:connection", "detail": "Fetching http://mydomain.tld/.well-known/acme-challenge/xCefC0pD3W1VRLeWVYHmYmJj1Bf06G1hoskXdN1xIEg: Connection refused", "status": 400 }, "url": "https://acme-v02.api.letsencrypt.org/acme/chall-v3/6603509164/7d1MkA", "token": "xCefC0pD3W1VRLeWVYHmYmJj1Bf06G1hoskXdN1xIEg", "validationRecord": [ { "url": "http://www.mydomain.tld/.well-known/acme-challenge/xCefC0pD3W1VRLeWVYHmYmJj1Bf06G1hoskXdN1xIEg", "hostname": "www.mydomain.tld", "port": "80", "addressesResolved": [ "88.136.16.221", "2001:470:cc33::3" ], "addressUsed": "2001:470:cc33::3" }, { "url": "http://www.mydomain.tld/.well-known/acme-challenge/xCefC0pD3W1VRLeWVYHmYmJj1Bf06G1hoskXdN1xIEg", "hostname": "www.mydomain.tld", "port": "80", "addressesResolved": [ "88.136.16.221", "2001:470:cc33::3" ], "addressUsed": "88.136.16.221" }, { "url": "http://mydomain.tld/.well-known/acme-challenge/xCefC0pD3W1VRLeWVYHmYmJj1Bf06G1hoskXdN1xIEg", "hostname": "mydomain.tld", "port": "80", "addressesResolved": [ "88.136.16.221", "2001:470:cc33::3" ], "addressUsed": "2001:470:cc33::3" } ] } ] }] (1712 bytes)
acme-client: challenge, token: xCefC0pD3W1VRLeWVYHmYmJj1Bf06G1hoskXdN1xIEg, uri: https://acme-v02.api.letsencrypt.org/acme/chall-v3/6603509164/7d1MkA, status: -1
(…)
acme-client: https://acme-v02.api.letsencrypt.org/acme/chall-v3/6603509164/7d1MkA: bad HTTP: 400
acme-client: transfer buffer: [{ "type": "urn:ietf:params:acme:error:malformed", "detail": "Unable to update challenge :: authorization must be pending", "status": 400 }] (144 bytes)
acme-client: bad exit: netproc(37360): 1
Explications
Au dessus de la ligne terminant par status: -1
, on remarque une nouvelle
ligne. Cette ligne nous informe :
invalid
,Connection refused
,status: 400
,"addressUsed": "2001:470:cc33::3"
En fait, acme-client informe qu’il n’arrive pas à se connecter sur le serveur à l’adresse IPv6. La première chose à s’assurer est que le serveur web soit joignable sur votre adresse IPv6 !
Il peut y avoir diverses raisons pour lesquelles votre serveur web ne soit pas joignable sur IPv6 :
ping6
, puis…listen on votre-adresse-ipv6 port 80
listen [::]:80;
pass in quick on egress inet6 proto tcp to votre-adresse-ipv6 port 80 flags S/SA modulate state
Une manière de s’en assurer est d’utiliser un scanner de port sur IPv6, par exemple celui de ipv6scanner.com. Si le scanner vous dit qu’aucun port correspond n’est ouvert, cherchez profondément la raison…
Dans cet exemple, le serveur ne répondait pas lors de l’interrogation sur
son adresse IPv6. Le status 400
peut très bien être provoqué sur l’adresse
IPv4 du serveur. Appliquez le même raisonnement pour vous assurez que votre
serveur soit joignable sur son adresse IPv4.
Ceci est une des raisons pour lesquelles acme-client peut retourner un statut d’erreur 400. À chaque fois, il faut analyser profondément les informations retournées.
Le client acme restitue de manière sybilline ce message :
# acme-client -v mydomain.tld
(…)
acme-client: order.status -1
acme-client: bad exit: netproc(27643): 1
Là, il peut y avoir de multiples raisons qui empêche tout simplement le client acme de discuter avec votre serveur web.
Le propos est de vérifier qu’aucune écriture de la configuration du serveur n’empêche la lecture dans le répertoire de challenge acme.
Exemples pouvant générer :
location ~ /\. {
access_log off;
log_not_found off;
deny all;
}
Cet article montre comment installer et utiliser une imprimante MFP de marque Epson, sous OpenBSD, avec Cups.
Si votre imprimante gère le protocole ESC/P-R, continuez la lecture… sinon au-revoir !
De même, ce tutoriel ne montre pas la configuration par connexion USB, mais en mode réseau.
Imprimantes testées :
La MFP peut être détectée de manière automatique sur votre réseau, grâce au protocole DNSSD, si et seulement si vous installez le paquet avahi Celui-ci nécessite que le service messagebus soit actif.
Autant la détection de la MFP se fait sans soucis, autant je ne suis jamais arrivé à l’utiliser ainsi.
Avahi n’est pas strictement nécessaire.
Commencez par installer CUPS !
Depuis OpenBSD 6.2, les binaires lpq
, lpr
, et lprm
ne sont plus liés symboliquement
à /usr/bin
. Il est nécessaire de les utiliser en les préfixant de /usr/local/bin/
.
Pensez à éditer votre fichier ~/.kshrc
, afin de créer des alias qui vous
seront utiles, en ajoutant le code suivant :
for i in lpq lpr lprm; do alias $i=/usr/local/bin/$i; done
/usr/local/share/ppd/epson-inkjet-printer-escpr/Epson-ET-4700_Series-epson-escpr-en.ppd
vers votre répertoire ~/Downloads
puis indiquez-le à l’interface Web de Cups.Dans un premier temps, il est nécessaire d’installer le paquet epson-inkjet-printer-escpr.
Les paquets foomatic et gutenprint peuvent à être utile à la reconnaissance du périphérique.
Pour pouvoir scanner, il est nécessaire d’installer le logiciel sane :
# sane-backends xsane
Il sera accessible depuis le menu “Graphisme” > “Xsane”.
De préférence, choisir le protocole Unix lpd, c’est celui qui fonctionne le mieux…
Tel que : lpd://adr_ip/PASSTHRU
Il est possible d’imprimer aussi sur ces autres protocoles :
ipp://adr_ip:631/ipp/print
ou ipps://adr_ip:631/ipp/print
http://adr_ip:631/ipp/print
ou https://adr_ip:631/ipp/print
socket://adr_ip:9100
Les versions ipps et https nécessitent une configuration plus poussée, non abordée ici.
Théoriquement, Cups permet aussi d’imprimer via Samba, mais je n’ai pas testé.
Dans un premier temps, il faut modifier le fichier de configuration /etc/sane.d/dll.conf
pour y ajouter le mot clé epkowa.
Ensuite, il est nécessaire de modifier le fichier de configuration /etc/sane.d/epkowa.conf
pour préciser : net adr_ip 1865
Il est probable que le fichier epkowa.conf ne soit pas disponible ; je vous propose cette version par défaut à configurer :
Fichier : /etc/sane.d/epkowa.conf
|
|
La partie scanner n'est pas encore gérée . Les scanners de la série EcoTank sont reconnus en tant que backend externe à SANE, par le projet de pilote nommé utsushi.
Le dépôt officiel du projet utsushi : https://gitlab.com/utsushi/utsushi
Gageons que dans un futur procher, le projet Sane intégrera ce pilote, ce qui devrait ensuite permettre l’usage de la partie scanner.
Testée sur OpenBSD stable : 6.7
La partie impression fonctionne très bien…
Après avoir installé
le paquet epson-inkjet-printer-escpr
, copiez le fichier
/usr/local/share/ppd/epson-inkjet-printer-escpr/Epson-ET-4700_Series-epson-escpr-en.ppd
vers votre répertoire ~/Downloads
.
Indiquez à Cups d’installer le fichier PPD en cliquant sur le bouton [ Browse… ] au moment du choix de celui-ci.
Les protocoles de connexion suivants sont supportés :
lpd://adr_ip/PASSTHRU
ipp://adr_ip:631/ipp/print
> ou ipps://adr_ip:631/ipp/print
http://adr_ip:631/ipp/print
ou https://adr_ip:631/ipp/print
socket://adr_ip:9100
smb://adr_ip/printer
Pensez à redémarrer le service CUPS !
La partie scanner n’est pas encore gérée. Les scanners de la série EcoTank sont reconnus pour être pris en charge par la partie de backend externe utsushi au projet SANE.
Un petit mémoriel pour décrire comment gérer régulièrement une Debian Sid. Ceci est aussi valable pour une Devuan Ceres.
C’est plus du “Trucs & Astuces”, car je risque fort de ne pas rentrer dans les détails, mais plutôt de préciser les étapes nécessaires à la gestion d’une version dite “Unstable” de Debian, ou Devuan.
Je ne décrirais pas le processus d’installation. Si vous avez déjà installé une Debian/Devuan, vous êtes certainement déjà familier avec celui-ci. Si ce n’est pas le cas, voyez la section Documentation où vous trouverez des informations utiles.
Pour installer Sid, le plus simple est de télécharger l’image mini.iso. Cette version minimale de Debian Sid est mise à jour régulièrement.
Pour :
Pour les autres architectures, parcourez l’arborescence correspondante à la vôtre dans le répertoire ftp suivant : http://ftp.debian.org/debian/dists/sid/main/
Pour information, il existe deux communautés différentes qui proposent aussi Debian Sid, déjà packagée, prête à être installé :
Par expérience, préférez la Xebian… elle fournit par défaut les outils apt nécessaires. De plus, l’image ISO est plus souvent générée.
Quoiqu’il en soit les conseils de gestion que vous trouverez ci-dessous, sont absolument valables. Tenez en compte !
Pour la Devuan Ceres, le plus simple est de partir de l’installation de la
stable actuelle, puis de modifier votre fichier sources.list
pour qu’il
contienne à minima cette ligne :
deb http://deb.devuan.org/merged ceres main non-free contrib
Ce qui signifie de commenter celles de votre précédente installation, voire de les supprimer.
Pour le faire proprement : # apt edit-sources
Puis mettez à jour les dépôts et faites une mise à niveau :
# apt update
# apt full-upgrade
Les outils supplémentaires à installer ABSOLUMENT sont des outils
complémentaires à l’outil apt
:
apt-listbugs
: outil qui lors d’une mise à jour vous avertira à-propos
duquel logiciel a un bogue plus ou moins critique. Cet outil est PRIMORDIAL.apt-listchanges
: outil qui vous informera après la mise à jour, des
changements importants fait sur untel logiciel.needrestart
: outil qui permet de savoir quel service doit absolument
être redémarré après une mise à jour. Pas nécessaire, mais utile.package-update-indicator
: outil de suivi et notification de la disponibilité
de paquets mis à jour. Pas nécessaire, mais utile.Si vous avez choisi d’installer la Xebian, les deux premiers outils sont fournis, par défaut.
Lorsque vous faites une mise à jour, s’il y a des bogues plus ou moins critique, du fait d’avoir installé l’outil apt-listbugs, apt vous avertira que tel logiciel a tel bogue, ayant tel niveau de criticité.
Le plus simple est, si vous avez un doute, que vous ne comprenez pas en quoi ce bogue consiste, comment il impacte le système, alors répondez ABSOLUMENT par l’appui sur la touche P !
Cela “épinglera” le logiciel en question, empêchant sa mise à jour jusqu’à une future mise à jour qui aura corrigé le bogue en question et vous permettra à ce moment futur de le mettre à jour sans aucun soucis.
Tout épingleage sera enregistré dans le fichier
/etc/apt/preferences.d/apt-listbugs
.
L’impact : à chaque logiciel, que vous aurez figé en état “Pin”, il vous faudra arrêter ensuite la mise à jour en appuyant ensuite sur la touche N… Puis relancer la mise à jour normalement.
Les logiciels “étiquettés”, ainsi par vos soins, ne vous seront plus soumis à l’analyse, et attendront une future mise à jour corrigeant le(s) bogue(s) en question.
⇒ À partir du moment où vous avez installé apt-listbugs, apt vous avertira aussi lors d’une installation logicielle. S’il y a un bogue critique qui concerne le logiciel que vous cherchez à installer sur votre architecture, il est certainement prudent d’en tenir compte ; si cela concerne une autre architecture, ne vous tracassez pas du bogue en question, et faites votre installation demandée/nécessaire. Dans le cas où vous épinglez le logiciel lors de l’installation, à cause d’un bogue critique, vous ne pourrez donc pas installer le logiciel ; il vous faudra attendre une future mise à jour de celui-ci.
C’est un dilemne : à vous de faire votre choix. Étant donné que les messages d’avertissements sont en anglais, il peut en effet être délicat de les comprendre. Ne faites pas l’impasse sur un message que vous ne comprenez pas, en prenant le risque d’installer ou de mettre à jour un logiciel.
Posez des questions au-travers des différentes communautés , qui généralement, seront capables de vous aider de manière adéquate.
⇒ Si apt-listchanges vous avertit d’un changement précis, tenez-en compte. À ce propos, si vous avez configuré votre système pour envoyer des courriels, vous recevrez un courriel vous informant desdits changements.
⇒ Pensez à redémarrer absolument votre machine si un nouveau noyau a été installé. Malheureusement, parfois un nouveau noyau ne vous permettra pas d’utiliser correctement votre matériel, cela peut en effet arriver. Il vous faudra veiller à garder et redémarrer sur un noyau précédent fonctionnel.
⇒ needrestart vous avertira de redémarrer tel ou tel service ; parfois, ce sera votre session utilisateur qu’il faudra simplement redémarrer.
⇒ Régulièrement, utilisez l’option autoremove
de l’outil apt afin
de supprimer les dépendances qui ne seraient plus nécessaires à votre
système suite à vos différentes mises à jours. Lire à ce propos le chapitre correspondant
.
Une fois par semaine, de préférence le Lundi - l’expérience m’ayant appris que c’est le jour le moins critique, dans le sens où je n’ai jamais planté une mise à jour d’une Sid ce jour-là ; par contre, cela m’est arrivé sur d’autres jours de la semaine.
Ce jour-là, utilisez juste l’option upgrade
à l’outil apt
.
Une fois par mois, ceci est un impératif - qui peut être fait une fois
par semaine, mais généralement peu utile, utilisez l’option full-upgrade
de l’outil apt
.
full-upgrade
peut avoir pour conséquence la suppression de certains logiciels installés,
qui ne seront peut-être pas réinstallables par la suite.Parfois l’outil apt
peut vous informer d’un certain nombre de logiciels
qui n’ont plus de dépendances utiles et qui peuvent être supprimés avec
l’option autoremove
.
Ce sera particulièrement le cas lorsque vous aurez utiliser l’option
full-upgrade
pour mettre à jour votre version Unstable.
Si vous ne voulez pas que apt vous supprime particulièrement certains des
logiciels nommés dont vous pouvez avoir besoin, il faudra utiliser l’outil
apt-mark
au cas par cas en utilisant l’option manual
, tel que :
$ apt-mark manual nom-logiciel
Ensuite, une fois les logiciels marqués, vous pourrez utiliser l’option autoremove
avec l’outil apt
.
Il est utile de lire le manpage : man 8 apt-mark
⇒ Lire les journaux liés à l’activité d’apt, ils sont dans /var/log/apt
et se nomme history
et term
. Le deuxième nécessite les droits admins
même pour la lecture, et reprend l’historique de l’activité tel qu’il est
affiché dans le terminal/la console.
⇒ Pour savoir quels paquets sont épinglés, il y a deux manières :
apt-cache
et de son option policy
, tel que :Fichiers du paquet :
100 /var/lib/dpkg/status
release a=now
500 http://deb.devuan.org/merged ceres/non-free i386 Packages
release v=1.0.0,o=Devuan,a=unstable,n=ceres,l=Devuan,c=non-free,b=i386
origin deb.devuan.org
500 http://deb.devuan.org/merged ceres/non-free amd64 Packages
release v=1.0.0,o=Devuan,a=unstable,n=ceres,l=Devuan,c=non-free,b=amd64
origin deb.devuan.org
500 http://deb.devuan.org/merged ceres/contrib i386 Packages
release v=1.0.0,o=Devuan,a=unstable,n=ceres,l=Devuan,c=contrib,b=i386
origin deb.devuan.org
500 http://deb.devuan.org/merged ceres/contrib amd64 Packages
release v=1.0.0,o=Devuan,a=unstable,n=ceres,l=Devuan,c=contrib,b=amd64
origin deb.devuan.org
500 http://deb.devuan.org/merged ceres/main i386 Packages
release v=1.0.0,o=Devuan,a=unstable,n=ceres,l=Devuan,c=main,b=i386
origin deb.devuan.org
500 http://deb.devuan.org/merged ceres/main amd64 Packages
release v=1.0.0,o=Devuan,a=unstable,n=ceres,l=Devuan,c=main,b=amd64
origin deb.devuan.org
Paquets épinglés :
libigdgmm12 -> 22.0.2+ds1-1 avec la priorité 30000
libigdgmm12:i386 -> 22.0.2+ds1-1 avec la priorité 30000
Remarquez la section “Paquets épinglés :” en fin d’invite.
/etc/apt/preferences.d/apt-listbugs
.⇒ Parfois du fait d’avoir épinglé un ou plusieurs logiciels, cela rend impossible l’installation d’un autre logiciel avec un ou plusieurs messsages d’erreurs lors de la tentative d’installation, tel que :
Lecture des listes de paquets…
Construction de l'arbre des dépendances…
Lecture des informations d'état…
Calcul de la mise à jour…
Certains paquets ne peuvent être installés. Ceci peut signifier
que vous avez demandé l'impossible, ou bien, si vous utilisez
la distribution unstable, que certains paquets n'ont pas encore
été créés ou ne sont pas sortis d'Incoming.
L'information suivante devrait vous aider à résoudre la situation :
Les paquets suivants contiennent des dépendances non satisfaites :
linux-headers-5.16.0-3-amd64 : Dépend : linux-compiler-gcc-11-x86
E: Impossible de corriger les problèmes, des paquets défectueux sont en mode "garder en l'état".
N’oubliez pas que leur coup de main est bénévole, souvent anonyme, alors soyez le plus descriptif possible, fournissez une EXACTE copie du message en n’oubliant pas de décrire sur quelle architecture vous installez ou mettez à jour tel logiciel !
Plus vous serez précis, plus vous serez agréable, et plus vous aurez des chances d’être aidé. Et surtout, n’attendez pas ET n’exigez JAMAIS qu’on vous aide absolument.
Soyez amical, cordial, agréable - même si la réponse ne vous plaît/convient pas.
checkrestart est un programme conçu pour aider à trouver les processus qui ont besoin d’être redémarrés après une mise à jour.
checkrestart parcourt entièrement la table de fichiers du système, à la recherche de processus ayant des nœuds détachés du système de fichiers.
Installez
le
paquet checkrestart
.
Très simplement : # checkrestart
# checkrestart
76195 pflogd
47538 pflogd
54214 slaacd
50500 slaacd
41162 slaacd
Il faut donc redémarrer les services
en question, qui dans cet exemple sont pflogd
et slaacd
.
checkrestart - une aide pour trouver les programmes qui ont besoin d’être redémarrés.
checkrestart [-v] [-M core] [-N system] [-W swap]
checkrestart est un programme conçu pour aider à trouver les processus qui ont besoin d’être redémarrés après une mise à jour.
checkrestart parcourt entièrement la table des fichiers sur le système à la recherche de nœuds de processus VTEXT détachés du système de fichiers.
Par défaut, checkrestart affichera l’identifiant du processus et le nom de l’exécutable du processus en cours.
Les options sont les suivantes :
Cas d’utilisation typique :
pkg_add -u
Le nom checkrestart vient d’un outil similaire sur Debian qui est relié à lsof(1) FR pour aboutir au même résultat.
checkrestart a été écrit par Sebastien Marie semarie@online.fr.
Seuls les nœuds VTEXT sont rapportés par checkrestart. Certains programmes qui utilisent d’anciennes bibliothèques ne sont pas rapportés du fait d’un manque de support dans le noyau.
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Depuis OpenBSD 6.7, le système de fichiers FFS2 - pour Enhanced Fast Filesystem - est disponible, dans les contextes suivants :
newfs
(8) avec l’option -O2
,
pour les tailles plus petites.Toutes les architectures supportées par le projet OpenBSD en bénéficient.
fsck
(8).fsck()
surtout si de nombreux inodes sont utilisés.Le plus simple pour convertir une partition est de faire une nouvelle installation avec une image de la version 6.7 ou supérieure.
Néanmoins, il est possible de le faire en quelques petites étapes simples :
# umount
# dump
# newfs -O2
# restore
# mount
Attention, les commandes présentées ci-dessus ne sont pas complètes, dans le sens où elle ne précise pas le disque ou la partition à cibler ; il est important de lire les manpages correspondants pour les utiliser correctement.
Pour finir, redémarrez la machine…
Et, voilà !
cf : source
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
OpenBSD intègre par défaut dans le système de base :
un serveur web, nommé httpd, depuis 5.7 - que j’ai présenté plus ou moins succinctement ici
un serveur CGI, nommé slowcgi, depuis 5.4
Site web : https://bsd.plumbing/
OpenBSD : 6.6, 6.7
Principe : si le client web informe qu’il accepte l’encodage de compression aux formats deflate, gzip, br, alors httpd passe la main à slowcgi qui délivre le contenu compressé correspondant.
Le problème est que le serveur httpd n’est pas capable de gérer la délivrance de contenu statique compressé.
L’astuce est d’utiliser le serveur CGI slowcgi, intégré lui-aussi dans le système de base, pour assumer la délivrance de ce contenu statique compressé.
En effet, par le biais de script CGI - ici, en shell - nous allons pouvoir assumer la délivrance de ces contenus statiques suivants :
Il est nécessaire de télécharger mon script sbw.cgi.
Une fois téléchargé, à vous de le mettre dans le répertoire cgi-bin
du
chroot web. Le mieux étant d’utiliser la commande install
suivante :
install -o www -g bin -m 0550 sbw.cgi /var/www/cgi-bin/sbw.cgi
qui nous permet de l’installer proprement avec les droits minimum, strictement
nécessaire, attribué à l’utilisateur web www
, au groupe bin
.
Le script nécessite l’installation de plusieurs binaires et quelques bibliothèques à l’intérieur du chroot web pour fonctionner correctement.
Il faut donc veiller à copier :
/bin
./usr/bin
/usr/lib/libc.so.xx.0
2
/usr/libexec/ld.so
vers leurs répertoires respectifs dans le chroot web /var/www/
.
Si tous doivent être assujettis à l’utilisateur root
et groupe bin
:
install -o root -g bin -m 0555 /bin/sh /var/www/bin/
install -o root -g bin -m 0555 /usr/bin/stat /var/www/usr/bin/
install -o root -g bin -m 0444 /usr/lib/libc.so.xx.0 /var/www/usr/lib/
install -o root -g bin -m 0444 /usr/libexec/ld.so /var/www/usr/libexec/
Cela nécessite de créer avant les répertoires correspondant dans le chroot web !
Mais comme je suis quelqu’un de très gentil, retrouvez mon script de gestion des dépendances.
1
De l’intérêt du binaire logger
:
bien sûr que normalement, idéalement, nous n’avons pas besoin du logger, mais
il a pour propos de journaliser certaines actions, qui en cas d’échec, sont
intéressantes à faire écrire dans les journaux /var/log/{daemon,messages}
.
De même, si la variable debug
est paramétrée sur 1
, dans la fonction
principale, alors le logger restituera les valeurs correspondantes aux
différentes variables, à fin d’analyse : s’assurer que telle variable reçoit
bien une valeur, dans tel contexte, et si oui, quelle valeur !
2 La bibliothèque C partagée, entre chaque version d’OpenBSD, change aussi de nom. Ainsi, pour OpenBSD :
libc.so.96.0
libc.so.95.1
Ce détail est important et peut difficilement être scripté. Donc, lors de changement de version d’OpenBSD, il faut bien veiller à modifier le script pour lui définir le nouveau nom de la bibliothèque, sinon il ne fonctionnera pas !
ldd
sur le binaire en question.Il est nécessaire d’ajouter dans votre contexte server
, les déclarations
location
suivantes :
Code : httpd
location "/*.atom" { include "/etc/httpd.d/sbw.conf" }
location "/*.css" { include "/etc/httpd.d/sbw.conf" }
location "/*.html" { include "/etc/httpd.d/sbw.conf" }
location "/*.js" { include "/etc/httpd.d/sbw.conf" }
location "/*.json" { include "/etc/httpd.d/sbw.conf" }
location "/*.svg" { include "/etc/httpd.d/sbw.conf" }
location "/*.txt" { include "/etc/httpd.d/sbw.conf" }
location "/*.xml" { include "/etc/httpd.d/sbw.conf" }
Quant au cas du fichier sbw.conf
, il renferme le contenu des déclarations
fastcgi
suivantes :
Fichier : /etc/httpd.d/sbw.conf
root "/cgi-bin/sbw.cgi"
fastcgi param realroot "/htdocs/domaine.tld/www"
fastcgi param cachecontrol "1814400"
fastcgi param file404 "/404.html"
Explications :
Il importe de définir au moins :
Le serveur slowgci ne nécessite aucune configuration. Il nécessite
seulement d’être activé et démarré avec l’outil de contrôle rcctl
.
En effet, l’histoire du protocole HTTP nous a révélé deux failles majeures liées à la compression à la volée, ou compression dynamique de contenu : CRIME et BREACH - qui est dérivée de la première. Ces deux failles peuvent même impacter TLS .
Même si la plupart des clients web ont été corrigés pour s’efforcer d’atténuer ces failles, il n’est clairement pas recommandé d’utiliser la méthode de compression à la volée, que savent très bien gérer la plupart des serveurs HTTP.
Parmi les parades, a été l’adoption depuis HTTP 1.1 du transfert par encodage
de bloc - la fameuse entête Transfer-Encoding: chunked
- de même, il est
fortement recommandé de mettre en place une politique Referrer afin de
n’autoriser que la délivrance de contenu compressé QUE depuis le domaine
en cours, et de la refuser depuis tout autre domaine duquel du contenu est
appelé (CSS, JS, fonts, json, etc.).
L’auteur Reyk Floeter se refuse à la prise en charge de contenu compressé. Et, même si une requête a été faite pour délivrer du contenu déjà compressé, ce n’est pas prêt d’être intégré.
Le format brotli est un format de compression inventé par une équipe de l’entreprise Google. Il est considéré comme étant le successeur de gzip car plus rapide et un meilleur taux de compression.
En savoir plus :
À savoir que curl gére le format brotli, depuis la sortie de sa version
7.57.0, par l’usage de l’option --compressed
, voire de l’option -H
-
option qui permet de gérer finement les entêtes HTTP. (cf : lire son manpage)
Ahhh, fichu Firefox, qui depuis la version 64, ne gére plus nativement les flux de syndication Atom et RSS.
En fait, c’est plus subtil qu’il n’y paraît. Si vous délivrez le contenu Atom et RSS avec le mime type text/xml, puisqu’après tout, tous les deux sont bel et bien des fichiers XML, alors Firefox acceptera de les lire nativement et de vous les afficher. Il ne les mettra pas en forme, mais il vous affichera le contenu.
Si vous les délivrer avec leur propre type de contenu, à savoir respectivement application/atom+xml et application/rss+xml, tous les deux normés par une RFC ou l’autre, alors Firefox vous demandera quoi en faire !
Une aberration sans nom !!!
Pour la petit histoire, Xavier Cartron @prx est l’auteur original de cette idée de délivrer du contenu statique compressé.
Le travail que j’ai effectué se base sur sa première version de script CGI shell. Mais elle ne me satisfaisait pas, pour plusieurs raisons, car il se contente à délivrer au format gzip, QUE SI gzip est demandé.
Il a eu l’idée géniale d’ajouter la gestion de l’entête ETag
, qui sert à
fixer un identifiant par ressource délivrée. C’est dans ce contexte, que
le binaire sha256 est utile.
Ayant entendu parler du format de compression brotli , j’ai donc repris/continué l’écriture afin de pouvoir délivrer du contenu statique compressé précédemment avec ce format.
Ensuite, j’ai ajouté le code nécessaire pour la gestion des entêtes nécessaires :
Content-Length
: pour envoyer le poids du document quelque soit sa version ;
c’est dans ce contexte que le binaire stat est nécessaire.Last-Modified
: pour récupèrer la date de modification du document à
délivrer ; d’aucun considère que cette entête est plus pertinente que ETag.
C’est dans ce contexte que les binaires date et stats sont utiles.Transfer-Encoding
: pour envoyer le document à délivrer dans le bon
format de compression, si besoin est.Puis, j’ai écrit le code nécessaire pour détecter si les dépendances utiles étaient bien dans le chroot web, autrement le script ne peut fonctionner. Si les dépendances ne sont pas installées, alors le serveur renvoie une erreur 500, avec un message HTML décryptant l’erreur.
Attention : le script n’installe pas et ne peut pas installer les dépendances, du fait d’être dans le chroot web, il ne peut voir ce qui se passe au-delà !
Puis, après quelques recherches sur le web, j’ai compris que le format de compression deflate qui peut être demandé par certains clients web, est compris dans le format de compression gzip, de là, la prise en charge.
Mais j’étais confronté à des dysfonctionnements que je n’arrivais pas à comprendre et encore moins à résoudre. Et, là deux “choses” m’ont sérieusement aider à avancer - car, à moment donné, ne m’en sentant plus les capacités, j’ai tout simplement laissé tomber, n’y arrivant pas, ne trouvant pas l’aide nécessaire pour avancer - :
debug
et d’utiliser le binaire logger
pour m’assurer des différents retours.Une astuce que m’a donné Solène est l’usage en local de cette commande :
env HTTP_ACCEPT_ENCODING=br realroot=/var/www/htdocs/domaine.tld/dev/ PATH_INFO=index.html /var/www/cgi-bin/sbw.cgi | less
m’expliquant qu’il est possible d’interroger localement directement le script
CGI, en lui envoyant les différentes valeurs possibles lors de l’appel…
via les variables d’environnements.
Idée géniale !
À ce propos, étant donné que nous avons installé le script shell CGI sbw.cgi
avec des droits utilisateurs 0550, vous aurez le droit à cette petite
erreur : env: /var/www/cgi-bin/sbw2.cgi: Permission denied
il suffit de changer le droit d’exécution pour les autres ;-) (0551
, ou +x
)
J’ai amélioré la détection du mime type en l’obtenant à partir du fichier appelé sur le système - qui nécessite l’usage du binaire basename - et la gestion des types de contenu des flux de syndication Atom ou RSS.
Pour finir, j’ai écrit le code nécessaire pour détecter si l’agent utilisateur était Firefox .
J’ai écrit la première mouture de ce hack nécessitant l’ajout des binaires
grep
et awk
- solution qui ne me satisfaisait pas, mais fonctionnelle.
Et, suite à la réflexion de l’utilisateur @eol, sur le forum de la communauté
française d’“OpenBSD pour tous”, j’ai remplacé par un travail sur l’expansion
des variables en shell.
Et, voilà !
Actuellement, @prx a réécrit son script shell en langage C :
En savoir plus sur la mise en place d’une politique Referrer : Referrer (header)
Megatools est une collection de programmes pour accéder aux services de Mega depuis la ligne de commande depuis votre machine ou serveur.
Megatools vous permet de copier des fichiers individuels voire une arborescence de répertoires vers et depuis le nuage informatique. Vous pouvez aussi permettre le téléchargement de flux, tels la prévisualisation de vidéos et de fichiers audio, sans avoir le besoin de télécharger le fichier en entier.
Megatools est robuste et optimisé pour les opérations rapides - autant que les serveurs Mega le permettent. Les exigences de mémoire et d’utilisation de CPU sont réduites au minimum.
Installez
le
paquet megatools
.
~/.megarc
.Voici à quoi il ressemble, au minimum :
[Login]
Username = identifiant
Password = mot-de-passe
Pour rappel, merci de lire le man megarc
pour connaître les
différentes options de configuration possibles.
La première chose à tester, une fois votre configuration
faite, est la commande megadf
qui permet de tester si la connexion se
fait bien avec le service, ainsi que l’authentification avec ; tel que,
pour l’exemple :
$ megadf
Total: 53687091200
Used: 1163522967
Free: 52523568233
Ainsi la commande retourne l’espace total, celui utilisé et celui qui est disponible.
Cette vidéo vous permet en
quelques minutes de comprendre l’usage des différentes commandes.
ATTENTION la commande megasync
, mentionnée dans la vidéo, a été
remplacée par la commande megacopy
**.
Vous avez oublié de spécifier votre identifiant de connexion, généralement votre courriel.
Il est très probable que le mot de passe ou l’identifiant que vous fournissez ne soit pas le bon.
Résultat, vous ne pouvez pas vous connecter au service de Mega.
Vous n’avez pas spécifié de mot de passe - donc pas de connexion au service.
Une fois le paquet installé, sont accessibles les différents manpages sur votre OS :
Ils sont ainsi accessibles sur Internet à l’adresse suivante : https://megatools.megous.com/man/megatools.html
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Tor Browser est une version personnalisée de Firefox-ESR spécifiquement préparée pour surfer sur Internet via le réseau anonyme Tor.
Sa configuration a pour but d’atténuer les attaques contre l’anonymisation d’un client, incluant le fait de déterminer son adresse IP et l’empreinte du navigateur. D’autres aspects de Firefox ont aussi été corrigés pour éviter autant que possible les failles de confidentialité.
Par défaut, sont inclus les modules NoScript, HTTPS Everywhere, TorButton, et Tor-Launcher. Notez que du fait de l’utilisation du module NoScript, l’utilisation de Javascript est bloqué par défaut.
Tor Browser utilise sa propre instance différente du port du serveur Tor , exécutée sur un autre port que celui du serveur.
obfsproxy
.Installez
le
meta-paquet tor-browser
.
Par défaut, Tor Browser enregistre sa configuration dans votre
répertoire personnel ~/TorBrowser-Data/
.
Le sous-répertoire Data
sert à enregistrer ses propres données :
Data/Browser
: la configuration liée au client webData/tor_data
: lié au service daemon TorData/torrc
: enregistre l’instance Tor - par exemple, la
configuration des ponts (briges), …Depuis OpenBSD 6.6, le logiciel de confidentialité KeePassXC est installable.
Pour fonctionner correctement, il est nécessaire d’installer le module KeePassXC-Browser.
Lire la page KeePassXC pour avoir plus d’informations concernant le module KeePassXC-Browser
Après l’installation, n’oubliez pas de lire le fichier
/usr/local/share/doc/pkg-readmes/tor-browser
.
La documentation officielle - en anglais - :
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
KeePassXC est un dérivé communautaire de KeePassX, le port multi-plateforme de KeePass pour Windows. Chaque fonctionnalité travaille sur ces plateformes et fait l’objet de tests approfondis afin de fournir aux utilisateurs les mêmes apparences et sensations sur chacun des systèmes d’exploitation supportés. Cela inclut la bien-aimée fonctionnalité Auto-Type.
Par défaut, la basse de données est toujours chiffrée avec l’algorithme de chiffrement AES (alias Rijndael) de norme industrielle, utilisant une clé de 256 bits. KeePassXC utilise un format de basse de données compatible avec KeePass Password Safe. Votre porte-monnaie fonctionne hors-ligne et ne requiert pas de connexion Internet.
Les principales fonctionnalités :
Disponible depuis OpenBSD 6.6 !
Actuellement, il existe 4 versions que vous pouvez installer :
keepassxc
: la version de basekeepassxc-browser
: la version d’intégration avec les navigateurs internetkeepassxc-browser-yubikey
: la version d’intégration pour les navigateurs
et pour fonctionner avec les clés USB de sécurité de type Yubikeykeepassxc-yubikey
: la version fonctionnant avec les clés de type YubikeyNe pas confondre les paramètres de configuration
de l’outil KeePassXC et ceux de la base de données .
La gestion des paramètres, une fois KeePassXC ouvert, se fait par le biais du menu Outils > Paramètres.
Cliquez sur l’icône Intégration aux navigateurs, puis dans la partie droite de la fenêtre cliquez sur la case à cocher [ ] Activer l’intégration aux navigateurs.
Une fois activée, les onglets Général et Avancé sont accessibles.
⇒ L’onglet Général précise qu’il faut télécharger le module KeePassXC-Browser correspondant au client web que vous utilisez. Une fois téléchargé, il faut activer l’intégration pour le(s) navigateur(s) en question.
Sous OpenBSD, les trois navigateurs web :
… sont disponibles.
⇒ L’onglet “Avancé” permet, entres autres, la prise en charge correcte de la communication entre KeePassXC et le navigateur web. Activez les cases à cocher suivantes :
/usr/local/bin/keepassxc-proxy
Dans les deux contextes, il existe d’autres options que vous pouvez activer ou non…
Cliquez sur l’icône “Agent SSH”, puis dans la partie droite de la fenêtre, cliquez sur la case à cocher [ ] Activer l’agent SSH (redémarrage nécessaire).
Cliquez sur l’icône `Intégration au Secret Service, puis dans la partie droite de la fenêtre cliquez sur la case à cocher [ ] Activer l’intégration de KeePassXC à Freedsktop.org Secret Service.
Une fois activée, les onglets Général et Autorisation sont accessibles.
⇒ L’onglet Général, outre les options diverses, donne un aperçu des bases de données KP visibles, sous le dénominateur Groupes de la base de données visibles :
Ce groupe contient trois colonnes :
⇒ L’onglet *Autorisation donne un aperçu des applications qui sont autorisées de communiquer avec la base de données.
Deux colonnes :
Les paramètres de la base de données sont accessibles par le menu Base de données > Paramètres de la base de données…
Deux onglets sont accessibles :
⇒ L’onglet Clé maître permet de gérer le mot de passe lié à la base de données en cours.
Un bouton [ Ajouter une protection supplémentaire… ], qui lorsqu’il est cliqué, donnera accès à la gestion :
⇒ L’onglet Paramètres de chiffrement permet le paramétrage d’un temps de déchiffrement de la base de données avant son possible accès, ainsi que de choisir le format de celle-ci.
Le menu Entrées visibles permet de rendre visible ou non les données qui sont dans la base de données.
Ce menu permet de gérer les “Paramètres de KeePassXC-Browser” sur la base de données, ainsi que les “Clés stockées”, relatives à la communication entre KeePassXC et votre client web, par le biais du module KeePassXC-Browser.
En bas, à gauche, de la fenêtre de KeePassXC, dans les paramètres de la base de données se trouve une case à cocher [ ] Paramètres avancés.
La cocher modifie l’apparence du menu Sécurité des paramètres de la base de données, et tout particulièrement dans l’onglet Paramètres de chiffrement qui permet ainsi de modifier plus finement certaines options, tel l’algorithme de chiffrement, la fonction de dérivation, le cycle de transformation, l’utilisation mémoire, et le nombre de processus.
Le générateur de mot de passe ou de passphrase est accessible par le menu Outils > Générateur de mot de passe.
Une fois ce module installé, et KeePassXC configuré pour communiquer avec navigateur web, cliquez sur l’icône du module pour gérer la communication avec KeePassXC. Celui-ci vous demandera la première fois de créer une clé de communication qui sera enregistrée dans les paramètres de la base de données de KeePassXC.
Il semble y avoir un souci empêchant le bon fonctionnement de communication
entre le module KeePassXC-Browser et KeePassXC si votre session utilise
ck-launch
.
Modifiez votre fichier personnel .xsession
pour redémarrer votre session
sans !
KeePassXC-Browser n’est pas configuré. Appuyez sur le bouton Connecter pour se connecter à KeePassXC. : ce message est affiché lors du premier usage du module. Cliquez sur le bouton [ Connecter ] pour créer une association de touches.
Échec du chiffrement du message. KeePassXC est-il lancé ? : Vérifiez que le logiciel KeePassXC soit activé !
Impossible de se connecter à KeePassXC. Vérifiez que l’intégration au navigateur soit activée dans les paramètres de KeePassXC. signifie que le module KeePassXC-Browser ne peut se connecter à la base de données KeePassXC.
L’échange de clé a échoué. : l’échange de la clé de communication entre le module KeePassXC-Browser et KeePassXC n’arrive pas à se faire.
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
OpenBSD intègre par défaut dans le système de base, depuis 5.7, le serveur de relais nommé relayd.
Site web : https://bsd.plumbing/
OpenBSD : 6.6, 6.7
Le but de cet article est de savoir comment mettre en place une journalisation du flux HTTP(S) qui passe au-travers de relayd.
C’est très simple !
/etc/relayd.conf
Dans un premier temps, nous devons déclarer le paramètre global log
dans
le fichier de configuration de relayd.
relayd.conf(5)#log
Les déclarations de journal suivantes ont pour signification les suivantes :
log state changes
ou log host checks
sont utiles pour suivre l’état
de l’hôte ou les contrôles effectués dessus.
up
si l’état de santé de l’hôte est positifdown
si celui est arrété ou si les contrôles ne sont pas bons.unknown
si l’hôte est désactivé ou n’a pas encore été
contrôlé.log connection
nous permet de journaliser les connexions TCP, si relayd
est configuré en tant que relai(s) 1
.
À noter l’ajout de l’option errors
pour le cas où nous voulons journaliser
que les erreurs de connexions TCP.1 En effet, relayd peut aussi être configuré en tant que routeur ou serveur de redirection.
Toujours dans le contexte du fichier de configuration de relayd, les relais ont la possibilité de filtrer les connexions par le biais de paramètres de filtrage spécifiques.
Ainsi nous utiliserons l’action de correspondance match
sur laquelle
nous appliquons l’option de journalisation log
.
relayd.conf(5)#match
Cette action de correspondance s’appliquera sur un type d’action ;
actuellement, 5 types d’actions sont définies :
cookie
: une action qui a lieu sur un cookie. 2
relayd.conf(5)#cookie
header
: une action ciblant le protocol d’entête HTTP - les fameuses headers
relayd.conf(5)#header
path
: une action qui analyse le chemin de l’URL demandée. 2
relayd.conf(5)#path
query
: une action pour chercher la partie query de l’URL demandée. 2
relayd.conf(5)#query
url
: l’action récupérant l’URL complète… 2
relayd.conf(5)#url
2 seulement disponible sur une requête HTTP.
L’exemple ci-dessous nous montre cinq règles de filtrage :
Fichier : /etc/relayd.conf
|
|
Là encore, tout simplement, une fois la configuration établie, validée, et le service relayd fonctionnel, les différents journaux se retrouvent principalement dans :
/var/log/daemon
,/var/log/message
.Code : sh
$ grep relayd /var/log/daemon
May 17 16:37:21 sh1 relayd[25237]: relay www, session 13 (2 active), 0, 192.168.1.1 -> :80, done
May 17 16:37:21 sh1 relayd[45869]: relay www, session 7 (2 active), 0, 192.168.1.1 -> :80, done
May 17 16:37:21 sh1 relayd[45869]: relay www, session 8 (1 active), 0, 192.168.1.1 -> :80, done
May 17 16:37:22 sh1 relayd[25237]: relay www, session 14 (1 active), 0, 192.168.1.1 -> :80, done
May 17 17:01:19 sh1 relayd[45869]: relay www, session 9 (1 active), 0, 207.180.140.98 -> :80, Forbidden (403 Forbidden), [<em>Stop scanning for PHP: none</em>!, User-Agent: polaris] GET: Invalid argument
May 17 17:01:19 sh1 relayd[45869]: relay www, session 10 (1 active), 0, 207.180.140.98 -> :80, done
May 17 17:02:43 sh1 relayd[7531]: relay www, session 13 (1 active), 0, 84.161.80.36 -> :80, Forbidden (403 Forbidden), [<em>Stop scanning for an admin interface: none</em>!, Host: 88.136.16.221] [<em>Stop scanning for an admin interface: none</em>!, User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36] [<em>Stop scanning for an admin interface: none</em>!, 88.136.16.221/phpmyadmin/] GET: Invalid argument
Cet exemple nous restitue :
done
block
- non expliquées iciCode : sh
$ grep relayd /var/log/messages
May 17 16:22:23 sh1 relayd[7531]: relay www, session 11 (1 active), 0, 37.49.230.25 -> :80, Forbidden (403 Forbidden), [<em>Stop scanning for PHP: none</em>!, User-Agent: Uirusu/2.0] GET: Invalid argument
May 17 17:01:19 sh1 relayd[45869]: relay www, session 9 (1 active), 0, 207.180.140.98 -> :80, Forbidden (403 Forbidden), [<em>Stop scanning for PHP: none</em>!, User-Agent: polaris] GET: Invalid argument
May 17 17:02:43 sh1 relayd[7531]: relay www, session 13 (1 active), 0, 84.161.80.36 -> :80, Forbidden (403 Forbidden), [<em>Stop scanning for an admin interface: none</em>!, Host: 88.136.16.221] [<em>Stop scanning for an admin interface: none</em>!, User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36] [<em>Stop scanning for an admin interface: none</em>!, 88.136.16.221/phpmyadmin/] GET: Invalid argument
Cet exemple nous montre 3 écritures de journalisation de règles bloquantes, provoquant une erreur 403, sur des critères de filtrage non expliqués ici.
Ici, il n’est pas question d’installation, mais juste de l’aperçu du retour
de dmesg
de ce mini-pc fourni par OVH, nommé “Over The Box V2A”.
OpenBSD 6.8 (GENERIC.MP) #98: Sun Oct 4 18:13:26 MDT 2020
deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 2036154368 (1941MB)
avail mem = 1959460864 (1868MB)
random: good seed from bootblocks
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 3.0 @ 0x7b8f3000 (51 entries)
bios0: vendor American Megatrends Inc. version "5.11" date 12/04/2017
bios0: OVH SAS Over TheBox V2A
acpi0 at bios0: ACPI 5.0
acpi0: sleep states S0 S4 S5
acpi0: tables DSDT FACP APIC FPDT FIDT MCFG SSDT SSDT SSDT UEFI SSDT HPET SSDT SSDT SSDT LPIT BCFG PRAM BGRT CSRT WDAT
acpi0: wakeup devices XHC1(S4)
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Atom(TM) x5-Z8350 CPU @ 1.44GHz, 1440.28 MHz, 06-4c-04
cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,RDRAND,NXE,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,TSC_ADJUST,SMEP,ERMS,MD_CLEAR,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu0: 1MB 64b/line 16-way L2 cache
cpu0: smt 0, core 0, package 0
mtrr: Pentium Pro MTRR support, 8 var ranges, 88 fixed ranges
cpu0: apic clock running at 79MHz
cpu0: mwait min=64, max=64, C-substates=0.2.0.0.0.0.3.3, IBE
cpu1 at mainbus0: apid 2 (application processor)
cpu1: Intel(R) Atom(TM) x5-Z8350 CPU @ 1.44GHz, 1439.96 MHz, 06-4c-04
cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,RDRAND,NXE,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,TSC_ADJUST,SMEP,ERMS,MD_CLEAR,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu1: 1MB 64b/line 16-way L2 cache
cpu1: smt 0, core 1, package 0
cpu2 at mainbus0: apid 4 (application processor)
cpu2: Intel(R) Atom(TM) x5-Z8350 CPU @ 1.44GHz, 1439.97 MHz, 06-4c-04
cpu2: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,RDRAND,NXE,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,TSC_ADJUST,SMEP,ERMS,MD_CLEAR,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu2: 1MB 64b/line 16-way L2 cache
cpu2: smt 0, core 2, package 0
cpu3 at mainbus0: apid 6 (application processor)
cpu3: Intel(R) Atom(TM) x5-Z8350 CPU @ 1.44GHz, 1439.97 MHz, 06-4c-04
cpu3: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,CX16,xTPR,PDCM,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,RDRAND,NXE,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,TSC_ADJUST,SMEP,ERMS,MD_CLEAR,IBRS,IBPB,STIBP,SENSOR,ARAT,MELTDOWN
cpu3: 1MB 64b/line 16-way L2 cache
cpu3: smt 0, core 3, package 0
ioapic0 at mainbus0: apid 1 pa 0xfec00000, version 20, 115 pins
acpimcfg0 at acpi0
acpimcfg0: addr 0xe0000000, bus 0-255
acpihpet0 at acpi0: 14318179 Hz
acpiprt0 at acpi0: bus 0 (PCI0)
acpiprt1 at acpi0: bus 1 (RP01)
acpiprt2 at acpi0: bus -1 (RP02)
acpiprt3 at acpi0: bus -1 (RP03)
acpiprt4 at acpi0: bus -1 (RP04)
"INT33A4" at acpi0 not configured
chvgpio0 at acpi0 GPO1 uid 2 addr 0xfed88000/0x8000 irq 48, 59 pins
chvgpio1 at acpi0 GPO3 uid 4 addr 0xfed98000/0x8000 irq 91, 55 pins
chvgpio2 at acpi0 GPO2 uid 3 addr 0xfed90000/0x8000 irq 50, 24 pins
chvgpio3 at acpi0 GPO0 uid 1 addr 0xfed80000/0x8000 irq 49, 56 pins
dwiic0 at acpi0 I2C7 addr 0x91728000/0x1000 irq 38
iic0 at dwiic0
"INT33F4" at iic0 addr 0x34 not configured
acpipci0 at acpi0 PCI0: 0x00000000 0x00000011 0x00000001
"TXE8086" at acpi0 not configured
"INT3496" at acpi0 not configured
sdhc0 at acpi0 SDHB addr 0x9173a000/0x1000 irq 46
sdhc0: SDHC 3.0, 200 MHz base clock
sdmmc0 at sdhc0: 4-bit, sd high-speed, mmc high-speed, ddr52, dma
"RTL8723" at acpi0 not configured
sdhc1 at acpi0 SDHC addr 0x91738000/0x1000 irq 47, gpio
sdhc1: SDHC 3.0, 200 MHz base clock
sdmmc1 at sdhc1: 4-bit, sd high-speed, mmc high-speed, ddr52, dma
"80862286" at acpi0 not configured
"808622C0" at acpi0 not configured
"80862288" at acpi0 not configured
"80862289" at acpi0 not configured
"8086228A" at acpi0 not configured
"8086228A" at acpi0 not configured
"JEHE8888" at acpi0 not configured
"8086228E" at acpi0 not configured
"8086228E" at acpi0 not configured
"8086228E" at acpi0 not configured
dwiic1 at acpi0 I2C1 addr 0x91734000/0x1000 irq 32
iic1 at dwiic1
"TXN27501" at iic1 addr 0x6b not configured
"TXN24292" at iic1 addr 0x55 not configured
dwiic2 at acpi0 I2C2 addr 0x91732000/0x1000 irq 33
iic2 at dwiic2
"10EC5670" at iic2 addr 0x1c not configured
"INTCF1D" at acpi0 not configured
"JAHC2333" at acpi0 not configured
"JAHC8563" at acpi0 not configured
dwiic3 at acpi0 I2C4 addr 0x9172e000/0x1000 irq 35
iic3 at dwiic3
dwiic4 at acpi0 I2C5 addr 0x9172c000/0x1000 irq 36
iic4 at dwiic4
dwiic5 at acpi0 I2C6 addr 0x9172a000/0x1000 irq 37
iic5 at dwiic5
"808622A8" at acpi0 not configured
"ADMA22A8" at acpi0 not configured
"TIMC22A8" at acpi0 not configured
"HAD022A8" at acpi0 not configured
acpihid0 at acpi0: HIDDacpihid0: exec of HEBC failed
acpihid0: exec of HEBC failed
acpicmos0 at acpi0
"JEHE2333" at acpi0 not configured
acpibtn0 at acpi0: PWRB
chvgpio4 at acpi0 GPO4 uid 5
"8086229C" at acpi0 not configured
"INTCFD9" at acpi0 not configured
"INT33BD" at acpi0 not configured
"ACPI000C" at acpi0 not configured
"INT3400" at acpi0 not configured
"INT3403" at acpi0 not configured
"INT3403" at acpi0 not configured
"INT3406" at acpi0 not configured
"INT3403" at acpi0 not configured
acpicpu0 at acpi0: C3(10@1000 mwait.1@0x64), C2(10@500 mwait.1@0x58), C1(1000@1 mwait.1), PSS
acpicpu1 at acpi0: C3(10@1000 mwait.1@0x64), C2(10@500 mwait.1@0x58), C1(1000@1 mwait.1), PSS
acpicpu2 at acpi0: C3(10@1000 mwait.1@0x64), C2(10@500 mwait.1@0x58), C1(1000@1 mwait.1), PSS
acpicpu3 at acpi0: C3(10@1000 mwait.1@0x64), C2(10@500 mwait.1@0x58), C1(1000@1 mwait.1), PSS
acpipwrres0 at acpi0: ID3C, resource for ISP3
acpipwrres1 at acpi0: WWPR, resource for HS03, MDM1
acpipwrres2 at acpi0: WWPR, resource for HS13, MDM1
acpipwrres3 at acpi0: WWPR, resource for SSC1, MDM3
acpipwrres4 at acpi0: WWPR, resource for SSCW, MDM3
acpipwrres5 at acpi0: WWPR, resource for HSC1, MDM2
acpipwrres6 at acpi0: WWPR, resource for HSC3, MDM4
acpipwrres7 at acpi0: CLK3, resource for RTEK, RTK1
acpipwrres8 at acpi0: CLK4
acpipwrres9 at acpi0: CLK2, resource for NFC2
acpipwrres10 at acpi0: CLK1
acpipwrres11 at acpi0: CLK0
acpipwrres12 at acpi0: CLK1
acpipwrres13 at acpi0: USBC, resource for XHC1, OTG1
acpipwrres14 at acpi0: P28X
acpipwrres15 at acpi0: P18X
acpipwrres16 at acpi0: P12X
acpipwrres17 at acpi0: P28P
acpipwrres18 at acpi0: P18P
acpipwrres19 at acpi0: P19X
acpipwrres20 at acpi0: P06X
acpipwrres21 at acpi0: P12A
acpipwrres22 at acpi0: P28T
acpipwrres23 at acpi0: P18D
acpipwrres24 at acpi0: P18T
acpipwrres25 at acpi0: P3P3
acpipwrres26 at acpi0: P12T
acpipwrres27 at acpi0: P28W
acpipwrres28 at acpi0: P18W
acpipwrres29 at acpi0: P12W
acpipwrres30 at acpi0: P33W
acpipwrres31 at acpi0: P33X
acpipwrres32 at acpi0: P4BW
acpitz0 at acpi0: critical temperature is 90 degC
acpivideo0 at acpi0: GFX0
acpivout0 at acpivideo0: DD01
acpivout1 at acpivideo0: DD02
acpivout2 at acpivideo0: DD03
acpivout3 at acpivideo0: DD04
acpivout4 at acpivideo0: DD05
acpivout5 at acpivideo0: DD06
acpivout6 at acpivideo0: DD07
acpivout7 at acpivideo0: DD08
cpu0: using VERW MDS workaround
cpu0: Enhanced SpeedStep 1440 MHz: speeds: 1920, 1840, 1760, 1680, 1600, 1520, 1440, 1360, 1280, 1200, 1120, 1040, 960, 880, 800, 720, 640, 560, 480 MHz
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel Braswell Host" rev 0x36
inteldrm0 at pci0 dev 2 function 0 "Intel HD Graphics" rev 0x36
drm0 at inteldrm0
inteldrm0: msi, CHERRYVIEW, gen 8
"Intel Braswell Power" rev 0x36 at pci0 dev 11 function 0 not configured
sdhc2 at pci0 dev 16 function 0 vendor "Intel", unknown product 0x2294 rev 0x36: apic 1 int 16
sdhc2: SDHC 3.0, 200 MHz base clock
sdmmc2 at sdhc2: 8-bit, sd high-speed, mmc high-speed, ddr52, dma
xhci0 at pci0 dev 20 function 0 "Intel Braswell xHCI" rev 0x36: msi, xHCI 1.0
usb0 at xhci0: USB revision 3.0
uhub0 at usb0 configuration 1 interface 0 "Intel xHCI root hub" rev 3.00/1.00 addr 1
"Intel Braswell USB OTG" rev 0x36 at pci0 dev 22 function 0 not configured
"Intel Braswell TXE" rev 0x36 at pci0 dev 26 function 0 not configured
ppb0 at pci0 dev 28 function 0 "Intel Braswell PCIE" rev 0x36: msi
pci1 at ppb0 bus 1
re0 at pci1 dev 0 function 0 "Realtek 8168" rev 0x07: RTL8168E/8111E-VL (0x2c80), msi, address 24:1c:04:08:8c:05
rgephy0 at re0 phy 7: RTL8169S/8110S/8211 PHY, rev. 5
pcib0 at pci0 dev 31 function 0 "Intel Braswell PCU LPC" rev 0x36
isa0 at pcib0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com1 at isa0 port 0x2f8/8 irq 3: ns8250, no fifo
com2 at isa0 port 0x3e8/8 irq 5: ns8250, no fifo
pckbc0 at isa0 port 0x60/5 irq 1 irq 12
pckbd0 at pckbc0 (kbd slot)
wskbd0 at pckbd0: console keyboard
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
vmm0 at mainbus0: VMX/EPT (using slow L1TF mitigation)
efifb at mainbus0 not configured
sdmmc0: can't enable card
sdmmc1: can't enable card
scsibus1 at sdmmc2: 2 targets, initiator 0
sd0 at scsibus1 targ 1 lun 0: <Samsung, 8GME4R, 0000> removable
sd0: 7456MB, 512 bytes/sector, 15269888 sectors
umass0 at uhub0 port 2 configuration 1 interface 0 "ASMedia AS2115" rev 2.10/0.01 addr 2
umass0: using SCSI over Bulk-Only
scsibus2 at umass0: 2 targets, initiator 0
sd1 at scsibus2 targ 1 lun 0: <ASMT, 2115, 0> serial.174c1153000000000000
sd1: 122104MB, 512 bytes/sector, 250069680 sectors
uhub1 at uhub0 port 4 configuration 1 interface 0 "Genesys Logic USB2.0 Hub" rev 2.00/85.36 addr 3
vscsi0 at root
scsibus3 at vscsi0: 256 targets
softraid0 at root
scsibus4 at softraid0: 256 targets
root on sd0a (2f18100544c5d963.a) swap on sd0b dump on sd0b
inteldrm0: 1024x768, 32bpp
wsdisplay0 at inteldrm0 mux 1: console (std, vt100 emulation), using wskbd0
wsdisplay0: screen 1-5 added (std, vt100 emulation)
$ sysctl hw.sensors
hw.sensors.cpu0.temp0=43.00 degC
hw.sensors.acpitz0.temp0=0.00 degC (zone temperature)
Dino est un client de communication chat moderne et open-source, sous X. Il se concentre sur le fait de fournir une expérience propre et fiable Jabber/XMPP tout en gardant à l’esprit votre confidentialité.
Dino est sécurisé par défaut : vos communications sont toujours chiffrées. Une fois que vous avez activé le chiffrement de bout à bout via OMEMO ou OpenPGP, seuls vous et vos correspondants peuvent lire vos messages, pas même un administrateur de serveurs.
Disponible : à partir d’OpenBSD 6.7
installez
le
paquet dino
.
La première chose que demande Dino est sa configuration. Un clic sur le gros bouton rouge [ Configurer le compte ] permet soit de configurer un nouveau compte XMPP, soit de se connecter à un compte existant.
Une fenêtre titrée “Ajouter un compte” s’ouvre, et vous demande un JID - un Identifiant Jabber.
La fenêtre est très minimaliste. Les menus sont situés dans le haut de la fenêtre sous forme de symbole.
En haut à gauche :
+
: permet de choisir les menus Commencer une conversation et
Rejoindre un salonEn haut à droite :
(à suivre)
⇒ Articles :
J’ai écrit historiquement de manière collaborative cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
OpenBSD intègre par défaut dans le système de base, depuis 5.7 :
un serveur web, nommé httpd - que j’ai présenté plus ou moins succinctement ici
un serveur relay, nommé relayd
Site web : https://bsd.plumbing/
OpenBSD : 6.6, 6.7
Le problème est que le serveur httpd n’est pas capable de gérer la mise en cache de contenu statique.
Nous passons donc le relais au serveur relayd qui lui en est capable - par contre, il le fait de manière globale, çad non spécifique à un domaine en particulier -
Les explications de configuration du serveur httpd ont été abordés sur cet autre article : Relayd : Gestion des entêtes pour httpd (cf : l'exemple de configuration )
C’est exactement le même principe.
/etc/relayd.conf
, par défaut.Dans le contexte du protocole http, en lui donnant un nom - le nom importe peu, mais est réutilisé plus tard, dans le contexte des déclarations de relais :
tag
.
Là, encore le nom donné importe peu pourvu que vous réutilisiez le même
dans le cadre de l’entête header
de réponse.Cache-Control
ciblant l’étiquette.Puis nous appliquons le protocole http déclaré a un relay cible.
Code : relayd
ip4 = "public-address-ipv4"
http protocol "hw" {
match request path "/*.atom" tag "CACHE"
match request path "/*.css" tag "CACHE"
match request path "/*.gif" tag "CACHE"
match request path "/*.html" tag "CACHE"
match request path "/*.ico" tag "CACHE"
match request path "/*.jpg" tag "CACHE"
match request path "/*.js" tag "CACHE"
match request path "/*.png" tag "CACHE"
match request path "/*.rss" tag "CACHE"
match request path "/*.svg" tag "CACHE"
match request path "/*.xml" tag "CACHE"
match response tagged "CACHE" header set "Cache-Control" value "public, max-age=86400"
tcp { nodelay, sack, socket buffer 65536, backlog 100 }
pass
}
relay "www" {
listen on $ip4 port 80
protocol hw
forward to 127.0.0.1 port 80
}
OpenBSD intègre par défaut dans le système de base, depuis 5.7 :
un serveur web, nommé httpd - que j’ai présenté plus ou moins succinctement ici
un serveur relay, nommé relayd
Site web : https://bsd.plumbing/
OpenBSD : 6.6, 6.7
Le problème est que le serveur httpd n’est pas capable de gérer les entêtes HTTP (en anglais : header ), et que l’auteur ne le veut pas.
Nous passons donc le relais au serveur relayd qui lui est capable de les gérer - par contre, il le fait de manière globale, çad non spécifique à un domaine en particulier -
Étant donné que relayd est en frontal d’httpd, nous allons modifier la configuration des deux fichiers de configuration relatifs.
Ne pas oublier de redémarrer les services correspondants après modifier de la configuration !
/etc/httpd.conf
, par défaut.Dans le contexte server
, il y a deux, trois modifications importantes à
faire :
listen on
doit écouter localhost - cf : listen onlog
est à modifier pour que le style
soit
paramétré sur forwarder
- cf : styleSeule l’entête HSTS est géré différement :
L’entête HSTS se modifie, non pas en déclarant une entête, comme pour les
autres, mais en utilisant tout simplement l’option hsts
(cf : hsts).
Elle se gère bien sûr dans le contexte de protocole HTTPS , via TLS .
Pour l’instant, nous n’aborderons pas ce sujet ; d’autant que je fais les présentations dans mon article de présentation d'httpd .
Code : httpd
server "domain.tld" {
listen on 127.0.0.1 port 80
listen on ::1 port 80
# enable hsts only if you use TLS for HTTPS
hsts {
max-age 63072000
preload
subdomains
}
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
location "/" {
directory index index.html
}
log {
access "domain.tld/access.log"
error "domain.tld/errors.log"
style forwarded
}
root "/htdocs/domain.tld/www"
}
Voici un exemple de log :
domain.tld 127.0.0.1 - - [06/May/2020:04:08:51 +0200] "GET / HTTP/1.1" 200 0 "" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" 66.249.79.202 -
domain.tld 127.0.0.1 - - [06/May/2020:09:48:36 +0200] "GET /robots.txt HTTP/1.1" 200 0 "" "Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)" 5.196.87.174 -
domain.tld 127.0.0.1 - - [06/May/2020:10:29:29 +0200] "GET / HTTP/1.1" 200 0 "" "Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)" 54.36.148.31 -
Nous remarquons bien que l’adresse IP du client est précisé en fin de ligne.
C’est ce que permet le paramètre de style de journal forwarder
.
/etc/relayd.conf
, par défaut.Dans les faits :
match
pour créer les réponses d’entêtes header
.
$SERVER_ADDR:$SERVER_PORT
pour l’option X-Forwarded-By
,$REMOTE_ADDR
pour l’option X-Forwarded-For
.relay
correspondantes :
listen
, sur l’adresse IP public et le port www et,forward
vers l’interface de bouclage
local, et le port désiré, correspondant à celui sur lequel écoute
httpd.Certains des plus attentifs remarqueront dans l’exemple ci-dessous la déclaration de l’entête suivante :
match request header remove "Proxy"
Celle-ci est utile pour lutter contre la faille Httpoxy qui affecte les applications CGI, PHP, dans le contexte d’une connexion HTTP .
C’est reconnue comme étant la meilleure façon de bloquer cette faille. L’autre angle de protection efficace est de fournir des connexions HTTPS , qui apparemment ne sont pas assujetties à cette faille.
Code : relayd
ip4 = "ipv4_public_address"
ip6 = "ipv6_public_address"
http protocol "hw" {
match request header set "X-Forwarded-By" value "$SERVER_ADDR:$SERVER_PORT"
match request header set "X-Forwarded-For" value "$REMOTE_ADDR"
match request header remove "Proxy"
match response header set "Cache-Control" value "max-age=1814400"
match response header set "Content-Security-Policy" value "upgrade-insecure-requests; default-src https: 'self'"
match response header set "Permissions-Policy" value "fullscreen=(), geolocation=(), microphone()"
match response header set "Frame-Options" value "SAMEORIGIN"
match response header set "Referrer-Policy" value "strict-origin"
match response header set "Server" value "OpenBSD Relayd+httpd"
match response header set "X-Content-Type-Options" value "nosniff"
match response header set "X-Download-Options" value "noopen"
match response header set "X-Frame-Options" value "SAMEORIGIN"
match response header set "X-Powered-By" value "!"
match response header set "X-Robots-Tag" value "index, nofollow"
match response header set "X-Xss-Protection" value "1; mode=block"
tcp { nodelay, sack, socket buffer 65536, backlog 100 }
pass
}
relay "www" {
listen on $ip4 port 80
protocol hw
forward to 127.0.0.1 port 80
}
relay "www6" {
listen on $ip6 port 80
protocol hw
forward to ::1 port 80
}
Pour en savoir plus sur les entêtes :
Pour information, Xavier Cartron @prx propose une autre méthode - personnellement testé, non réussie.
ou la page du wiki de la communauté “OpenBSD Pour Tous” : "HTTPd : Comment gérer les entêtes HTTP"
Voici un exemple très complet, avec gestion TLS - en anglais
OpenSMTPD est une libre implémentation du protocole SMTP tel que défini dans la RFC 5321 , avec quelques extensions standards additionnels. Il permet à des machines ordinaire d’échanger des mails avec d’autres systèmes parlant le protocole SMTP.
OpenSMTPD fait partie du système de base du système d’exploitation OpenBSD. Il a été “porté” sur d’autres OS, tel Devuan.
Informations :
Q : Pourquoi utiliser OpenSMTPD ?
Parce qu’OpenSMTPD est :
Fonctionnel et testé sur :
apt install opensmtpd
/var/log/mail.log
/etc/smtpd.conf
Pour envoyer un mail par SMTP à un service de mails nécessitant une
identification, il est nécessaire de créer dans un premier temps, un
fichier secrets
avec les droits adéquats sur votre système, ensuite
il nous reste à configurer le fichier smtpd.conf
.
Création du fichier de secrets :
$ mkdir -p .config/mail
$ touch .config/mail/secrets
$ chmod 0640 .config/mail/secrets
Ensuite, il est nécessaire de le remplir de telle manière :
identifiant username:password
n'écrivez pas TEXTUELLEMENT cette information
,
remplacez-là par les informations ci-dessous :
identifiant
est l’identifiant que vous choisissez soigneusement,
et qui vous servira plus tard dans la configuration du fichier
smtpd.conf
;username
est votre identifiant de connexion mail au service mail de
votre fournisseur - généralement votre adresse mail - ;password
étant le mot de passe lié à votre identification mail.Il est possible de nommer autrement ce fichier secrets, et de le mettre ailleurs dans votre système de fichier ; comprenez-le principe et modifier en conséquence.
De même, je vous encourage fortement à ne mettre QUE des droits 0440 sur le fichier - par défaut : 0640.
Même si l’accès au fichier par smtpd peut sans soucis être fait avec vos
droits personnels $USER:$USER
, il est préférable de mettre à minima les
droits du groupe opensmtpd
.
# chown $USER:opensmtpd .config/mail/secrets
$ chmod 0440 .config/mail/secrets
Note à-propos d’un home chiffré : veillez absolument à copier/déplacer ce fichier vers /etc/mail/, autrement le service correspondant ne démarrera pas, puisqu’il ne peut/pourra pas avoir accès au fichier à ce moment-là !
Maintenant modifions le fichier /etc/smtpd.conf
# $OpenBSD: smtpd.conf,v 1.10 2018/05/24 11:40:17 gilles Exp $
# This is the smtpd server system-wide configuration file.
# See smtpd.conf(5) for more information.
table aliases file:/etc/aliases
table secrets file:/home/votre-id/.config/mail/secrets
queue compression
# To accept external mail, replace with: listen on all
listen on localhost
action "local" maildir alias <aliases>
action "relay" relay host smtp+tls://identifiant@serveur:587 auth <secrets> mail-from "@your-domain.tld"
# Uncomment the following to accept external mail for domain "example.org"
#
# match from any for domain "example.org" action "local"
match for local action "local"
match from local for any action "relay"
Explications
Par rapport à la version originale, nous avons donc rajouté :
table secrets
qui appelle le fichier .config/mail/secrets
-
ou son équivalent, si vous l’avez personnalisé…action relay
qui nous permet de définir l’action nécessaire
vers l’hôte relais par lequel nous enverrons les mails…
identifiant@serveur
:
identifiant
par celle que vous avez créée dans votre fichier secrets
.serveur
, il faut la remplacer par l’adresse
du serveur de mail, par exemple :
mail.gandi.net
.smtp+tls
est le protocol que nous utilisons pour nous
connecter au service de l’hôte mail relais…
il est bien sûr possible d’utiliser les autres protocoles, tel
que :
lmtp
pour se connecter avec une session
LMTP
.smtp
pour essayer de se connecter avec une session STARTTLS
si possiblesmtp+tls
pour obliger une connexion par le biais d’une
session STARTTLS.smtp+notls
pour se connecter “en clair”, sans chiffrementsmtps
pour se connecter en forçant la connexion
TLS
auth
permet de spécifier la table secrets
fournissant
les données d’identification mail nécessaires.mail-from
nous permet de spécifier le nom de domaine -
ce qui permet d’éviter l’erreur
Sender address rejected: Domain not found
;
il faut bien sûr que ce domaine vous appartienne…match … action "relay"
est l’action qui sera déclenchée
lors de l’envoi de mails à l’extérieur !Un mot sur la gestion des alias système !
Il est intéressant de gérer l’alias relatif à votre compte root
voire
celui de votre utilisateur principal…
Éditez le fichier /etc/aliases
, avec des droits administrateurs.
Vers la fin du fichier, modifiez root
en lui indiquant vers quelle
adresse mail vous désirez que les messages systèmes adressés au compte
root vous soit envoyés !
Faites de même pour votre utilisateur système ;)
N’oubliez pas de recharger la base des aliases, grâce à l’usage de la
commande newaliases
!
Avant de redémarrer le service opensmtpd pour qu’il prenne en compte
les modifications faites, il nous faut tester l’écriture de la
configuration : # smtpd -n
qui devrait réponde par : configuration OK
informant ainsi que tout va bien…
Sinon, rééditez le fichier de configuration à la ligne indiquée en premier ; c’est d’elle que vient l’erreur principale !
Il est nécessaire de redémarrer le service :
# service opensmtpd restart
, ou
# /etc/init.d/opensmtpd restart
- si vous utilisez openrc en tant
que gestionnaire de service !
Soit :
echo "Test d'envois de mail on $(hostname); date: $(date)" | mail -s "Test de mail" adresse_mail_à_qui_envoyer
echo "Test d'envois de mail on $(hostname); date: $(date)" | mail -s "Test de mail" root
Dans un cas, comme dans l’autre, le journal vous indiquera l’équivalent, en cas de réussite, d’un tel message :
(…)
Apr 27 09:16:47 pc-z smtpd[1718]: 09cca279ca1178e4 smtp connected address=local host=***
Apr 27 09:16:47 pc-z smtpd[1718]: 09cca279ca1178e4 smtp message msgid=85868a25 size=474 nrcpt=1 proto=ESMTP
Apr 27 09:16:47 pc-z smtpd[1718]: 09cca279ca1178e4 smtp envelope evpid=85868a25fcb1569a from=<my-id@***> to=<my-id@***>
Apr 27 09:16:47 pc-z smtpd[1718]: 09cca279ca1178e4 smtp disconnected reason=quit
Apr 27 09:16:51 pc-z smtpd[1718]: 09cca27892fa38ea mta delivery evpid=85868a25fcb1569a from=<my-id@huc.fr.eu.org> to=<email@nom-de-domaine.tld> rcpt=<my-id@***> source="192.168.47.47" relay="80.67.160.70 (lautre.net)" delay=4s result="Ok" stat="250 2.0.0 Ok: queued as 53C92112839"
Apr 27 09:17:02 pc-z smtpd[1718]: 09cca27892fa38ea mta disconnected reason=quit messages=2
(…)
À partir de maintenant, vous pourrez envoyer depuis votre console ou vos scripts shell des mails avec authentification SMTP !
Retrouvez les différentes erreurs possibles sur mon article OpenBSD : Configurer smtpd.conf pour l'authentification (depuis OpenBSD 6.4 & ≥)
Le protocol SMTP est défini par la RFC 5321 :
OpenNTPD est un service qui peut être utilisé pour synchroniser l’horloge système depuis les serveurs de temps, utilisant le protocole NTP .
OpenNTPD fait partie du système de base du système d’exploitation OpenBSD. Il a été “porté” sur d’autres OS, tel Devuan.
Par le biais de l’outil apt
: apt install openntpd
/etc/opennptd/ntpd.conf
Par défaut, il est paramétré pour fonctionner, sans aucune modification nécessaire.
Fichier : /etc/opennptd/ntpd.conf
|
|
Explications
À-propos des options :
server
permet de cibler un serveur de temps, en particulierservers
permet de cibler un ensemble de serveur de temps - préférez cet usagesensor
permet d’utiliser les sondes de temps localesPour vérifier que la configuration soit bonne, il faut utiliser l’option
-n
tel que :
# openntpd -n
configuration OK
Si la configuration du fichier n’est pas bonne, la commande vous avertira en conséquence ; à vous, de corriger le fichier de configuration si nécessaire.
L’utilitaire qui nous permet de contrôler le service de temps est ntpctl
.
-s all
- ou sa version abrégée : -sa
- permet d’afficher
les informations disponibles.Code : shell
# ntpctl -sa
4/4 peers valid, clock unsynced, clock offset is -552.476ms
peer
wt tl st next poll offset delay jitter
82.64.42.185 from pool 0.debian.pool.ntp.org
1 10 2 6s 32s 0.203ms 60.784ms 31.533ms
194.177.34.116 from pool 0.debian.pool.ntp.org
1 10 3 9s 32s 2.000ms 54.595ms 17.411ms
212.129.10.70 from pool 0.debian.pool.ntp.org
1 10 2 9s 33s 5.552ms 51.518ms 4.078ms
162.159.200.1 from pool 0.debian.pool.ntp.org
1 10 3 7s 33s -0.176ms 55.383ms 17.593ms
Le nom du service étant openntpd, il se gère avec l’outil service
,
sans soucis particulier.
service openntpd commande
commande
est bien sûr une des actions possibles sur un service, tel start
,
stop
, restart
par exemple.Il peut arriver au démarrage qu’il y ait un décalage de temps, plus ou moins conséquent.
L’usage de l’option -s
permettra de résoudre :
Code : shell
# openntpd -s -d
adjtimex returns frequency of 0.000000ppm
/var/lib/openntpd/db/ntpd.drift is empty
ntp engine ready
reply from 212.83.179.156: offset -522.890034 delay 0.054365, next query 7s
set local clock to Sat Apr 25 12:09:03 CEST 2020 (offset -522.890034s)
reply from 5.135.3.88: negative delay -522.825725s, next query 3203s
reply from 46.105.237.136: negative delay -522.823915s, next query 3197s
reply from 185.21.216.198: negative delay -522.821620s, next query 3012s
reply from 51.15.175.180: negative delay -522.821769s, next query 3010s
reply from 37.187.104.44: negative delay -522.820949s, next query 3031s
reply from 46.235.141.130: negative delay -522.816360s, next query 3274s
reply from 162.159.200.1: negative delay -522.816819s, next query 3030s
reply from 5.39.60.244: negative delay -522.816297s, next query 3254s
reply from 95.81.173.155: negative delay -522.812132s, next query 3176s
reply from 51.15.191.239: negative delay -522.810759s, next query 3017s
reply from 5.39.60.244: negative delay -522.809750s, next query 3082s
reply from 51.158.147.92: negative delay -522.805041s, next query 3250s
reply from 212.85.158.10: negative delay -522.800165s, next query 3041s
reply from 88.212.196.95: negative delay -522.784156s, next query 3179s
reply from 156.38.0.219: negative delay -522.657588s, next query 3023s
reply from 212.83.179.156: offset -0.004612 delay 0.049539, next query 7s
reply from 212.83.179.156: offset -0.007646 delay 0.049241, next query 9s
peer 212.83.179.156 now valid
Apparemment l’option de contrainte constraints
bien appréciée sous OpenBSD
n’est pas utilisable !
Il peut arriver lorsque vous utilisez le contrôleur ntp, il vous soit notifié qu’un ou plusieurs des pairs soi(en)t non valides, tel que par exemple :
Code : shell
wt tl st next poll offset delay jitter
95.81.173.8 from pool 0.debian.pool.ntp.org
1 4 2 8s 9s ---- peer not valid ----
Patientez encore un peu que les retours des requêtes ntp se soient faites. Normalement lors de l’interrogation suivante, cela ne devrait plus être le cas.
Autrement, vérifiez que les serveurs NTP enregistrés dans le fichier de configuration soient bien écrits, joignables et fonctionnels.
Le protocol NTP est défini dans la version :
Du fait que les outils viennent de l’univers OpenBSD, je vous renvoie aux manpages compétents correspondants :
Opensearch est un format de description qui permet à un site de décrire un moteur de recherche pour lui-même, afin que toute application cliente, tel un navigateur web, puisse faire une recherche dans le site en question.
La plupart des navigateurs vous proposeront l’ajout de votre site en tant que moteur de recherche si vous gérez l’autopublication .
Hugo, par défaut, ne génére pas de descriptif Opensearch. Nous allons devoir modifier la configuration pour créer un nouveau format de sortie personnalisé.
Un petit tour sur la documentation officielle Hugo :
Ainsi que sur la documentation officielle d’Opensearch :
config.toml
Il est nécessaire de modifier le fichier de configuration pour :
Le type mime lié au format de description d’Opensearch est : application/opensearchdescription+xml
.
Depuis Hugo 0.20, il faut ajouter :
[mediaTypes]
[mediaTypes."application/opensearchdescription+xml"]
suffix = "xml"
Là, nous avons donc implémenté un nouveau type de format ayant pour mime type : application/opensearchdescription+xml
, et pour nom d’extension : xml
.
Depuis Hugo 0.44, pour que cela fonctionne correctement il faut ajouter :
[mediaTypes]
[mediaTypes."application/opensearchdescription+xml"]
suffixes = ["xml"]
suffix
en suffixes = ['xml']
!La déclaration du format de sortie, à ajouter :
[outputs]
[outputFormats.OpenSearch]
baseName = "opensearch"
isHTML = false
isPlainText = false
mediaType = "application/opensearchdescription+xml"
noUgly = true
Puis, il faut ajouter "OpenSearch"
à votre variable home
, tel que :
[outputs]
home = ["HTML", "OpenSearch"]
Le modèle peut simplement être créé dans le répertoire layouts/_default/index.opensearch.xml
.
{{ printf `<?xml version="1.0" encoding="utf-8" ?>` | safeHTML }}
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:ie="http://schemas.microsoft.com/Search/2008/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<Attribution>© {{ $.Date.Format "2006" | safeHTML }} {{ site.Author.name }}; http://creativecommons.org/publicdomain/zero/1.0/legalcode.{{ site.Language.Lang }}</Attribution>
<Contact>{{ site.Author.email | safeHTML }}</Contact>
<Description>{{ i18n "opensearchDescription" }}</Description>
<Developer>{{ site.Author.name | safeHTML }}</Developer>
<InputEncoding>utf-8</InputEncoding>
<Image width="64" height="64" type="image/png">{{ site.BaseURL }}img/Logo-64px.png</Image>
<Image width="16" height="16" type="image/vnd.microsoft.icon">{{ site.BaseURL }}img/favicon.ico</Image>
<Language>{{ site.LanguageCode }}</Language>
<LongName>{{ site.Title }} :: {{ site.Language.Lang }}</LongName>
<OutputEncoding>UTF-8</OutputEncoding>
<ShortName>Websearch</ShortName>
<SyndicationRight>open</SyndicationRight>
<ie:PreviewUrl type="text/html" method="GET" template="{{ site.BaseURL }}{{ site.Language.Lang }}/tags/{searchTerms}/"/>
<moz:SearchForm>{{ site.BaseURL }}{{ site.Language.Lang }}/tags/{searchTerms}/</moz:SearchForm>
<Url template="{{ site.BaseURL }}{{ site.Language.Lang }}/tags/{searchTerms}/" type="text/html" />
<Url rel="self" template="{{ site.BaseURL }}opensearch.xml" type="application/opensearchdescription+xml" />
</OpenSearchDescription>
L’autopublication est la méthode qui permet d’informer les clients web du format de description Opensearch.
title
corresponde à celle de
l’élément ShortName
!Si vous avez modifié votre configuration de Hugo pour générer un flux Atom il vous faudra le modifier pour ajouter ce qui suit :
<link href="{{ site.BaseURL }}/opensearch.xml" rel="search" type="application/opensearchdescription+xml" title="Websearch" />
Ajouter un élément link
, tel que :
<link rel="search" href="/opensearch.xml" title="Websearch" type="application/opensearchdescription+xml">
Si vous générez votre flux RSS , veillez à le modifier pour ajouter :
xmlns:atom="http://www.w3.org/2005/Atom"
dans votre élément rss
, tel que :<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
atom:link
, tel que :<atom:link href="{{ site.BaseURL }}/opensearch.xml" rel="search" type="application/opensearchdescription+xml" title="Websearch" />
Encore un merci sincère @solene qui m’a fait connaître Opensearch.
fswebcam est une une petite application simple de gestion de webcam. Elle peut capturer des images depuis différentes sources et effectuer des manipulations simples sur les images capturées. Les images peuvent être sauvegardées au format JPG ou PNG.
Installez
le paquet fswebcam
.
Il est nécessaire de capturer le périphérique vidéo ! [[tips:webcam|capturer le périphérique vidéo]]
Voici un exemple :
$ fswebcam -r 1280x960 --save "/tmp/webcam-$(date +%Y-%m-%d-%H-%M-%S).jpg"
--- Opening /dev/video0...
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
Adjusting resolution from 1280x960 to 960x720.
--- Capturing frame...
Captured frame in 0.00 seconds.
--- Processing captured image...
Writing JPEG image to '/tmp/webcam-2020-03-18-13-24-42.jpg
'.
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Par défaut, WAN est sur le port 0 et LAN accessible sur les autres ports, le port 1 étant celui par défaut. Ce qui signifie matériellement que votre câble Ethernet qui vient de votre FAIbox est connecté sur le port 0, et celui qui va vers votre réseau Lan est connecté sur le port 1.
Il peut être intéressant de faire en sorte que sur votre routeur :
Si l’interface d’administration LuCI est installée, allez dans le menu ‘System’ > ‘Switch’.
off
untagged
.Le fichier de configuration aura cette aspect :
Code : sh
$ cat /etc/config/network
(…)
config switch_vlan
option device 'switch0'
option vlan '1'
option ports '0 1 2 3 6t'
config switch_vlan
option device 'switch0'
option vlan '2'
option ports '4 6t'
(…)
Il faudra redémarrer le service network
et recharger le service firewall
.
# /etc/init.d/network restart
# /etc/init.d/firewall reload
Puis connecter les cables Ethernet pour :
Et, voilà !
Le routeur EdgeRouter X fait partie de la gamme EdgeMax des produits fabriqués par la société Ubiquiti. C’est un routeur 5 ports Gigabits, sans Wifi.
Cet article a pour propos de montrer l’installation d’OpenWRT sur ce petit routeur.
Actuellement, l’installation du firmware peut se faire depuis une console SSH. (si vous souhaitez la faire par TFTP, lisez cet article - en anglais -)
Par défaut le routeur est fourni avec EdgeOS ; le compte est ubnt.
Veillez à :
En premier lieu, téléchargeons le firmware :
Code : sh
$ ftp http://downloads.openwrt.org/releases/19.07.1/targets/ramips/mt7621/openwrt-19.07.1-ramips-mt7621-ubnt-erx-initramfs-kernel.bin
Trying 2a01:4f8:150:6449::2...
Requesting http://downloads.openwrt.org/releases/19.07.1/targets/ramips/mt7621/openwrt-19.07.1-ramips-mt7621-ubnt-erx-initramfs-kernel.bin
100% |************************************************************************************************************************************************************************************************************| 3461 KB 00:04
3545054 bytes received in 4.55 seconds (761.55 KB/s)
Et, envoie sur le routeur en SSH :
$ scp openwrt-19.07.1-ramips-mt7621-ubnt-erx-initramfs-kernel.bin ubnt@192.168.1.1:/tmp
puis on se connecte en SSH au routeur :
Code : sh
$ ssh ubnt@192.168.1.1
ubnt@ubnt:/$ cd tmp
ubnt@ubnt:/tmp$ add system image openwrt-19.07.1-ramips-mt7621-ubnt-erx-initramfs-kernel.bin
Checking upgrade image...Upgrade image does not support the device. Upgrade failed.
/tmp
ubnt@ubnt:/tmp$
C’est (mal?)heureusement un problème connu et identifié sur le forum d’OpenWRT. L’explication étant que le noyau fourni est trop gros.
Il nous faut télécharger la version fournie par cet autre initiative.
/tmp
.Téléchargeons le premier firmware :
Code : sh
$ ftp https://downloads.opennet-initiative.de/ubnt/edgeos/openwrt-ramips-mt7621-ubnt-erx-initramfs-factory.tar
Trying 2001:638:804:2228:216:3eff:fe76:4703...
Requesting https://downloads.opennet-initiative.de/ubnt/edgeos/openwrt-ramips-mt7621-ubnt-erx-initramfs-factory.tar
100% |************************************************************************************************************************************************************************************************************| 2890 KB 00:03
2959360 bytes received in 3.85 seconds (749.99 KB/s)
On l’envoie sur le routeur en SSH, puis on s’y connecte pour l’installer :
Code : sh
$ scp openwrt-ramips-mt7621-ubnt-erx-initramfs-factory.tar ubnt@192.168.1.1:/tmp
ubnt@ubnt:/$ cd tmp
ubnt@ubnt:/tmp$ add system image openwrt-ramips-mt7621-ubnt-erx-initramfs-factory.tar
Checking upgrade image...Done
Preparing to upgrade...Done
Copying upgrade image.../usr/bin/ubnt-upgrade: line 569: [: too many arguments
Done
Removing old image...Done
Checking upgrade image...Done
Copying config data...Done
Finishing upgrade...Done
Upgrade completed
show system image
The system currently has the following image(s) installed:
… (default boot)
v1.9.7+hotfix.3.5013617.170830.0227 (running image)
#A reboot is needed to boot default image, which is now are custom OpenWRT
Il est maintenant nécessaire de redémarrer le routeur :
Code : sh
root@ubnt:~# reboot
Proceed with reboot? [confirm]y
#Reboot time was rather fast. Less then 1m.
Une minute plus tard, il est normalement possible de se connecter en SSH au routeur, mais cette fois-ci avec l’identifiant root.
Dans l’état, la version du firmware est minimaliste, sans aucune interface d'administration web . Il faut connaître les méandres du système et tout configurer à la main - ce qui peut devenir très vite délicat et dangereux.
En suite, il est préférable d’installer l’image plus complète du firmware OpenWRT - et de répéter le processus d'installation , cela vous permettra entres autres d’avoir l’interface web d’administration LuCI.
Peut-être apprécierez-vous de savoir comment :
Peut-être apprécierez-vous l’astuce suivante :
Pour le mettre à jour correctement, ça se passe là :
Abordons l’aspect de connexion SSH dans OpenWRT pour sécuriser l’accès à l’interface d’administration LuCI.
Merci de vous référez à mon article à-propos d’OpenWRT
qui restitue quelques notions intéressantes à-propos du serveur SSH, de certains paramétrages clients nécessaires à faire, etc.
Par défaut, l’interface web LuCI n’est disponible QUE sur le protocole HTTP , et en plus à l’écoute partout ET sur toutes les interfaces !!!
Une manière de protéger est de rediriger le flux web vers l’interface locale de bouclage puis dans un tunnel SSH.
Aprés s’être connecté en SSH à votre routeur OpenWRT :
/etc/config/uhttpd
pour :
list listen_http 0.0.0.0:80
et list listen_https 0.0.0.0:443
; ajoutez en début de ligne
le symbole #
.list listen_http 127.0.0.1:80
(et si vous voulez interrogez localhost sur IPv6 : list listen_http [::1]:80
)/etc/init.d/uhttpd restart
$ netstat -ant | grep -E ":80"
tcp 0 0 127.0.0.1:80 0.0.0.0:* LISTEN
tcp 0 0 ::1:80 :::* LISTEN
ssh -L 127.0.0.1:8080:127.0.0.1:80 -p 22 id@ip-routeur
Où :
-p 22
est le numéro du port d’écoute par défaut du serveur SSH -
par défaut, il n’est même pas nécessaire de l’écrire : si vous
l’avez changé dans l’administration, pensez à le modifier ici, aussi !id
est l’identifiant de votre
nouvel utilisateur
.ip-routeur
est bien sûr l’adresse IP(v4), côté LAN, de votre routeur OpenWRT !Fichier : ~/.ssh/config
|
|
$ ssh luciweb
localhost:8080
Voilà !
/etc/config/dropbear
/etc/init.d/dropbear
.Le serveur SSH dropbear n’est pas capable de gérer des chiffrements forts autres que ceux restitués dans le message d’erreur.
Ajoutez à votre configuration client SSH : Ciphers aes256-ctr
Le serveur SSH dropbear n’est pas capable de gérer des clés d’hôtes plus fortes autres que celles restituées dans le message d’erreur.
Ajoutez à votre configuration client SSH : HostKeyAlgorithms ssh-rsa
Le serveur SSH dropbear n’est pas capable de gérer des algorithmes forts, pour les MAC , autres que ceux restitués dans le message d’erreur.
Ajoutez à votre configuration client SSH : MACs hmac-sha2-256
Par défaut, OpenWRT est livré avec un seul compte, celui de l’administrateur root
.
Nous allons créer un nouvel utilisateur sans privilège particulier qui
aura le droit d’administrer le système par le biais de l’utilitaire sudo
.
En tant que root, exécutons les commandes d’installation suivantes :
# opkg update
# opkg install shadow-useradd sudo
shadow-usermod
qui permettra
au besoin de modifier tout paramètre lié au compte utilisateur.Maintenant, configurons le compte utilisateur :
# u=username
où username
est le nom d’utilisateur choisi -
à vous de paramètrer à votre convenance…# useradd "${u}"
# passwd "${u}"
: afin de définir le mot-de-passe lié à l’utilisateur# mkdir -p /home/"${u}"/.ssh
: pour créer le répertoire home principal,
ainsi que le sous-répertoire .ssh
qui pourra servir plus tard.# touch /home/"${u}"/.ssh/authorized_keys
: créer le fichier vide nécessaire
pour y copier les clés SSH publiques.# chown -R "${u}":"${u}" /home/"${u}"
: pour donner les droits d’utilisateurs sur son home.# chmod 0700 /home/"${u}"
: pour n’autoriser que cet utilisateur dans son home.Je ne parlerais que de la méthode la plus sécurisée de configuration de sudo
.
Cette méthode permet de n’avoir qu’à utiliser le mot de passe de l’administrateur
sans avoir à se connecter avec le compte administrateur.
Une fois, connecté avec votre compte utilisateur, lors des besoins d’administration,
il faudra précéder de la commande sudo
toute autre commande nécessaire.
Avec l’utilitaire visudo
, nous allons éditer le fichier adéquate /etc/sudoers
.
# visudo
Puis dirigez vous vers la fin du fichier pour décommenter les deux lignes
suivantes, en supprimant le symbole #
:
# Defaults targetpw # Ask for the password of the target user
# ALL ALL=(ALL) ALL # WARNING: only use this together with 'Defaults targetpw'
:wq!
une fois que vous avez modifié le fichier afin d’écrire celui-ci
et de quitter l’éditeur.Une fois l’écriture validée, il sera permis à votre utilisateur ego
d’utiliser
toute commande d’administration, telle que décrit ci-dessus.
Profitez de ce moment particulier pour mettre votre clé d'authentification ssh
,
dans le fichier /home/ego/.ssh/authorized_keys
.
.pub
!!!Pensez à éditer le fichier /etc/sysupgrade.conf
afin d’ajouter :
/etc/sudoers.d/
(seulement si vous faites des ajouts dans ce répertoire)puis vérifier avec la commande sysupgrade -l
que le répertoire est bien inclus.
Ainsi lors de votre futur mise à niveau d’OpenWRT, vos données personnelles seront sauvegardées !
OpenWRT a pour gestionnaire de paquet l’outil opkg
.
Pour mettre à jour la liste des différents paquets, il n’est pas prévu de mettre à jour facilement ceux-ci en une seule ligne de commande, bien que l’option upgrade
existe.
upgrade
est hautement découragée. Pour comprendre la raison, merci de lire la
page du wiki à ce propos !Voici l’astuce :
# for name in `opkg list-upgradable | awk '{print $1}'`; do opkg upgrade "${name}"; done
Ou si comme moi, vous avez créé un utilisateur qui a le droit d’utiliser la commande sudo
, faites simplement :
$ for name in `sudo opkg list-upgradable | awk '{print $1}'`; do sudo opkg upgrade "${name}"; done
Un petit scrip shell nommé opkgupgrade.sh
:
#!/bin/sh
sudo opkg update
for name in `sudo opkg list-upgradable | awk '{print $1}'`; do sudo opkg upgrade "${name}"; done
Il n’y a plus qu’à l’appeler :
$ ./opkgupgrade.sh
Et voilà !
Reed-alert est un projet de monitoring simple sous OpenBSD, il n’enregistre aucune donnée ni ne produit des graphes de visualisation.
À partir d’un fichier de configuration, il vérifie plusieurs états et si ceux-ci échouent alors il sera envoyé une alerte. Le langage utilisée est le Lisp.
Auteure : Solène Rapenne
dépôt Git : git://bitreich.org/reed-alert
présentation de reed-alert (en anglais)
constat au bout de cinq ans… (en anglais)
L’installation est très simple en soit : # pkg_add reed-alert
Vous pouvez préférer le code sur le dépôt git qui corrige quelques détails.
$ git clone git://bitreich.org/reed-alert
$ cd reed-alert
$ make
sed 's,REEDDIR=,&/usr/local/share/reed-alert/,' reed-alert.in > reed-alert
$ doas make install
mkdir -p /usr/local/share/reed-alert/
mkdir -p /usr/local/bin
install -o root -g bin -m 755 reed-alert /usr/local/bin/reed-alert
install -o root -g wheel -m 644 probes.lisp functions.lisp /usr/local/share/reed-alert//
L’avantage du dépôt est qu’il fourni le fichier README très explicatif, ainsi que des fichiers d’exemples, ainsi qu’un outil de sortie au format HTML .
# pkg_add ecl
— qui est normalement installé en
dépendance du paquet reed-alert.Le fichier README
vous informe que vous pouvez copier l’un des deux
fichiers exemples en fichier de configuration.
Faisons simple, en admettons que nous soyons dans le répertoire de reed-alert :
$ touch config.lisp
.
Il vous faudra ensuite l’éditer avec votre éditeur de texte favori.
PATH
dans votre crontab
comporte aussi le répertoire /usr/local/bin
.Une fois que vous aurez tout configuré, et vérifiez
que votre configuration soit sans erreur, n’hésitez pas à ouvrir la table
de cron de l’utilisateur root
pour y ajouter un job de surveillance,
tel que :
*/5 * * * * -ns reed-alert /repertoire-vers/reed-alert/config.lisp
où :
-ns
sont spécifiques à la gestion cron - cf la
partie Documentations
/repertoire-vers/reed-alert/
correspond au répertoire où vous aurez
créé/déposé votre fichier de configuration
C’est du Common LISP !
Hormis les variables et les preuves déjà prédéfinies, il est possible d’utiliser des concepts de condition, de boucles, d’imbriquer des dépendances, des niveaux d’échelles d’alertes, d’étendre/créer vos propres preuves. Tout cela est expliqué clairement dans le fichier README.
Il existe des variables prédéfinies, elles sont entourées du symbole modulo
%
et peuvent être utilisées partout dans votre fichier de configuration.
Voici leurs noms et leur définition :
%function%
: le nom de la fonction qui sert de preuve%date%
: la date actuelle au format YYYY/MM/DD hh:mm:ss%params%
: les paramètres utilisés dans le contexte de la preuve%hostname%
: le nom d’hôte%result%
: l’erreur retournée (tel que la valeur excédant la limite, un fichier non trouvé, etc… )%desc%
: une description arbitraire nommant une vérification ; par défaut, est une chaîne vide%level%
: le type de la notification utilisé%os%
: le système d’exploitation utilisé (FreeBSD/Linux/OpenBSD)%newline%
: le caractère de nouvelle ligne%state%
: les états “start” / “end” lorsqu’un problème est levé ou résolu.La preuve est en fait un type de vérification à effectuer. C’est un test !
Par défaut, il est possible de vérifier :
command
: exécute une commande arbitraire, désirée par l’administrateur,
et qui déclenchera une alerte si le code d’erreur est supérieur à zéro.curl-http-status
: exécute une requête HTTP et lève une alerte si le
code de retour est différent de ‘OK’ (code 200)disk-usage
: que la taille d’une partition n’excéde pas une certaine limitefile-exists
: qu’un certain fichier existefile-less-than
file-updated
: qu’un certain fichier existe et qu’il a été mis à jour
depuis un temps définiload-average-1
: que la charge moyenne durant la dernière minute
n’excéde pas une certaine limiteload-average-5
: que la charge moyenne durant les cinq dernières minutes
n’excéde pas une certaine limiteload-average-15
: que la charge moyenne durant les quinze dernières
minutes n’excéde pas une certaine limitenumber-of-processes
: le nombre de processus n’excède pas une certaine limite.pid-running
: le processus en question soit vivant, en spécifiant le
fichier d’identifiant de processus.ping
: que l’hôte distant répond à deux ping.service
: qu’un service soit actif sur le système hôtessl-expiration
: qu’un certificat SSL expire dans une période donnée
en nombre de secondes.write-to-file
: permet d’écrire du contenu dans un fichier ; le créera
s’il n’existe pas localement.Je vous renvoie à la lecture du fichier README pour en savoir plus sur chacune de ces preuves.
La première chose à faire est d’ajouter une alerte - pour nous faciliter le propos, nous créerons une alerte mail.
Ajoutez basiquement :
(alert mail "echo 'problem on %hostname%' | mail mail@domain.tld")
Une version plus élaborée :
(alert mail "echo -n '[%state%] Problem with %function% %date% %params%' | mail -s '[%state%] alarm on %hostname%' mail@domain.tld")
La version du dépôt git
fournit un outil de sortie au
format HTML que l’on trouve dans le répertoire enfant extras/output2html.sh
.
Voici comment l’utiliser :
$ reed-alert config.lisp | extras/output2html.sh > alert.html
Il ne vous reste plus qu’à mettre/fournir ce fichier html sur un espace web pour obtenir la lecture de celui-ci.
Pour rappel, allez lire les deux fichiers d’exemples fournis par le projet. Ils sont instructifs.
Ci-dessous, retrouvez des exemples de mon cru.
curl-http-status
https://
suivi du nom de domaine à cibler.⇒ version basique :
Code : LISP
(=> mail curl-http-status :url "huc.fr.eu.org" :timeout 3)
(=> mail curl-http-status :url "openbsd.fr.eu.org" :timout 3)
(=> mail curl-http-status :url "blog.openbsd.fr.eu.org" :timeout 3)
⇒ version élaborée :
Code : LISP
(loop for host in (list "huc.fr.eu.org" "openbsd.fr.eu.org" "blog.openbsd.fr.eu.org")
do
(=> mail curl-http-status :url host :timeout 3))
⇒ Exemple de retour :
Code : sh
MAIL CURL-HTTP-STATUS URL https://huc.fr.eu.org TIMEOUT 3 SUCCESS SUCCESS NO 0
MAIL CURL-HTTP-STATUS URL https://openbsd.fr.eu.org TIMEOUT 3 SUCCESS SUCCESS NO 0
MAIL CURL-HTTP-STATUS URL https://blog.openbsd.fr.eu.org TIMEOUT 3 SUCCESS SUCCESS NO 0
disk-usage
Là, je vous ferais direct la version élaborée :
Code : LISP
(loop for path in (uiop:run-program "mount | awk -v pattern='/' '$0 ~ pattern { print $3 }' " :output :lines)
do
(=> mail disk-usage :path path :limit 80))
Explication :
mount
qui est “filtrée” par la commande
awk
afin de ne restituer que le nom des partitions existantes, sur
lesquelles sera appliqué le test de preuve.⇒ Exemple de retour :
Code : sh
MAIL DISK-USAGE PATH / LIMIT 80 SUCCESS SUCCESS NO 0
MAIL DISK-USAGE PATH /home LIMIT 80 SUCCESS SUCCESS NO 0
MAIL DISK-USAGE PATH /tmp LIMIT 80 SUCCESS SUCCESS NO 0
MAIL DISK-USAGE PATH /usr LIMIT 80 SUCCESS SUCCESS NO 0
MAIL DISK-USAGE PATH /usr/X11R6 LIMIT 80 SUCCESS SUCCESS NO 0
MAIL DISK-USAGE PATH /usr/local LIMIT 80 SUCCESS SUCCESS NO 0
MAIL DISK-USAGE PATH /usr/obj LIMIT 80 SUCCESS SUCCESS NO 0
MAIL DISK-USAGE PATH /usr/src LIMIT 80 SUCCESS SUCCESS NO 0
MAIL DISK-USAGE PATH /var LIMIT 80 SUCCESS SUCCESS NO 0
ping
⇒ version basique :
Code : LISP
(=> mail ping :host "192.168.1.1" :desc "Ping 192.168.1.1")
(=> mail ping :host "huc.fr.eu.org" :desc "Ping huc.fr.eu.org")
(=> mail ping :host "openbsd.fr.eu.org" :desc "Ping openbsd.fr.eu.org")
(=> mail ping :host "blog.openbsd.fr.eu.org" :desc "Ping blog.openbsd.fr.eu.org")
⇒ version élaborée :
Code : LISP
(loop for host in (list "192.168.1.1" "huc.fr.eu.org" "openbsd.fr.eu.org" "blog.openbsd.fr.eu.org")
do
(=> mail ping :host host))
Ping :
, utilisez la fonction concatenate
, en ajoutant une description
dans la dernière ligne, tel que :
:desc (concatenate 'string "Ping : " host)
⇒ Exemple de retour :
Code : sh
MAIL PING HOST 192.168.1.1 Ping : 192.168.1.1 SUCCESS SUCCESS NO 0
MAIL PING HOST huc.fr.eu.org Ping : huc.fr.eu.org SUCCESS SUCCESS NO 0
MAIL PING HOST openbsd.fr.eu.org Ping : openbsd.fr.eu.org SUCCESS SUCCESS NO 0
MAIL PING HOST blog.openbsd.fr.eu.org Ping : blog.openbsd.fr.eu.org SUCCESS SUCCESS NO 0
service
⇒ version basique :
Code : LISP
(=> mail service :name "ntpd")
(=> mail service :name "pflogd")
(=> mail service :name "smbd")
(=> mail service :name "smtpd")
(=> mail service :name "sshd")
(=> mail service :name "syslogd")
⇒ version élaborée :
Code : LISP
(loop for name in (list "ntpd" "pflogd" "smbd" "sshd" "syslogd")
do
(=> mail service :name name))
⇒ Exemple de retour :
Code : sh
MAIL SERVICE NAME ntpd SUCCESS SUCCESS NO 0
MAIL SERVICE NAME pflogd SUCCESS SUCCESS NO 0
MAIL SERVICE NAME smbd SUCCESS SUCCESS NO 0
MAIL SERVICE NAME sshd SUCCESS SUCCESS NO 0
MAIL SERVICE NAME syslogd SUCCESS SUCCESS NO 0
Pour vérifier l’écriture de votre fichier de configuration, une fois que
celle est terminée/modifiée, exécutez simplement en console :
$ reed-alert /repertoire-vers/reed-alert/config.lisp
Une fois que votre vérification est faite, pensez à créer une tâche cron ;-)
Exemple :
An error occurred during initialization:
Reader error in file #<input stream #P/path/reed-alert/config.lisp" 0xa5b677d1960>, position 173:
The character Space is not a valid dispatch macro character.
Vérifiez vos écritures. Vous avez certainement fait une erreur typographique…
Vous avez le message suivant :
ecl or sbcl not found in PATH.
you need at least one of them to use reed-alert
Après vous être assuré d’avoir au moins installer le paquet ecl
,
ajoutez dans la variable d’environnement PATH
de votre crontab le
répertoire /usr/local/bin
.
An error occurred during initialization:
"name" is not of type FUNCTION.
Vous utilisez une boucle ? Il y a de forte probabilité que vous ayez utilisé un nom de variable similaire à celui d’une fonction !
An error occurred during initialization:
Not a valid property list (HOST Ping 192.168.1.3).
Vous utilisez une boucle ? Vérifiez l’écriture de votre boucle, une des propriétés n’est pas correcte.
An error occurred during initialization:
Unexpected end of file on #<input stream #P"/path/reed-alert/config.lisp">.
L’erreur ci-dessus est due à une mauvaise écriture dans votre fichier de configuration ! Donc, VÉRIFIEZ, vérifiez ET vérifiez encore, et encore ce que vous avez écrit : un simple oubli d’une parenthèse fermante, d’un apostrophe/guillemet peut en être la cause.
La copie du dépôt vous permettra de lire les fichiers suivants :
README
: À lire, très complet, il fournit en anglais, les différentes
étapes d’installation, de paramétrage, et autres exemples.example-simple.lisp
et example-full.lisp
.MATE est un environnement de bureau graphique.
Installez
la base
et les quelques utilitaires (optionnels) : mate mate-extras
Il est nécessaire de configurer votre fichier de session .xsession
pour y inclure ceci :
exec /usr/local/bin/ck-launch-session /usr/local/bin/mate-session
Afin de fonctionner correctement cette fonctionnalité, MATE a besoin que
le service system-wide D-Bus
soit opérationnel.
Veuillez lire les informations sur la page ConsoleKit2 .
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
SLiM est un gestionnaire de session graphique indépendant du Bureau pour X11, dérivé de Login.app.
Il clame être léger et simple, bien que complètement configurable au-travers de thèmes et d’un fichier option. Il convient pour les machines sur lesquelles la fonctionnalité de session à distance n’est pas nécessaire.
ATTENTION : ce logiciel n’est plus maintenu officiellement depuis 2015 !
De plus, depuis OpenBSD 6.1, le gestionnaire de session officiel xenodm est embarqué !
Il était possible d’installer
le paquet slim
; les thèmes sont disponibles dans le paquet slim-themes
.
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Vous appréciez mes articles pour la qualité, leur sérieux, et vous voulez faire un petit geste sympa, tel le prix d’un café, d’une bierre… Ou, juste pour me remercier, et m’encourager ;-) :p
Faites un don, tout simplement.
Merci d’avance :D
⇒ Si vous le faites, et si vous le souhaitez votre nom, ou pseudo sera affiché ici, avec votre accord, à la date du don.
⇒ Alors, si vous le désirez, faites-le moi savoir dans votre don ;)
⇒ Au mois d’Octobre :
⇒ Au mois de Novembre :
OpenWRT est un système d’exploitation GNU/Linux ciblant les périphériques embarqués (typiquement des routeurs sans fils).
Ce n’est pas un projet monolitique , bien au contraire, c’est plus un framework fournissant les outils logiciels nécessaires afin de fournir un système de fichiers complet, de permettre la création de micrologiciels (en anglais : firmware) selon le matériel et tout autour une distribution complète qui permet à l’administrateur/utilisateur de la configurer “aux petits oignons” permettant différents usages utiles.
OpenWRT : v19.07.x
Le shell est le ash du projet Busybox.
L’éditeur par défaut est vi
- si vous n’aimez pas, il est possible d’en installer
d’autres, tel nano
.
Les fichiers de configuration se trouvent généralement dans /etc/config/
et
portent le nom du service à configurer.
Les services sont fonctionnels à partir du répertoire /etc/init.d/
et portent
le nom du service ; ils ont pour options les classiques :
disable
: désactiver un service - il ne redémarrera pas lors d’un (re)démarrage du routeur,enable
: activer un service - permet le démarrage du service lors du (re)démarrage du routeur,reload
: recharge la configuration du service,restart
: redémarre le service,start
: démarre le service,stop
: arrête le service.Le gestionnaire de paquets est opkg
est intégré de base dans le système ;
hormis la
mise-à-jour 'one-shot' de plusieurs paquets
,
il a pour propos les différentes possibilités de gestion des paquets, à savoir
installation, configuration, suppression de paquets…
pour en savoir plus : $ opkg ?
Si vous avez installé l'interface d'administration **LuCI** , il est possible de gérer les paquets par le biais du menu ‘System’ > ‘Software’.
LuCI est l’interface web d’administration. Par défaut, elle n’est fonctionnelle que sur le protocole HTTP .
Installez le paquet avec le gestionnaire de paquets.
# opkg install luci
L’installation de LuCI installe plusieurs paquets, dont un serveur web minimaliste nommé uhttpd , le thème basé sur Bootstrap, et les dépendances nécessaires pour la gestion de l’administration (gestion des différents protocoles réseaux, du parefeu, etc.).
Pour installer la version supportant HTTPS - ce qui est préférable -, ce sera :
# opkg install luci-ssl
Il est possible d’installer la langue française au besoin.
Retrouvez les différents paquets linguistiques :
# opkg list | grep -E "luci-i18n-(.*)-fr"
N’installez pas tous les paquets disponibles, mais seuls ceux qui vous sont vraiment nécessaires, tels - peut-être - :
luci-i18n-base-fr
pour l’interface de base de LuCI.luci-i18n-firewall-fr
pour la partie parefeuLa première ET la plus importante des premières modifications à faire est de changer le mot de passe de l’admin.
passwd
/etc/config/network
,Par défaut sont configurées les interfaces :
De plus, il est configuré deux VLAN , à partir du menu ‘Network’ > ‘Switch’, pour séparer logiciellement le LAN du WAN.
/etc/init.d/network
./etc/config/firewall
,Il est possible d’écrire directement des règles iptables à partir de l’onglet ‘Custom Rules’.
Son fichier se trouve être /etc/firewall.user
. C’est seulement dans celui-ci
où peut s’écrire directement des règles iptables ou ip6tables.
/etc/init.d/firewall
.Le serveur DHCP est dnsmasq, un serveur léger qui fait aussi office de résolveur DNS Relais (en anglais : DNS Forwarder) et fait partie du système de base. La pile IPv6 est assurée par le serveur odhcpd.
/etc/config/dhcp
dnsmasq
et odhcpd
sont accessibles à partir du même répertoire
d’initialisation /etc/init.d
./tmp/dhcp.leases
/tmp/hosts/odhcpd
On ne peut fixer/enregistrer des baux DHCP au-travers de LuCI que pour IPv4.
/etc/config/luci
-
évitez d'y toucher, à moins de savoir réellement ce que vous faîtes !
C’est le serveur dropbear - un serveur SSH, seulement v2, léger - qui fait office, par défaut dans le système de base. Il gère très bien les clés à courbes elliptiques, tel ed25519.
La première chose à faire du côté de votre client est d’ajouter dans votre configuration sécurisée , le support de :
Ciphers aes256-ctr
HostKeyAlgorithms ssh-rsa
MACs hmac-sha2-256
Retrouvez les différents codes d’erreurs liés à la fin de cet article sur SSH .
Puis paramétrez ainsi :
Par mesure de sécurité : laissez non cochées, les trois autres options que sont ‘Password Authentication’, ‘Allow root logins with password’ et ‘Gateway Ports’. Ainsi nous ne permettrons pas à l’identifiant root de se connecter, et à nul compte de pouvoir se connecter par mot-de-passe. Cela signifie qu’il faut ajouter une clé d’authentification SSH.
Il est aussi possible de créer un nouvel utilisateur SSH, en choisissant pour interface : ‘unspecified’, qui permettrait de créer ledit utilisateur…
Bien que léger, voire minimaliste uhttpd est LE serveur web, par défaut non installé sur le firmware initram, qui fait fonctionner l’interface web LuCI .
/etc/config/uhttpd
/etc/init.d/uhttpd
Par défaut, le serveur uhttpd écoute sur toutes les interfaces, partout !
Pensez à minima, par principe de sécurité, à changer les lignes list listen_http
pour cibler seulement l’adresse IP de votre LAN, tel que :
list listen_http 192.168.1.1:80
- (bien sûr, si votre adresse IP est celle-là, sinon changez-la selon vos paramétrages) -
idem, pour le port HTTPS, voire pour l’IPv6, si vous gérez !
Toujours par principe de sécurité, il est recommandé de le démarrer qu’en cas de besoin de configuration et de l’arrêter une fois terminée. C’est pourquoi, vous pouvez faire allégrement :
# /etc/init.d/uhttpd disable
ainsi il ne redémarrera pas lors de (re)démarrage du routeur.# /etc/init.d/uhttpd start
et stop
pour réciproquement le démarrer et l’arrêter au besoin.Avantage : Cela permet de libérer les ressources de puissance machine.
Cela sous-entend bien-sûr une connexion SSH active !
La restauration d’une configuration précédente peut se faire par :
La sauvegarde de toutes configurations du routeur peut se faire par :
La mise à jour du firmware peut se faire :
sysupgrade
après avoir téléchargé le firmware adéquat.Il faut être conscient que lors de la mise à jour du firmware, toute configuration personnalisée hors système sera purgée.
Mieux vaut suivre ce processus de sauvegarde correcte :
OpenWRT : Gérer correctement le processus de mise à niveau (sysupgrade)
À configurer dans votre fichier ~/.profile
, normalement, seule
LC_MESSAGES
est nécessaire :
export LC_MESSAGES="fr"
On peut au besoin configurer également les autres variables
d’environnement LC_*
, tel que:
export LC_CTYPE="fr_FR.UTF-8"
export LC_MESSAGES="fr"
export LC_NUMERIC=C
Il est possible de l’écrire légèrement différemment :
LC_CTYPE="fr_FR.UTF-8"
LC_MESSAGES="fr"
LC_ALL="fr_FR.UTF-8"
export LC_CTYPE LC_MESSAGES LC_ALL
Il est possible d’ajouter
aussi les dictionnaires aspell-fr et ispell-xyz-french
(xyz
est le numéro de la version en cours…) :
Puis mettre le français par défaut avec :
# /usr/local/bin/ispell-config
Il est possible d’y ajouter
aussi les dictionnaires aspell
et ispell
!
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Dans le fichier /etc/login.conf
, on peut allouer plus de mémoire :
Notez que la classe default
est attribuée à chaque utilisateur qui n’a
pas de classe particulière dans /etc/master.passwd
.
L’utilisateur principal se trouve généralement dans la classe staff
.
default:\
:path=/usr/bin /bin /usr/sbin /sbin /usr/X11R6/bin /usr/local/bin /usr/local/sbin:\
:umask=022:\
:datasize-max=infinity:\
:datasize-cur=4G:\
:maxproc-max=512:\
:maxproc-cur=256:\
:openfiles-cur=512:\
:stacksize-cur=4M:\
:localcipher=blowfish,a:\
:tc=auth-defaults:\
:tc=auth-ftp-defaults:
Ensuite, si votre fichier login.conf
est conséquent, vous gagnerez en
performance en créant une base de donnée. Pour créer et mettre à jour la
base de donnée :
# cap_mkdb /etc/login.conf
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
# usermod -G wheel nom_user
ATTENTION : Ce qui suit n’est qu’un exemple, parmi tant d’autres…
Pour de plus amples informations, lisez absolument la page de manuel de
doas.conf
(5) !
Dans le fichier /etc/doas.conf
:
permit setenv { ENV PS1 } :wheel
Puis logout, login !
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Vous débutez sur OpenBSD ?
Vous avez oublié une commande bien utile après avoir vécu 15 jours chez belle-maman ?
Cette page recense quelques astuces relatives à la gestion d’OpenBSD
⇒ En premier, lisez ces explications ;)
⇒ Le miroir utilisé pour chercher les paquets est indiqué dans le fichier /etc/installurl .
Vous trouverez une liste de miroirs officiels.
Les services sont gérés avec rcctl !
⇒ Pour mettre à jour le système, il faut utiliser l’outil
syspatch
⇒ Pour mettre à jour
les paquets, utilisez l’outil pkg_add
avec l’option -u
.
sudo
? inconnu !
Ici, c’est doas
(1).
Veuillez lire notre page d’information à-propos de l’outil
systat
.
Le plus simple est :
http://localhost:631
et aller dans la partie administration en tant
qu’administrateur système.Là, c’est le must… oui, oui… nous vous avons concocté plusieurs astuces, toutes recensées sur la page “Trucs et astuces pour OpenBSD”.
Alors, profitez-en, régalez-vous - c’est fait pour cela :p
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
⇒ La commande ci-dessous détecte le nombre de CPU :
$ sysctl hw.ncpu
⇒ La commande suivante détecte le nombre de coeurs / CPU :
$ sysctl hw.ncpufound
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Par défaut, le démarreur attend 5 secondes avant de commencer le
lancement d’OpenBSD. Pour réduire ce temps, mettez une ligne comme
celle-ci dans le fichier /etc/boot.conf
:
set timeout 1
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Par défaut, depuis OpenBSD 6.4, pour des raisons de confidentialité, l’enregistrement audio est désactivé !
Pour le réactiver : # sysctl kern.audio.record=1
N’oubliez pas de modifier le fichier /etc/sysctl.conf
en conséquence,
si vous désirez qu’il soit actif dès le démarrage :
# echo kern.audio.record=1 >> /etc/sysctl.conf
Pour chaque périphérique mixer, record.enable
peut être paramétré sur :
off
(toujours éteint),on
(toujours actif),sysctl
(par défaut : suit l’état du paramètre kern.audio.record
de sysctl
).Il peut être utile d’ajouter votre utilisateur au groupe operator
:
# usermod -G operator votre-id
À partir d’OpenBSD 6.7, c’est l’outil sndioctl(1) qui est utilisé. Par défaut, il n’y a aucune option de configuration à paramétrer. Normalement, il se manipule sans soucis avec les droits utilisateurs, sans autre nécessité de gestion de droits particuliers.
L’outil sndioctl(1)
est le contrôleur pour manipuler le dispositif
audio ; par exemple :
$ sndioctl output.level=+0.1
$ sndioctl output.mute=1
$ sndioctl output.mute=!
Vous désirez avoir l’affichage sous forme de pourcentage ?
⇒ Utilisez :
$ sndioctl output.level | awk -F = '{printf "%d\n",$2*100}'
Les applications audio qui utilisent la bibliothèque sndio(7)
n’ont plus accès directement aux matériels audio (au-travers de /dev/audio*
).
OpenBSD exécute le serveur de son sndiod(8) qui découvrira automatiquement quels sont vos dispositifs audio et requerra les applications audio qui en ont besoin.
Il existe des exceptions :
sndiod(8)
(cf : la section AUTHENTICATION
du manpage sndio(7)
)
Il est possible de vérifier que le serveur de son sndiod(8)
est
fonctionnel en exécutant :
$ pgrep -lf sndiod
cf : source
Avant OpenBSD 6.7, c’est la commande mixerctl
qui était utile. Vous pouvez lancer la commande seule pour voir toutes les sorties existantes.
mixerctl outputs.master=+10
mixerctl outputs.master=-10
mixerctl outputs.mute=toggle
Comme le rappelle la FAQ Multimédia d’OpenBSD,
l’outil mixerctl
sert toujours à configurer les paramètres liés au
matériel audio !
(à utiliser toujours avec des droits administrateurs)
Pour savoir ce que gère l’outil de votre matériel :
# mixerctl -av
Quelque soit la modification faite ou à faire, il faut ensuite l’écrire
dans le fichier /etc/mixerctl.conf
qui n’existe pas par défaut :
# cp /etc/examples/mixerctl.conf /etc/mixerctl.conf
Si les modifications ne sont pas écrites dans ce fichier, tout sera réinitialisé par défaut au redémarrage suivant.
Lire la FAQ Contrôles des niveaux.
L’Amplificateur EAPD est un bouton logiciel utile dans le contexte des modes d’énergie, tels que la veille ou l’hibernation. C’est une spécification de la norme Intel HDA - HD Audio.
Lire la FAQ Amplificateur EAPD si vous utilisez un ordinateur portable.
Pour information, votre matériel peut très certainement le gérer et déjà
paramétré pour les différentes sorties correspondantes. Vérifiez :
# mixerctl -av | grep eapd
Lire la FAQ Amplificateur EAPD
Lire la FAQ Utiliser une interface USB Audio
Lire la FAQ Utiliser à distance le matériel audio
Pour gérer le son sur une sortie SPDIF, donc en mode digital, il est nécessaire de modifier le mode de sortie :
outputs.mode=digital
Ensuite, il faut modifier le serveur de son sndiod(8) pour qu’il gère
les canaux correspondants. Par défaut, sndiod ne gère que les canaux
0:1
, ce qui permet quand même un son stéréo.
En premier, vérifions la sortie SPDIF :
# mixerctl outputs.SPDIF_source
Ce qui pour l’exemple :
$ doas mixerctl outputs.SPDIF_source
outputs.SPDIF_source=dig-dac-2:3
Comme le montre cet exemple, la sortie SPDIF se fait sur les canaux
2:3
(2 et 3), non géré par défaut par le serveur sndiod.
Il faut donc modifier le démarrage du serveur sndiod, en ajoutant les
drapeaux suivants 0:3
pour :
# rcctl set sndiod flags -c0:3
# rcctl restart sndiod
Attention, certains périphériques matérielles (càd comme des cartes-mères) peuvent gérer plus de canaux que les 4 premiers en question. C’est à chacun de s’assurer des canaux à utiliser et à modifier en conséquence la gestion des canaux par le serveur de son.
Parfois, un bip peut être émis si par exemple une commande n’arrive pas
à être complétée avec Tab. Pour le désactiver, ajoutez cette ligne au
fichier /etc/wsconsctl.conf
:
keyboard.bell.volume=0
Avant OpenBSD v6.7, il pouvait être utile d’utiliser la commande suivante :
# mixerctl inputs.mix_beep = 0
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
ksh est le shell par défaut sous OpenBSD - exactement pdksh : Public Domain Korn Shell, qui est l’équivalent du ksh88.
/etc/ksh.kshrc
~/.kshrc
Les autres fichiers de configuration liés à l’usage de ksh sont (cf : le manpage ksh) :
~/.profile
/etc/profile
/etc/shells
/etc/suid_profile
Préférez modifier votre fichier de configuration personnel, en ajoutant les déclarations principales, tel que :
. /etc/ksh.kshrc
.profile
Sourcez votre fichier personnel ~/.profile
dans lequel vous déclarez
toutes vos variables d’environnement, vos alias, de manière généraliste.
Préférez l’usage de la variable HOME
plutôt que du
tilde ~
, tel que :
. $HOME/.profile
Ajoutez ceci :
HISTFILE=~/.hist
HISTSIZE=3000
Si vous ne voulez pas garder de doublons si une même commande est lancée plusieurs fois de suite :
HISTCONTROL=ignoredumps
⇒ PS1 user : PS1="\e[0;36m\u@\h: \e[0;32m\w \e[0;36m\$ \e[m"
⇒ PS1 root : PS1="\e[0;31m\u@\h | \e[0;32m\w | \e[0;31m\# \e[m"
Il peut être intéressant d’avoir un prompt couleur, d’une part pour se repérer dans son terminal, d’autre part, ça devient intéressant visuellement si ce dernier change de couleur en fonction du code de retour de la commande qui vient d’être lancée.
Pour cela, voici un bout de config à ajouter :
escape=$(print '\033')
ctrla=$(print '\001')
PS1=$(print '\001\015')
PS1=$PS1$ctrla$escape'[$(($? ? 31 : 32))m'$ctrla
PS1=$PS1'[\u@\h \w]'
PS1=$PS1$ctrla$escape'[0m'$ctrla' '
. /etc/ksh.kshrc
. $HOME/.profile
HISTCONTROL=ignoredumps
HISTFILE=~/.hist
HISTSIZE=3000
# Préférez paramétrer les variables PS1, LC_* dans .profile
export PS1="\u@\h:\w\$ "
export LC_CTYPE=fr_FR.UTF-8
export LC_MESSAGES=fr
export TOP='-s 1'
export PAGER=less
⇒ Obtenir une date au format timestamp :
$ date +%s
⇒ Transformer un timestamp en date :
$ date -r $timestamp +"%x %X"
⇒ Obtenir la date de maintenant :
$ date +"%x %X"
⇒ Obtenir la date du jour :
$ date +'%Y-%m-%d_%H-%M-%S'
⇒ Obtenir la date d’hier :
date -r $(($(date -j $(date +%Y%m%d1200) +%s) - 86400)) +%F
⇒ date de création : $ stat -f "%c" nom-fichier
⇒ date de modification : $ stat -f "%m" nom-fichier
⇒ date du dernier accès : $ stat -f "%c" nom-fichier
Obtenir la taille d’un fichier :
$ stat -f "%z" nom-fichier
Obtenir le type du fichier :
$ stat -f "%T" nom-fichier
⇒ Obtenir l’utilisateur ayant les droits sur le fichier :
$ stat -f "%u" nom-fichier
⇒ et le groupe :
$ stat -f "%g" nom-fichier
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Audacious est un lecteur multimédia qui utilise actuellement une interface utilisateur basée sur les thémes de Winamp 2.x Il est dérivé de BMP et XMMS.
Installez
les
paquets audacious audacious-plugins
!
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
lftp est un outil en ligne de commande, qui permet de transférer des fichiers. Il supporte les protocoles Bittorent, FISH, FTP, FTPS, HTTP, HTTPS, SFTP et a un support partiel pour WebDAV. IPv(4|6).
Ses fonctionnalités sont :
installez
le
paquet lftp
.
En tant que client CLI, il peut autant s’utiliser dans une ligne de commande que dans un script sh.
Les options :
-c
: suivi d’un ensemble de commandes et quitte-d
: le mode de déboguage-e
: suivi d’un ensemble de commandes et ne quitte pas-f
: suivi d’un nom de fichier, permet d’exécuter les commandes dans
ce fichier et quitte. Cette option DOIT s’utiliser toute seule,
sans aucun autre argument (sauf --norc
).--norc
: ne pas exécuter les fichiers rc depuis votre répertoire $HOME.-p
: spécifie le numéro de port sur lequel se connecter--rcfile
: suivi d’un nom de fichier, permet d’exécuter un ensemble
de commandes dans ce fichier et d’être exécuté plusieurs fois.-u
: permet de spécifier le couple d’identification utilisateur +
mot de passe. Il est recommandé d’utiliser le fichier ~/.netrc
dans
lequel préciser le mot de passe, plutôt que dans la ligne de commande,
ou par le biais de la variable d’environnement LFTP_PASSWORD
qui
sera ensuite appelée par l’option --env-password
. De manière
alternative, il est possible d’utiliser une connexion SSH par
authentification par clé autorisée.Si les variables d’environnement suivantes sont précisées avant l’appel système, lftp est/sera capable de les utiliser :
EDITOR
: l’éditeur de texte qui sera appelé lors de l’usage de la
commande edit
.HOME
: le répertoire personnel localLFTP_HOME
: utilisée pour localiser le répertoire des fichiers de
configurations locaux spécifiques à l’utilisateur.
~/.lftp
.LFTP_MODULE_PATH
: initialise la variable module:path
LFTP_PASSWORD
: utilisée par l’argument open
lors de l’usage de
l’option --env-password
.LS_COLORS
: permet de paramétrer la variable color:dir-colors
qui
ajoutera des couleurs.PAGER
: le nom du pager à utiliser lors de l’usage des commandes
more
et zmore
.SHELL
: utilisée par la commande !
pour déterminer quel shell utiliserXDG_CONFIG_HOME
, XDG_DATA_HOME
, XDG_CACHE_HOME
: utilisée pour
localiser les répertoires spécifiques utilisateur si ~/.lftp
ou la
variable d’environnement LFTP_HOME
ne sont pas précisés.
~/.cache
, ~/.config
,
~/.local/share
. Il sera ajouté le préfixe /lftp
pour restituer
le chemin absolu du répertoire en question.ftp_proxy
: initialise la variable pour le mandataire FTPhttp_proxy
, https_proxy
: initialise les variables pour les
mandataires HTTP(S)no_proxy
: initialise la variable net:no_proxy
.ll existe énormément de commandes utilisables avec lftp ; veuillez lire le manpage ; seules certaines seront précisées ici sur cette page :
Cette commande spéciale !
exécute un shell suivi d’une autre commande
Pour définir un nom d’alias ; c’est le même principe que les alias de shell
Exécutera une commande au moment donné. Voir le manpage at(1).
Permettra l’édition d’un fichier distant par le biais de l’éditeur texte spécifié. Dans les faits, lftp récupérera le fichier vers un répertoire temporaire local, exécutera l’éditeur de texte local et téléversera sur le serveur le fichier.
Les options :
-k
: pour garder le fichier temporaire-o
: pour spécifier le répertoire temporaireFaire une copie en miroir d’un répertoire source spécifié vers un
répertoire cible. (c’est l’équivalent de l’outil rsync
).
Par défaut, la source est distante et la cible est le répertoire local.
Il faut utiliser l’option -R
pour inverser la source et la cible ;
ainsi le répertoire source sera le répertoire local et la cible sera le
répertoire distant.
Si le répertoire cible est omis, la base du nom du répertoire source sera utilisée. Si les deux sont omis, les répertoires courants local et distant seront utilisés.
Si le répertoire cible termine avec un /
(hormis le répertoire racine)
alors la base du nom du répertoire source sera ajouté.
Les options :
-a
: l’équivalent des options --allow-suid
et --no-umask
.-c
, --continue
: continue un job si possible-e
, --delete
: supprime les fichiers qui ne sont pas présent sur
la source
--delete-excluded
: supprimera les fichiesr exclus sur la cible--delete-first
: supprimera en premier les vieux fichiers avant de
transférer les nouveaux--depth-first
: descendra dans les sous répertoires avant de
transférer les fichiers--scan-all-first
: analysera tous les répertoires récursivement
avant de transférer les fichiers-F
, --directory=
: fera une copie miroir du seul répertoire
spécifié, ou selon un glob précis, tel /path/dir*
.-f
, --file=
: fera une copie miroir du seul fichier spécifié, ou
selon un glob précis, tel que /path/*.txt
.-I GP
, --include-glob=GP
: inclue les fichiers correspondants au
glob pattern. À-propos de GP
, voir la note ci-dessous.-i RX
, --include=RX
: inclue les fichiers correspondants à
l’expression régulière. À-propos de RX
, voir la note ci-dessous.-L
, --dereference
: télécharge les liens symboliques comme étant
des fichiers
--no-overwrite
: supprime d’abord les fichiers et les recréer ensuite--overwrite
: ré-écrit les fichiers sans les supprimer en premier-O
, --target-directory=
: cible le chemin ou l’URL-N
, --never-than=
: téléchargera seulement les fichiers les plus
récents selon une date spécifiée
--older-than=
: téléchargera seulement les fichiers anciens selon
une date spécifiée--size-range=
: téléchargera seulement les fichiers ayant telle taille-n
, --only-newer
: téléchargera seulement les fichiers les plus
récents - dans ce cas, l’option -c
ne fonctionnera pas.
--upload-older
: téléchargera sur la cible même les fichiers plus
vieux que les actuels.--transfer-all
: transférera tous les fichiers, même ceux qui
ressemblent à ceux existant sur la cible.-P
, --parallel
: téléchargera N fichiers en même temps
--loop
: répétera le miroir jusqu’à ce que plus aucun changement
ne soit trouvé--on-change=
: exécutera la commande spécifiée lors d’un changement--use-pget
: utilisera l’outil pget
pour transférer chaque fichier-p
, --no-perms
: ne paramétrera pas les permissions de fichiers
--no-umask
: n’appliquera pas le mode umask-R
, --reverse
: inverse le miroir-r
, --no-recursion
: ne parcourra pas les sous répertoires
--recursion=
: parcourra les sous répertoires selon un mode choisi--no-symlinks
: ne créera pas les liens symboliques-s
, --allow-suid
: paramétrera les bits suid
et sgid
selon
la source
--allow-chown
: paramétrera les droits utilisateur et groupe sur
les fichiers--ascii
: utilisera le mode de transfert ascii
- ce qui implique
l’option --ignore-size
.--ignore-size
: ignore la taille--ignore-time
: ignore l’heure de téléchargement--only-existing
: téléchargera seulement les fichiers déjà existant
sur la cible--only-missing
: téléchargera seulement les fichiers non existant
sur la cible.-v
, --verbose
: restitue les informations de manière verbeuse ; il
est possible de spécifier un niveau, tel que =level
.
--log=
: écrit le retour des commandes lftp exécutées dans le
fichier journal spécifié--max-errors=
: arrête l’exécution après N erreurs.--Move
: identique à l’option --Remove-source-dirs
.--Remove-source-dirs
: supprime les répertoires et les fichiers
sources après le transfert - à utiliser avec précaution !--Remove-source-files
: supprime les fichiers sources après le
transfert - à utiliser avec précaution !--script=
: lis les commandes lftp depuis un fichier, sans les
exécuter. Autres noms de l’option : --just-print
, ou --dry-run
.--skip-noaccess
: ne pas essayer de transférer les fichiers qui
n’ont pas d’accès en lecture.--use-cache
: utilise une liste de répertoire mis en cache-X GP
, --exclude-glob=GP
: exclue les fichiers selon le pattern
glob. À-propos de GP
, voir la note ci-dessous.
--exclude-glob-from=
, --exclude-rx-from=
, --include-glob-from=
,
--include-rx-from=
: inclura ou exclura les fichiers selon le
fichier renfermant l’expression régulière ou le glob pattern
fourni - un par ligne.-x RX
, --exclude=RX
: exclue les fichiers selon l’expression
régulière. À-propos de RX
, voir la note ci-dessous.Notes :
GP
est un glob pattern à fournir, tel *.zip
RX
est une expression régulière à fournirSe connecter en ligne de commande :
$ lftp -p $port sftp://$user@$address
-p $port
: est le numéro de port de connexion vers le serveur.
22
, mais cela dépend de votre
configuration serveur.$user
: l’identifiant de connexion$adress
: l’adresse ip ou le nom d’hôte FQDN du serveur sur lequel
se connecter.Dans un script shell :
/usr/local/bin/lftp -p $port sftp://$user@$host
Une des fonctionnalités intéressantes est le fait de pouvoir faire du “mirroring” - de la copie en miroir d’un ensemble de fichiers, répertoires vers un autre endroit ; l’équivalent de rsync -
$ lftp -e "mirror -e -R /repertoire_local/ /repertoire_distant/ ; quit" -p $port sftp://$user@$host
man ltfp
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Gajim est un client Jabber, messagerie de communication presque instantanée, écrit en Python-GTK.
Disponible : à partir d’OpenBSD 6.2
installez
le
paquet gajim
.
Pour installer un ou plusieurs plugins, il y a :
~/.local/share/gajim/plugins/
git clone https://dev.gajim.org/gajim/gajim-plugins.git
Ci-dessous sera abordé les quelques plugins pour communiquer de manière sécurisée avec un interlocuteur.
Le protocole de chiffrement OMEMO est basé sur les protocoles de chiffrement X3DH (génération de clés cryptographiques asymétriques, basées soit sur XEd25519, ou XEd448 ; le protocole XEdDSA est simplement une variante du protocole EdDSA) + “Double Rachet” (protocole d’échange et de maintenance des clés et autres informations secrètes).
OMEMO chiffre les messages en employant AES256+GCM !
Les informations concernant le plugin OMEMO pour Gajim sont disponibles depuis le wiki du git : https://dev.gajim.org/gajim/gajim-plugins/wikis/OmemoGajimPlugin
À noter qu’à partir d’OpenBSD 6.9, il est possible (et préférable)
d’installer
les
paquets pour les ajouter :
py3-cryptography py3-axolotl py3-qrcode py3-Pillow py3-future
Autrement, pour Python 2.x, une fois le plugin téléchargé et installé dans votre répertoire personnel, en tant qu’administrateur :
py-cryptography
soit installé
pip
certains
modules supplémentaires, autrement les fonctionnalités liés à OMEMO
ne pourraient être utilisées.
# python -m pip install python-axolotl qrcode pillow future
Ceci étant fait, ouvrez votre client Gajim, allez dans le menu Édition > Plugins. Activez le plugin dans l’onglet “Installé”… puis cliquer sur le bouton [ Configurer ] qui vous permettra de générer une empreinte, pour la transmettre à un tiers, et aussi de gérer celles de vos contacts !
Les informations concernant le plugin OTR - Off-the-Record - pour Gajim sont disponibles depuis le wiki du git : https://dev.gajim.org/gajim/gajim-plugins/wikis/OffTheRecordPlugin
L’auteur du plugin avertit qu’à cause de bogues dans le plugin qui restranscrit en text clair, il est préférable d’utiliser soit OMEMO, soit PGP !
De plus, le plugin ne fonctionnera pas si la version de Gajim est >= 1.0, car il n’a pas été migré vers Python 3.x, et n’est pas planifié.
Ceci étant fait, ouvrez votre client Gajim, allez dans le menu Édition > Plugins. Activez le plugin dans l’onglet “Installé”… puis cliquer sur le bouton [ Configurer ] qui vous permettra de générer une empreinte, pour la transmettre à un tiers, et aussi de gérer celles de vos contacts !
Les informations concernant le plugin PGP - pour Gajim sont disponibles depuis le wiki du git : https://dev.gajim.org/gajim/gajim-plugins/wikis/pgpplugin
Une fois le plugin téléchargé et installé dans votre répertoire personnel, en tant qu’administrateur :
py-gnupg
soit installé
J’ai écrit historiquement de manière collaborative cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
FileZilla est un client FTP puissant. Il est conçu pour être facile à utiliser et prenant en charge autant de fonctionnalités que possible, tout en s’efforçant d’être rapide et fiable.
Les fonctionnalités principales de FileZilla sont :
installez
le
paquet filezilla
.
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Avahi est une implémentation libre, conforme au standard des protocoles Multicast DNS (mDNS) et DNS-SD gérés par Zeroconf.
C’est un système qui facilite la découverte de services sur un réseau local. Cela signifie que vous pouvez connecter votre portable ou ordinateur sur un réseau et qu’il soit capable instantanément de voir les autres personnes avec qui vous pouvez discuter, trouver les imprimantes, ou les fichiers partagés. L’esprit de cette technologie est toujours trouvé dans l’Apple MacOS X (sous la marque Rendezvous, Bonjour et parfois Zeroconf) et est très pratique.
installez
le
paquet avahi
.
Il faut :
Activer les services
multicast avahi_daemon
messagebus
n’est pas activé, pensez à le faire !que le sous-système wide D-BUS soit
impérativement démarré en premier
:
messagebus avahi_daemon
puis démarrez les services
services relatifs : avahi_daemon
Voici les règles pare-feu si besoin :
pass proto udp from any to 224.0.0.251 port mdns allow-opts
pass inet6 proto udp from any to ff02::fb port mdns allow-opts
ff02::c
est l’adresse multicast de lien localff05::c
est l’adresse multicast de site localff08::c
est l’adresse multicast d’organisation localff0e::c
pour l’adresse multicast global - //que nous n’utiliserons pas dans le contexte local// !pass proto udp from any to 239.255.255.250 port ssdp allow-opts
pass inet6 proto udp from any to { ff02::c, ff05::c, ff08::c } port ssdp allow-opts
Après l’installation, n’oubliez pas de lire le fichier pkg-readme :
/usr/local/share/doc/pkg-readmes/avahi
!
Vous pouvez lire des exemples dans /usr/local/share/examples/avahi/
.
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
EncFS fournit un système de fichiers basés sur FUSE et OpenSSL.
EncFS travaille sur la base des fichiers, non pas avec des blocs périphériques. Un système de fichiers EncFS peut grandir à n’importe quelle taille sans être reformaté et peut être sauvegardés sur la base de fichiers par fichiers.
EncFS NE chiffre pas ou ne cache pas les informations suivantes :
Installez
le
paquet encfs
.
Il y a trois modes de créations d’un système de fichiers virtuel chiffré encfs :
Pour créer :
$ doas encfs /repertoire_chiffre /repertoire_cible
Création du nouveau volume encrypté.
Veuillez choisir l'une des options suivantes :
entrez "x" pour le mode de configuration expert,
entrez "p" pour le mode paranoïaque préconfiguré,
toute autre entrée ou une ligne vide sélectionnera le mode normal.
?>
Choisissez d’appuyer sur la touche :
Entrée pour utiliser le mode normal
p pour choisir le mode paranoïaque pré-configuré
x est le choix du mode expert
Ensuite, l’invite de commande vous demande de taper un mot-de-passe, puis de le confirmer !
⇒ Pour monter le système de fichier virtuel chiffré encfs, c’est exactement la même commande que la création :
$ doas encfs /repertoire_chiffre /repertoire_cible
⇒ Pour démonter le système de fichier virtuel chiffré encfs :
$ doas umount /repertoire_cible
Il peut arriver que, suite au montage d’un système de fichier virtuel encfs, les permissions d’appartenance des fichiers et autres répertoires sont paramétrées sur les droits administratifs de l’utilisateur root.
Modifiez les, à nouveau, par vos droits utilisateurs :
$ chown -R $USER:$USER /repertoire_cible
Il peut vous être utile de lire localement sur votre station de travail
OpenBSD, la page de manuel correspondante man encfs
.
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
ReadyMedia (anciennement nommé : MiniDLNA ) est un simple logiciel serveur multimédia, écrit en C, qui aime être pleinement compatible avec les clients DLNA ou UPnP-AV (télévisions, tablettes, etc…).
installez
le
paquet minidlna
.
/etc/minidlna.conf
L’option enable_tivo=yes
nécessite qu’Avahi
soit installé et configuré !
Pour améliorer la gestion des mécanismes de notification du noyau
kqueue(2) en temps réel, il est
intéressant d’augmenter la variable kern.maxfiles
gérée par
sysctl(8), soit en l’ajoutant au
fichier de configuration /etc/
sysctl.conf(5)
,
soit en modifiant les classes de login(1)
en augmentant les limites d’ouvertures de fichiers cur
et max
du
fichier /etc/
login.conf(5)
.
Ce qui peut donner, par exemple :
/etc/sysctl.conf
: kern.maxfiles=16384
/etc/login.conf
: minidlna:\
:openfiles=16384:\
:tc=daemon: </file>
Une fois fait, redémarrez votre machine !
Voici un exemple de règles PF, à modifier selon vos besoins :
pass in quick on egress proto tcp from egress:network to egress port 8200 flags S/SA modulate state
pass in quick on egress proto udp from egress:network to egress port 8200 allow-opts keep state
Il vous sera aussi nécessaire d’ajouter celles relatives à Avahi , si besoin…
Depuis OpenBSD 6.5, le fonctionnement de minidlna a changé. Ceci est
expliqué dans la section “Limites systèmes
”.
Malgré le paramétrage indiqué dans ladite section, il peut être nécessaire
de paramétrer l’option inotify
sur no
dans le fichier de configuration
de minidlna :
# set this to no to disable kqueue monitoring to automatically discover new files
# note: the default is yes
inotify=no
Puis, redémarrez le service de minidlna.
/usr/local/share/doc/pkg-readmes/minidlna
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Le projet OpenBSD diffuse ses sources, quelqu’elles soient, par le biais de serveurs Anonymes CVS - qui est un système de gestion des différentes versions d’un code (tel que peut l’être git, ou bazaar…)
Ayant une machine informatique sous OpenBSD, nous n’avons besoin de ne
rien installer, puisque cvs
est installé par défaut.
Le projet OpenBSD a 4 dépôts différents, avec lesquels nous pouvons interagir :
Ces dépôts, du fait de ne pas faire partie de l’équipe des développeurs, nous sont accessibles seulement en lecture seule !
Admettons que nous avons repéré une erreur sur une des pages du site web d’OpenBSD, nous “interagirons” donc avec le dépôt www.
Commençons par créer un répertoire où nous téléchargerons les sources désirées :
$ mkdir ~/src && cd ~/src
Puis, demandons à cvs de récupérer les sources désirées - nous choisissons pour l’exemple le serveur anonyme CVS de nos collaborateurs français que sont A.Jacoutot et L.Breuil :
$ cvs -qd anoncvs@anoncvs.fr.openbsd.org:/cvs get -P www
$ cd ~/src/www
$ cvs diff -u > /tmp/patch.txt
Cela étant fait, transmettez le contenu du fichier patch.txt
, intégré
dans le corps du mail - en copie - de préférence à la liste de diffusion
tech@openbsd.org !
Pour mettre à jour l’arborescence que vous avez déjà récupérée, c’est vraiment très simple :
$ cd ~/src/www
$ cvs -q up -Pd
Vous avez l’erreur suivante, quand vous utilisez cvs :
cvs update: No CVSROOT specified! Please use the `-d' option
cvs [update aborted]: or set the CVSROOT environment variable.
Vous n’êtes pas dans le bon répertoire à mettre à jour - déplacez-vous dans le répertoire cible à mettre à jour.
Admettons, pour reprendre l’exemple de gestion du site www, mettez-vous
dans ~/src/www
!!!
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
MediaTomb est LE serveur Multimedia UPnP OpenSource.
Site : http://mediatomb.cc/
N’est plus disponible ni en tant que paquet, ni en tant que port depuis OpenBSD 6.4 !
Veuillez migrer sur un autre service multimédia supporté, tel que ReadyMedia !
Était installable depuis le système de package : mediatomb
/etc/mediatomb/config.xml
Après toute modification, pensez à relancer le serveur !
Il est impératif d’empêcher toute connexion non désirée à l’interface web d’administration !
Ouvrir le fichier de configuration, pour modifier les lignes suivantes :
<accounts enabled="no" session-timeout="30">
<account user="mediatomb" password="mediatomb"/>
</accounts>
On change la valeur de l’attribut enabled
par yes
puis celles des
attributs user
et password
, par celles que vous désirez utiliser.
user
et
password
!L’encodage UTF-8 n’est pas géré nativement.
Ouvrir le fichier de configuration, après la balise ouvrante import
:
<import hidden-files="no">
Puis, ajoutez les lignes suivantes :
<filesystem-charset>UTF-8</filesystem-charset>
<metadata-charset>UTF-8</metadata-charset>
<playlist-charset>UTF-8</playlist-charset>
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
syspatch [-c | -l | -R | -r]
Syspatch est un outil pour récupérer, vérifier et installer, voire revenir à une précédente version, des correctifs de binaire d’OpenBSD.
Lorsqu’il est exécuté sans aucune option, syspatch appliquera tous les correctifs non installés, créant une archive pour revenir en arrière, contenant les fichiers qui vont être remplacés, puis extrait et installe tous les fichiers contenus dans l’archive pour syspatch. Les correctifs sont cumulatifs et en tant que tel, il n’est pas possible de les installer un par un.
Les options sont les suivantes :
-c
: liste les correctifs disponibles ; convient pour cron(8).-l
: liste les correctifs appliqués-R
: enlever tous les correctifs-r
: enlever les correctifs récemment installés/etc/installurl
: URL du miroir d’OpenBSD pour récupérer les correctifs./var/syspatch/*
: répertoires contenant les archives de reversion
et originales, signées avec diff(1)
et les correctifs installés.syspatch est apparu la première fois dans OpenBSD 6.1
syspatch a été écrit par Antoine Jacoutot ajacoutot@openbsd.org.
syspatch est conçu pour travailler seulement sur les versions d’un OpenBSD officiel.
Traduction du manpage syspatch(8) !
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Pour rappel, voici les usages les plus courants :
rcctl enable service
rcctl disable service
rcctl start service
rcctl restart service
rcctl reload service
rcctl stop service
Pour configurer un service avec certains drapeaux au démarrage de celui-ci :
rcctl set service flags nom_drapeau valeur_drapeau…
Il peut y avoir sans soucis plusieurs drapeaux et leurs valeurs se suivant, sans soucis.
Pour connaître les noms des drapeaux d’un service, il est impératif de lire le manpage correspondant.
Certains services doivent démarrés avant d’autres, il faut donc les spécifier les uns devant les autres :
rcctl order service1 service2 service…
L’utilitaire rcctl peut activer ou désactiver un service du système de base ou un démon d’un paquet dans rc.conf.local(8) ou afficher sa configuration et son statut. Pour un démon, il peut aussi changer les arguments de ligne de commande, l’utilisateur avec lequel l’exécuter, le délai “timeout” d’action de rc.d(8) ou appeler son script de contrôle du démon rc.d(8).
Les commandes suivantes sont disponibles (variable peut être de type class, flags, status, timeout ou user) :
rcctl action retourne un statut de sortie du script du démon rc.d(8). rcctl get daemon | service [status] termine avec 0 si le démon ou service est activé et avec 1 s’il ne l’est pas. rcctl getdef daemon | service [status] termine avec 0 si le démon ou service est activé par défaut et 1 s’il ne l’est pas. rcctl ls failed termine avec 1 si un démon activé ne fonctionne pas. Autrement, l’utilitaire rcctl termine avec 0 en cas de succès, et supérieur à 0 si une erreur arrive (2 indique un démon ou service non existant).
Active et paramètre les drapeaux d’apmd(8) :
# rcctl set apmd status on
# rcctl set apmd flags -A
# rcctl get apmd
apmd_class=daemon
apmd_flags=-A
apmd_rtable=0
apmd_timeout=30
apmd_user=root
# echo $?
0
La manière recommandée pour exécuter une seconde copie d’un démon en particulier pour un but différent est de créer un lien symbolique vers son script de contrôle rc.d(8) :
# ln -s /etc/rc.d/snmpd /etc/rc.d/snmpd6
# rcctl set snmpd6 status on
# rcctl set snmpd6 flags -D addr=2001:db8::1234
# rcctl start snmpd6
rcctl est apparu la première fois dans OpenBSD 5.7.
rcctl a été écrit par Antoine Jacoutot ajacoutot@openbsd.org.
Traduction du manpage rcctl(8) !
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
OpenNTPD est intégré nativement dans OpenBSD.
Les adresses de serveurs NTP sont visibles depuis la page pour trouver un serveur.
Les serveurs de pool NTP sont par zones mondiales comportant plusieurs pays.
Le fichier de configuration est /etc/ntpd.conf
.
Il est apparu dans OpenBSD 3.6.
Des différentes options :
*
est donné, ntpd écoutera toutes
les adresses locales où est spécifiée la table de routage.
Le mot-clé rtable
indique quelle table de routage écouter.
Par défault, ntpd écoute la table de routage en cours.*
est donné, ntpd essaiera d’écouter tous les capteurs
qu’il trouvera.
Par défaut, ntpd n’utilise aucun capteur.server
, à la différence que si les serveurs ont plusieurs
adresses IP, ntpd essaiera de se synchroniser sur toutes ces adresses.constraint from
,
à la différence que si le nom d’hôte est résolu sur plusieurs adresses
IP, ntpd(8) calculera une contrainte médiane à partir de toutes ces
adresses.À-propos des options de contraintes : ntpd(8) peut être configuré pour interroger la ‘Date’ des serveurs HTTPS de confiance via TLS. Cette information de temps n’est pas utilisée pour la précision mais agit comme une contrainte authentifiée, réduisant ainsi l’impact des attaques NTP non authentifiées de l’homme au milieu. Les paquets NTP reçus dont les informations temporelles se situent en dehors d’une plage proche de la contrainte seront rejetés et ces serveurs NTP seront marqués comme invalides.
Dans ce mail, Theo de Raadt explique pourquoi il n’est pas désirable de personnaliser les paramètres de contraintes autrement que ceux que l’équipe fixe. Où l’on apprend aussi que le domaine www.openbsd.org ne doit pas être invoqué, non plus…
Voici un exemple du fichier /etc/examples/ntpd.conf
:
# $OpenBSD: ntpd.conf,v 1.5 2019/11/11 16:44:37 deraadt Exp $
# sample ntpd configuration file, see ntpd.conf(5)
# Addresses to listen on (ntpd does not listen by default)
#listen on *
# sync to a single server
#server ntp.example.org
# use a random selection of NTP Pool Time Servers
# see http://support.ntp.org/bin/view/Servers/NTPPoolServers
servers pool.ntp.org
# time server with excellent global adjacency
server time.cloudflare.com
# use a specific local timedelta sensor (radio clock, etc)
sensor nmea0 trusted
# use all detected timedelta sensors
#sensor *
# get the time constraint from a well-known HTTPS site
constraint from "9.9.9.9" # quad9 v4 without DNS
constraint from "2620:fe::fe" # quad9 v6 without DNS
constraints from "www.google.com" # intentionally not 8.8.8.8
Le démon ntpd
synchronise l’horloge locale sur un ou plusieurs serveurs
NTP distants ou capteurs timedelta locaux. ntpd peut également agir comme
un serveur NTP lui-même, redistribuant l’heure locale. Il implémente la
version 4 de Simple Network Time Protocol, telle que décrite dans la RFC
5905, et la version 3 de Network Time Protocol, telle que décrite dans
la RFC 1305. Le temps peut également être récupéré depuis les serveurs
HTTPS pour réduire l’impact des attaques NTP dites “man-in-the-middle”
(l’homme au milieu) non authentifiées.
Le service ntpd
est apparu la première fois dans OpenBSD 3.6.
Les options possibles au service sont :
-d
: ne pas mettre en service. ntpd fonctionnera alors en arrière plan,
et journalisera vers la sortie stderr
.-f *fichier*
: utilisera le fichier de configuration spécifié au lieu
du fichier de configuration par défaut.-n
: test la validité du fichier de configuration. À n’utiliser que
pour cela.-S
: annule les effets de l’option -s
.-s
: essaye toujours de régler l’heure au démarrage de la machine.
Par défaut, ntpd essaye de régler l’heure au démarrage, uniquement
si les contraintes sont configurées et satisfaites. ntpd restera au
premier plan jusqu’à 15 secondes en attendant la réponse d’un des
serveurs NTP configurés.Le contrôleur ntpctl
est un programme qui affiche les informations liées
au service ntpd(8).
Les options possibles sont :
-s all | peers | Sensors | status
:
all
: affiche toutes les informations possiblespeers
: affiche les informations relatives à chaque pairSensors
: affiche les informations relatives à chaque capteur.status
: indique l’état des pairs et des capteurs, et si l’horloge du système est synchronisée.Le contrôleur est apparu la première fois dans OpenBSD 5.5.
⇒ les différents manpage :
/etc/examples/ntpd.conf
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
OpenBSD fournit des outils bien pratiques pour gérer l’installation, la mise à jour, la suppression des paquets officiels :
-u
pour mettre à jour.pkg_info -Q nom_du_paquet
pkg_add nom_du_paquet
pkg_delete nom_du_paquet
pkg_delete -a
pkg_check
Vous trouverez plus d’informations sur la page “Package Management” (en) de la FAQ Officielle d’OpenBSD…
Il faut définir la variable d’environnement http_proxy
.
Dans votre fichier ~/.profile
, insérez la ligne suivante :
export http_proxy=http://utilisateur_du_proxy:mot_de_passe@ip_du_proxy:port
Retrouvez ci-dessous les erreurs courantes :
Lors d’une installation de paquet interrompue pour une raison ou une autre,
pkg_ retient le paquet avec le nom partial-nom_du_paquet
.
Il vaut mieux les supprimer.
Au secours, plus rien ne fonctionne comme je veux !!!
Un petit coup de pkg_check
et hop, votre OpenBSD revit !
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
sysupgrade [-fkn] [-r | -s] [installurl]
sysupgrade est un utilitaire pour mettre à niveau OpenBSD vers la nouvelle version (release) ou un nouvel instantané (snapshot) si disponible.
sysupgrade télécharge les fichiers nécessaires vers _/home/sysupgrade, les vérifie avec signify(1), et copie bsd.rd vers /bsd.upgrade.
sysupgrade redémarre par défaut le système. Le chargeur de démarrage choisira automatiquement /bsd.upgrade, déclenchant une mise à niveau en une seule fois utilisant les fichiers déposés dans _/home/sysupgrade.
Les options sont les suivantes :
sysupgrade est apparu la première fois dans OpenBSD 6.6
Traduction du manpage sysupgrade(8) !
À-partir d’OpenBSD 6.7, sysupgrade
invoque l’outil
fw_update(1). (cf : 6.7) :
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Le fichier /etc/installurl
contient une simple ligne spécifiant un serveur
miroir d’OpenBSD, tel que :
https://ftp.openbsd.org/pub/OpenBSD
Il est créé par le script d’installation durant les phases d’installation et de mises à niveau par le biais d’HTTP.
Les lignes vides et les lignes commençant par le symbole ‘#’ dans le fichier sont ignorées.
/etc/installurl
Traduction du manpage installurl(5) !
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Pandoc n’est pas empaqueté sous OpenBSD. On peut quand même l’installer, mais il faut passer par le biais de l’outil cabal !
Modifiez le fichier /etc/login.conf
pour avoir la ligne suivante :
:datasize-cur=infinity:\
Dans la section “default” si vous voulez le permettre pour tous les utilisateurs, sinon pour seulement la section “staff”.
En plus, d’installer
l’outil cabal-install
, il semble nécessaire d’installer aussi le
paquet ghc
.
Deuxièmement, il importe de faire les
modifications systèmes
nécessaires pour l’usage correct de cabal
.
Ensuite, utilisez cabal
de manière à installer pandoc
.
$ cabal new-update
$ cabal new-install pandoc
Si une erreur de ce type apparaît:
ghc-pkg: /home/hvr/.cabal/store/ghc-8.6.6/package.db: getDirectoryContents:openDirStream: does not exist (No such file or directory)
Créez les dossiers manquants avant l’installation de pandoc:
mkdir -p $HOME/.cabal/store/ghc-8.6.4/
ghc-pkg init $HOME/.cabal/store/ghc-8.6.4/package.db
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
hotplug-diskmount est
un plugin pour le hotplugd(8)
d’OpenBSD qui monte automatiquement les périphériques à chaud.
Il fonctionne avec tout type de disque (des périphériques de stockage de
masse USB, des lecteurs de cartes, et CD/DVD) et il est prévu pour être
utilisé dans des environnements d’utilisateur uniques tels que des
ordinateurs de bureau ou des portables.
hotplug-diskmount semble se baser sur la détection des informations qui sont retournées par disklabel, aussi !
hotplug-diskmount gère les partitions de type :
Depuis la version 6.1, OpenBSD utilise la version 1.0.2 du projet !
Veuillez à mettre-à-niveau !
OpenBSD 6.0 utilise la version 0.9 - elle est clairement dépassée, et peut ne pas fonctionner sur certains périphériques ; la raison est que depuis février 2015, date de sortie de la v0.9, la structure du fonctionnement de l’outil ‘disklabel(8)’ a été modifiée. Dans ce contexte, il serait plus intéressant d’utiliser la version de l’arbre des ports, à ce jour la v1.0.
Néanmoins, il vaut mieux utiliser la version 1.0.2, car celle-ci ajoute le support ntfs grâce à l’ajout de la gestion du projet fuse(4).
Installez
le
paquet fuse
.
Il suffit d’[[system:base:pkg|installer]] le paquet hotplug-diskmount
.
Veuillez à mettre-à-jour !
Il est IMPORTANT d’initialiser le projet pour créer son répertoire de
montage par défaut - normalement /vol
:
# /usr/local/libexec/hotplug-diskmount init
Il est intéressant à noter que l’on peut spécifier un répertoire cible
en utilisant l’option -d
, tel que :
# /usr/local/libexec/hotplug-diskmount -d /mnt/$USER init
Il est ensuite nécessaire d’
activer le service
hotplugd
…
Il faut créer/modifier le fichier /etc/hotplug/attach
:
# nano /etc/hotplug/attach
#!/bin/sh
DEVCLASS=${1}
DEVNAME=${2}
LOGIN="votre_id_user"
case "${DEVCLASS}" in
2)
/usr/local/libexec/hotplug-diskmount attach -u "${LOGIN}" -m 0700 "${DEVNAME}"
;;
esac
puis veillez à ce qu’il soit exécutable :
# chmod +x /etc/hotplug/attach
ATTENTION : Toute modification dans ce fichier nécessitera le redémarrage du démon hotplugd !
Autrement, celles-ci ne seront pas prises en compte.
Démarrez le service
hotplugd
afin que les modifications soient gérées !
Après avoir inséré votre périphérique USB, ou CD-Rom…
En mode console :
$ mount
(…)
/dev/sd1i on /vol/DataTraveler 3. type msdos (local, nodev, nosuid, uid=1000, gid=0, mask=0700)
$ ls -al /vol/
total 44
drwxr-xr-x 4 root wheel 512 Sep 15 22:50 .
drwxr-xr-x 15 root wheel 512 Sep 12 23:04 ..
drwx------ 2 root wheel 512 Sep 15 22:50 .db
drwx------ 1 votre_id_user wheel 16384 Jan 1 1980 DataTraveler 3.
En mode graphique, utilisez donc votre navigateur de fichiers,
dirigez-vous vers le volume /vol
- ou le répertoire cible que vous
auriez précisé - où vous trouverez un répertoire créé automatiquement
selon le label correspondant à votre périphérique.
/usr/local/share/doc/pkg-readmes/hotplug-diskmount
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
ConsoleKit2 est un framework permettant de définir et de suivre les utilisateurs, les sessions de connexion et les seats. Il permet à de multiples utilisateurs d’être connectés en même temps et de partager le matériel pour leur session graphique. ConsoleKit2 gardera une trace de ces ressources et, quelle que soit la session active, utilisera le matériel à ce moment-là.
Un seat est une collection de sessions et de paramètres matériels (habituellement au moins un clavier et une souris). Une seule session peut être active à la fois par seat.
Une session est une collection de tous les processus qui proviennent
d’un seul ancêtre commun et qui conservent la connaissance d’un secret.
En tant que détail d’implémentation, ce secret peut être enregistré dans
un processus d’environnement par le gestionnaire de session sous le nom
de XDG_SESSION_COOKIE
.
Installez
les
paquets consolekit2 polkit
.
Pour activer consolekit
dans une session graphique, il est nécessaire
de préfixer le binaire ck-launch-session
dans le script de session,
tel que :
/usr/local/bin/ck-launch-session /usr/local/bin/openbox-session
Le gestionnaire de session gdm
s’occupe automatiquement de cette
fonction
Il est nécessaire que le service system-wide D-Bus
fonctionne en premier.
messagebus
history
Il peut être utile, du fait que le journal history
puisse devenir gros,
de prévoir de faire une rotation de celui-ci.
Ouvrez, avec vos droits administrateurs, le fichier /etc/newsyslog.conf
et ajouter, par exemple, la ligne suivante :
/var/log/ConsoleKit/history root:wheel 640 7 * * Z
Puis, relancez newsyslog
…
Après l’installation, n’oubliez pas de lire le fichier
/usr/local/share/doc/pkg-readmes/consolekit2
!
Vous pouvez aussi lire les exemples :
/usr/local/share/examples/consolekit/
/usr/local/share/examples/polkit/
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Anacron est un ordonnanceur de commandes périodiques. Il exécute des commandes à intervalles spécifiées par jours. À la différence de cron, il n’a pas besoin que le système fonctionne en continue. Il peut toutefois être utilisé pour contrôler l’exécution de travaux quotidiens, hebdomadaires et mensuels (ou toute autre période de n jours), sur des systèmes qui ne fonctionnent pas 24 heures par jour. Quand il est installé et configuré proprement, Anacron s’assurera que les commandes soient exécutées aux intervalles spécifiées aussi précisément que le permet la disponibilité de la machine.
Ce que ne fait pas Anacron : Anacron n’essaie pas de faire un cron redondant. Il ne peut être utilisé pour programmer des commandes à des intervalles plus petites que la journée. Il ne garantit pas que les commandes seront exécutées à heure ou jour spécifique. Ce n’est pas un démon à plein temps. Il est exécuté depuis des scripts de démarrage, des travaux cron, ou explicitement.
Installez
le
paquet anacron
.
Ce dernier est souvent utilisé en tant qu’administrateur. On rajoute dans
ce cas les tâches à effectuer dans le fichier /etc/anacrontab
puis on
le lance à chaque démarrage avec une nouvelle entrée dans /etc/rc.local
:
/usr/local/sbin/anacron -ds
Ce n’est pas très intéressant sur une machine de bureau où l’on peut vouloir lancer des commandes spécifiques aux utilisateurs (pour utiliser les clés ssh par exemple).
On crée le fichier ~/.anacron/anacrontab
:
$ mkdir -p ~/.anacron/
$ vi ~/.anacron/anacrontab
On écrit dans ce fichier sur chaque ligne les tâches à lancer régulièrement :
# period delay job-identifier command
# sauvegarde des cours
# <Tous les n jours> <séparé de 10 minutes avec les autres tâches> <nom de la tâche> <commande à lancer>
1 10 educ /home/xavier/geek/bin/sauvegarde/synccours
# sauvegarde des documents
7 10 backup /home/xavier/geek/bin/sauvegarde/backup_home
#sauvegarde du serveur web
7 10 webbackup /home/xavier/geek/bin/sauvegarde/savewww
Notez qu’inscrire 1
en premier revient à écrire @daily
pour lancer
la commande chaque jour, et 7
à @weekly
pour la lancer de façon
hebdomadaire.
Afin d’avoir les droits de lancer anacron en tant qu’utilisateur et
écrire dans la file d’attente, on peut s’ajouter dans le groupe wheel
.
Il existe peut-être une meilleure solution, comme définir un emplacement
de file d’attente différent que celui par défaut, mais je ne l’ai pas
encore trouvé.
# usermod -G wheel jdoe
On donne les droits pour le groupe wheel d’écrire dans la liste d’attente :
# chmod g+xrw /var/spool/anacron
Enfin, pour lancer anacron à chaque démarrage, on peut mettre dans le
fichier ~.profile
ceci :
/usr/local/sbin/anacron -s -t ~/.anacron/anacrontab
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
L’IDE PyCharm fournit une complétion de code intelligente, l’inspection du code, le surlignement des erreurs à la volée, des correctifs rapides, des modifications automatiques du code et offre des fonctionnalités avancées de navigation.
Installez
le paquet pycham
.
Après l’installation, n’oubliez pas de lire le fichier /usr/local/share/doc/pkg-readmes/pycharm
! ;-)
Au lancement, vous avez la fenêtre d’erreur xmessage
:
De même, si vous l’exécutez en mode console, vous avez le message suivant :
$ pycharm
/usr/local/bin/pycharm[41]: ulimit: bad -d limit: Invalid argument
egrep: -: No such file or directory
Error occurred during initialization of VM
Could not reserve enough space for 768000KB object heap
Il est nécessaire de modifier la limite système datasize-cur
à une
valeur minimale de 2G
.
Redémarrez votre session, avant de chercher à utiliser PyCharm !
Si l’écran d’accueil s’affiche mais que vous ne voyez alors qu’un écran
principal gris, installez le package
wmname
et exécutez :
wmname LG3D
C’est un problème vu avec certaines applications basées sur Java utilisées avec un gestionnaire de fenêtre non réparateur (tel que cwm (gestionnaire de fenêtres) / OpenBSD.
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Tor est un système de communication anonyme à latence basse qui protège les flux TCP : navigation web, messagerie instantanée, irc, ssh, etc…
Ne pas confondre avec le logiciel Tor Browser / OpenBSD !
Installez
le
paquet tor
.
Par défaut, OpenBSD maintient une limite basse de fichiers ouverts en
même temps. Le service tor
a besoin pour fonctionner correctement
qu’elles soient augmentées.
/etc/login.conf
Ajoutez ce qui suit :
tor:\
:openfiles-max=13500:\
:tc=daemon:
kern.maxfiles
Il semble nécessaire d’augmenter la limite des descripteurs de fichiers gérés par le noyau :
# echo "kern.maxfiles=16000" >> /etc/sysctl.conf
$ sysctl kern.maxfiles=16000
Pour utiliser un logiciel réseau avec tor, après avoir
activer
et
démarrer
le service,
utilisez le binaire torsocks
tel que :
torsocks -s 127.0.0.1 -P 9050 nom-binaire
Pour un logiciel graphique, tel Firefox, allez dans les paramètres de préférences réseaux, puis configurez le proxy socks en choisissant, si possible :
⇒ menu Édition > Paramètres
⇒ puis, dans la fenêtre ‘Paramètre de connexion’, choisir :
127.0.0.1
9050
— normalement est le port par défaut de
connexion établie par TorVoir la capture écran ci-jointe :
Tutoriel complémentaire : https://community.torproject.org/relay/setup/guard/openbsd/
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Le logiciel OpenJDK inclut des outils utiles pour le développement et les tests de programmes écrits dans le langage de programmation Java et s’exécutant dans une plate-forme Java.
Installez
le paquet jdk
.
/usr/local/share/doc/pkg-readmes/jdk
jdk-11*
: /usr/local/share/doc/pkg-readmes/jdk-11
Pensez à modifier votre variable d’environnement PATH
, généralement
depuis votre fichier personnel ~/.profile
, pour y ajouter :
:/usr/local/jre-1.8.0/bin
:/ur/local/jdk-11/bin/
Puis redémarrez votre session !
Par défaut, l’empreinte de la mémoire est réduite à un usage de 256 Mo.
Pour les applications nécessitant plus de mémoire, utilisez l’argument
-XX:CompressedClassSpaceSize
et augmentez en conséquence, selon le besoin.
Le mappage d’adresses IPv4 et IPv6 est désactivé. La conséquence est que jdk utilisera soit les adresses IPv4, soit celles d’IPv6, mais pas les deux en même temps. La gestion de l’adressage IPv4 est activée par défaut. Pour activer IPv6, il vous faut paramétrer les propriétés suivantes au moment de démarrer Java :
-Djava.net.preferIPv4Stack=false
-Djava.net.preferIPv6Stack=true
-Djava.net.preferIPv6Addresses=true
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
OpenBSD est UTF-8 !
Néanmoins, votre clavier quelque soit la langue n’est pas forcément capable de gérer tous les codes Unicode en appuyant simplement sur une seule touche.
Pour pouvoir générer un code Unicode, c’est la combinaison des touches CTRL+Shift+u suivi du code relatif au caractère à imprimer, appelé code Unicode.
tiret “demi-cadratin” :
combinaison CTRL+Shift+u + 2+0+1+3 : –
tiret “cadratin” : CTRL+Shift+u + 2+0+1+4 : —
caractère ✓
: CTRL+Shift+u + 2+7+1+3
un espace insécable :
: CTRL+Shift+u + 0+0+A+0
l’arobase @
: CTRL+Shift+u + 0+0+4+0
etc… oui, les trois points de suspension suivant etc
sont un
seul et même caractère unicode :
CTRL+Shift+u + 2+0+2+6
L’unicode peut être géré par le biais de la touche de composition …
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
CUPS fournit un calque d’impression portable pour les systèmes d’exploitation basés sur UNIX. CUPS fournit des interfaces en ligne de commande de System V et Berkeley.
CUPS utilise IPP (Protocole d’Impression Internet) comme bases pour gérer les queues et travaux d’impressions. Les protocoles des services LPD, SMB et AppSocket (tel que JetDirect) sont supportés avec des fonctionnalités réduites.
CUPS ajoute la recherche d’imprimantes réseaux et PPD (Description d’Imprimante PostScript) basé sur les options d’impression supportées dans le monde réel sous UNIX.
Installez
les
paquets : cups cups-filters cups-libs foomatic-db gutenprint
(cups-pdf
en option)
⇒ Depuis OpenBSD 6.5 : la version du driver Gutenprint a changé (v5.3.x au lieu de v5.2.x) ; modifiez les paramètres de l’imprimante pour lui changer le pilote vers cette nouvelle version !
Depuis OpenBSD 6.2, les binaires lpq
, lpr
, et lprm
ne sont plus
liés symboliquement à /usr/bin
. Il est nécessaire de les utiliser en
les préfixant de /usr/local/bin/
.
Pensez à éditer votre fichier ~/.kshrc
, afin de créer des alias qui
vous seront utiles, en ajoutant le code suivant :
for i in lpq lpr lprm; do alias $i=/usr/local/bin/$i; done
Vous pourrez ainsi les utiliser comme avant !
Pour la découverte des services multicast - mDNS (de type Avahi (Découverte de services multicast DNS), Bonjour, …)
Il nous faut :
cupsd cups_browsed
Voici les règles pare-feu si besoin :
pass in on egress proto tcp from egress:network to egress port 631 flags S/SA modulate state
Cups, à ce moment, devrait être accessible par votre navigateur web préféré, par exemple Firefox , sur : http://localhost:631
cupsctl
: # cupsctl --share-printers
lpadmin
: # lpadmin -E -p printer_name -o printer-is-shared=false
-E
active le chiffrement des données avec le service ;
elle est intégrée aussi aux autres outils ci-dessous.printer-is-shared
permet de partager ou non l’imprimante ;
true
autorise, false
ne le permet paslpoptions
: affiche les options d’une imprimante
-l
: version détailléelpstat
: outil pour obtenir les informations sur les imprimantes
ou le serveur Cups
-l
: affiche une liste détaillée des imprimantes, des travaux
d’impression, etc.-p
: restitue toutes les informations de toutes les imprimantes
configurées ; pour cibler une seule, il suffit de donner son nom
en argument de l’option, tel que dans la commande lpadmin
ci-dessus.-r
: l’état du serveur Cups-t
: restitue toutes les informations d’étatÀ toutes ces commandes, il existe pléthore d’options, veuillez lire les manpages correspondants.
Les deux premières commandes doivent avoir des droits d’administration, ce qui n’est pas le cas des deux autres.
Pour gérer les imprimantes en mode graphiques, il est nécessaire
d’installer
les packages suivants : gtk+2-cups
, gtk+3-cups
et/ou gtk+4-cups
selon votre bureau graphique.
Pour détecter votre imprimante usb, connectez-la sur un port usb, en premier, puis exécuter dans un terminal, la commande suivante :
# usbdevs -vd
Controller /dev/usb3:
addr 1: full speed, self powered, config 1, UHCI root hub(0x0000), Intel(0x8086), rev 1.00
uhub3
port 1 powered
port 2 addr 2: full speed, self powered, config 1, USB MFP(0x082f), EPSON(0x04b8), rev 1.00, iSerialNumber L83010704250947490
ugen0
Il faut repérer sur la ligne Controller /dev/usb
quel numéro est affiché
au périphérique ugen
et usb
, puis donner à ce périphérique les droits
nécessaires - dans ce cas-là :
# chown _cups /dev/ugen0.* /dev/usb3
ou pour une MFP (avec scanner intégré :
# chown _cups:_saned /dev/ugen0.* /dev/usb3
# chmod 0660/dev/ugen0.* /dev/usb3
Pour préserver ces changements, au prochain redémarrage, ajoutez la
commande à votre fichier /etc/[rc.local](http://man.openbsd.org/rc.local)
.
Bien-sûr, modifiez le numéro des périphériques ugen
et usb
utilisés.
Une autre méthode est d’utiliser les scripts attach
/detach
du service
hotplugd
!
Pour pouvoir utiliser correctement votre imprimante sur port usb, il est
nécessaire de désactiver ulpt(4) du noyau
(cf: [config(8)]http://man.openbsd.org/config.8)), autrement votre
imprimante ne sera pas “visible”, car non disponible par le biais de la
bibliothèque libusb
.
⇒ Depuis OpenBSD 7.0, il suffit de remplir/créer le fichier
/etc/bsd.re-config
avec :
disable ulpt
# echo 'disable ulpt' >>/etc/bsd.re-config
puis redémarrer la machine !
⇒ Avant OpenBSD 7.0 :
Pour cela, tapez :
# printf 'disable ulpt\nq\n' | config -ef /bsd
Puis, relinker le noyau :
# sha256 /bsd >/var/db/kernel.SHA256
Pour pouvoir imprimer sur une imprimante port parallèle, le service cups a besoin d’avoir accès aux périphériques spécifiques.
Exécutez la commande suivante :
chown _cups /dev/lp[a,t]0
/etc/rc.local
!Il est nécessaire qu’Avahi (Découverte de services multicast DNS) soit installé
et fonctionnel ; de même, le service cups_browsed
doit être actif sur
votre station !
Elle peut être administrée soit par l’interface d’administration web de Cups, soit avec des droits administrateurs…
Veuillez lire le fichier pkg-readme de cups !
Après l’installation, n’oubliez pas de lire le fichier :
/usr/local/share/doc/pkg-readmes/cups
,/usr/local/share/doc/pkg-readmes/cups-filters
,/usr/local/share/doc/pkg-readmes/cups-pdf
, ainsi que sous /usr/local/share/doc/cups-pdf/README
./usr/local/share/doc/pkg-readmes/foomatic-db-engine
.Depuis OpenBSD 6.2, l’accès aux pages de manuel est sensiblement différent :
man -m /usr/local/man lpr
Cela est vrai pour les binaires lpq
, lpr
et lprm
!
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Le programme en ligne de commande cabal
simplifie le processus de
gestion des logiciels Haskell en automatisant la récupération, configuration,
compilation et installation des programmes et bibliothèques Haskell.
Installez
le
paquet cabal-install
.
Du fait de la protection mémoire W^X, l’outil cabal
ne fonctionne pas
correctement. Pour résoudre cette situation, deux manières de faire :
Pour remédier à la situation, nous allons modifier légèrement votre
$HOME
et /usr/local
.
/usr/local
, avec les
droits administrateurs$HOME
# mkdir -p /usr/local/cabal/build
# chown -R user:wheel /usr/local/cabal
$ rm -rf ~/.cabal
$ ln -s /usr/local/cabal ~/.cabal
Pour finir, créez donc un alias dans votre fichier personnel .khsrc
,
ou .profile
:
alias cabal='env TMPDIR=/usr/local/cabal/build/ cabal'
Ajouter le dossier .cabal à votre variable PATH pour pouvoir lancer les commandes facilement !
PATH=$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:$HOME/.cabal/bin
Prenez conscience qu’utiliser cette possibilité aura pour conséquence de
permettre l’exécution de binaire potentiellement dangereux depuis votre
$HOME
.
Mieux vaut éviter !
Il est possible d’ajouter l’option de montage wxallowed
à votre partition
$HOME si vous l’avez créée.
source : https://deftly.net/posts/2017-10-12-using-cabal-on-openbsd.html
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
SANE signifie Scanner Access Now Easy - que l’on pourait traduire par : Scannérisation Facile
Installez
le paquet sane-backends
.
Ce paquet contient les bibliothèques SANE (le backend et la partie réseau)
ainsi que l’outil en ligne de commande scanimage
.
Puisque la scannerisation par USB peut être gérée par la bibliothèque
libusb
, nous avons besoin d’autoriser l’utilisateur _saned
au point
de montage USB correspondant.
Trouvez où votre scanner est attaché :
# usbdevs -vd
afin de changer les droits appropriés.
Pour l’exemple suivant :
Controller /dev/usb3:
addr 1: full speed, self powered, config 1, UHCI root hub(0x0000), Intel(0x8086), rev 1.00
uhub3
port 1 powered
port 2 addr 2: full speed, self powered, config 1, USB MFP(0x082f), EPSON(0x04b8), rev 1.00, iSerialNumber L83010704250947490
ugen0
il vous faudra utiliser : # chgrp _saned /dev/ugen0.* /dev/usb3
sur le périphérique /dev/usb3
.
La raison pour laquelle nous changeons le groupe et non pas l’utilisateur est que cela permet à des périphériques multi-fonctions de fonctionner à la fois pour l’impression et pour la scannérisation.
(par exemple, en appartenant à _cups:_saned
).
Pour préserver vos changements après une mise à niveau du système :
chown _cups:_saned /dev/ugen0.* /dev/usb1
attach
et detach
d’hotplugd(8) peuvent l’automatiser.Vous pouvez aussi garantir l’accès direct au scanner en ajoutant les
utilisateurs au groupe _saned
.
Par défaut, le service saned(8) fonctionne en tant que _saned
, ainsi
vous devez autoriser l’utilisateur _saned
a accéder au nœud du périphérique
du scanner.
SANE prend en charge seulement les périphériques supportés par le pilote SCSI générique uk(4).
Assurez-vous que votre utilisateur ait les accès sur le nœud du périphérique du scanner, sinon, vous ne serez pas capable de scanner.
Certains backends (tel que sane-plustek(5)) utilisent un verrouillage
fichier (lockfile) pour permettre les accès multiples au scanner. Si vous
utilisez de tels backends, vous devez vous ajouter au groupe _saned
,
sinon vous ne serez pas capable de scanner.
/usr/local/share/doc/pkg-readmes/sane-backends
/usr/local/share/doc/sane-backends/
/usr/local/share/doc/sane-backends/PROBLEMS
/usr/local/share/exemples/sane-backends/
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Inkscape est un logiciel d’édition de graphisme vectoriel utilisant le format de fichier SVG, norme du W3C.
Installez
le paquet inkscape
.
/usr/local/share/doc/pkg-readmes/inkscape
Aucune extension écrite dans le langage Ruby n’est fournie avec le paquet Inkscape.
Si vous voulez en installer, ou en écrire, il vous faudra installer d’abord le langage Ruby :
ruby-2.6
, pour OpenBSD 6.6, 6.7ruby-2.5.5
, au minimum, pour OpenBSD 6.5.ruby-2.4.4
, au minimum, pour OpenBSD 6.4.Inkscape n’est pas résilient sur l’oubli du paramétrage de l’icône et peut crasher (par exemple, lors de l’ouverture du menu fichier > “Propriétés du document”)
Si vous voulez spécifier un icône personnalisé dans votre thème
~/.gtkrc-2.0
, veuillez d’abord vous assurer de la présence effective
sur votre système de fichiers et de sa bonne localisation !
Bogue #1238142
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
FFmpeg est une solution complète pour enregistrer, convertir et émettre des flux audio et vidéo. Il inclut la principale bibliothèque de codec audio et vidéo libavcodec.
Installez
le paquet ffmpeg
.
Les périphériques de capture vidéo et tuners TV de la marque Brooktree sont gérés par le pilote bktr(4), seulement pris en charge sur les architectures amd64, i386 et powerpc.
Ils peuvent être contrôlés au moyen des variables d’environnements suivantes :
BKTR_DEV=
{0|1|2|3|4} en sélectionnant le périphérique d’entrée adéquat
(relatif au tuner, la caméra, etc…)BKTR_FORMAT=
{1|2|3|4|5|6} où :
BKTR_FREQUENCY=
xxx.yy où xxx.yy représente la fréquence à
paramétrer en Mhz.N’oubliez pas de lire le fichier pkg-readme : /usr/local/share/doc/pkg-readmes/ffmpeg
!
Vous pouvez lire aussi :
/usr/local/share/doc/ffmpeg
/usr/local/share/examples/ffmpeg
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
QEMU est un émulateur machine open source. Il peut exécuter des systèmes d’exploitations et des programmes faits pour une machine (càd, une carte ARM) sur une machine différente (càd, votre propre PC).
Installez
le paquet qemu
.
$ ftp ftp://ftp.openbsd.org/pub/OpenBSD/snapshots/i386/cd52.iso
$ ftp ftp://ftp.openbsd.org/pub/OpenBSD/snapshots/amd64/cd52.iso
$ ftp ftp://ftp.openbsd.org/pub/OpenBSD/snapshots/sparc/cd52.iso
$ qemu-img create -f qcow2 virtual.img 10G
$ qemu-system-i386 -m 32 -monitor stdio -no-fd-bootchk -hda virtual.img -cdrom cd52.iso -boot d
$ qemu-system-x86_64 -m 32 -monitor stdio -no-fd-bootchk -hda virtual.img -cdrom cd52.iso -boot d
$ qemu-system-sparc -m 32 -monitor stdio -hda virtual.img -cdrom cd52.iso -boot d
Notes :
xterm
ou équivalent.-no-fd-bootchk
permet un démarrage plus rapide quand il
n’y a pas de lecteur disquette
qemu-system-sparc
.qemu-system-ppc*
et qemu-system-sparc*
échoue actuellement avec
l’usage des drapeaux malloc J
ou S
$ qemu-img convert -c -O qcow2 virtual.img v.tmp && mv v.tmp virtual.img
$ qemu-system-i386 -m 32 -nographic -no-fd-bootchk -hda virtual.img
$ qemu-system-x86_64 -m 32 -nographic -no-fd-bootchk -hda virtual.img
$ qemu-system-sparc -m 32 -nographic -hda virtual.img
Par défaut, QEMU définit les paramètres réseaux suivants :
-net nic,vlan=0,model=e1000,macaddr=52:54:00:12:34:56
-net user,vlan=0
De même, à l’intérieur du mode réseau virtuel, il utilise le segment
10.0.2.0/24
et dessert DHCP à l’intérieur du réseau virtuel.
Des adresses statiques peuvent être utilisées s’il n’est pas possible
d’utiliser DHCP dans l’hôte invité :
C’est suffisant pour la plupart des opérations, QEMU assume la NAT lui-même et permet au réseau de l’espace utilisateur de faire des opérations TCP/UDP. ICMP et autres aspects réseaux ne sont pas possible dans ce mode.
-net
en ligne de commande, QEMU
présume que vous savez ce que vous faîtes et nettoie les valeurs par défaut
pour le reste des paramètres par défaut -net
./etc/resolv.conf
contient seulement des serveurs DNS IPv6.Parfois il est souhaitable de configurer QEMU pour accéder au réseau
directement via la Couche de niveau 2. Une manière de faire cela sans
exécuter QEMU avec les droits root est de laisser root ouvrir le
périphérique /dev/tapN
et de passer le fichier descripteur à QEMU.
L’interface tap(4) devrait être de
préférence configurée avant de démarrer QEMU :
# ifconfig tap0 192.168.0.254
L’interface peut aussi être configurée comme partie de
bridge(4), dans ce cas l’adresse ip
peut être omise :
# ifconfig bridge0 add tap0 add em0 up
Les interfaces tunnel et bridge peuvent aussi être configurées au démarrage
du système en éditant les fichiers /etc/hostname.tapN
et
/etc/hostname.bridgeN
, respectivement
(voir hostname.if(5)).
Après la configuration du réseau virtuel, nous pouvons utiliser doas
pour laisser root ouvrir le périphérique tunnel et ensuite utiliser encore
doas
pour supprimer les privilèges et démarrer QEMU :
$ doas sh -c "doas -u $USER qemu-system-i386 -nographic -net nic -net tap,fd=3 -no-fd-bootchk -hda virtual.img 3<>/dev/tap0"
NOTE : si vous utilisez sudo
à la place de doas
, souvenez vous que
sudo appelle closefrom(2)
.
Avant d’avoir plus d’un fd
passant l’interface tap
, ajouter une ligne
à sudoers
ressemblant à :
Defaults closefrom_override
et appeler sudo
via sudo -C 5 -u $USER qemu-system-i386 …
est requis.
Voir sudoers(5) et sudo(8) pour les détails.
Une alternative à la procédure décrite ci-dessus est de laisser QEMU
paramétrer le réseau via le fichier /etc/qemu-ifup
. Ceci n’est toutefois
pas recommandé, puisque vous allez exécuter QEMU avec les droits root,
et qu’il n’y a pas de moyen de supprimer les privilèges root à ce niveau.
/etc/qemu-ifup
contient quelques paramètres par défaut qui permettent
de faire ce qui suit :
# qemu-system-i386 -net nic -net tap -no-fd-bootchk -hda virtual.img
Cela présume que vous souhaitez que l’interface tap(4)
discute avec l’interface gérant la route IPv4 par défaut (basculant sur
trunk0
si aucune route n’est trouvée), et que vous voulez que bridge0
soit utilisée en tant que bridge en second.
Paramétrer les variables d’environnement ETHER
et BRIDGE
surchargera
ces paramètres, respectivement.
Lors du démarrage de QEMU, le script essaie de sortir les informations
utiles, mais il peut y avoir des messages d’erreurs qui apparaissent,
aussi bien. Sur mon laptop, je veux router NAT nativement en utilisant PF
et aussi en ayant accès à la couche de niveau 2 vers le réseau de QEMU.
J’ai donc ceci dans le fichier /etc/hostname.trunk101
:
inet6 fe80::1c 64 lladdr 00:03:25:0d:7a:2c
inet 10.7.255.1 255.255.255.0
inet6 alias 2001:240:58a:45::1c
J’ai configuré dhcpd pour s’exécuter sur trunk101, et aussi rad.
Pour QEMU, le démarrage ressemble à cela :
# export ETHER=trunk101
# export BRIDGE=bridge101
# qemu-system-i386 -net nic,vlan=0,macaddr=52:54:00:12:35:00 \
-net tap,vlan=0 -vnc :0 -localtime -usb -usbdevice tablet \
-m 256 -no-fd-bootchk -hda virtual.img -monitor stdio
{tap0 (bridge101 <-> trunk101)ifconfig: bridge101: No such process
ifconfig: bridge101: No such process
}
(qemu)
Ces erreurs sont normales et doivent être ignorées. Vérifiez que le réseau est proprement configurée en vérifiant l’interface bridge :
$ ifconfig bridge101
bridge101: flags=41<UP,RUNNING>
groups: bridge
priority 32768 hellotime 2 fwddelay 15 maxage 20 holdcnt 6 proto rstp
designated: id 00:00:00:00:00:00 priority 0
tap0 flags=3<LEARNING,DISCOVER>
port 16 ifpriority 0 ifcost 0
trunk101 flags=3<LEARNING,DISCOVER>
port 6 ifpriority 0 ifcost 0
Addresses (max cache: 100, timeout: 240):
52:54:00:12:34:56
pour chaque instance QEMU. Pour changer cela,
observez la syntaxe macaddr=
dans l’exemple ci-dessus et choisissez un
lladdr
unique par interface QEMU.NOTE : Certains systèmes d’exploitation fonctionnent mieux avec le périphérique
USB tablet
qu’avec le périphérique normal de souris PS/2.
Voir l’exemple ci-dessus pour l’usage.
-usb -usbdevice tablet
Installer OpenBSD via la console série est parfois désirable. X peut ne pas être disponible… Il y a deux manières d’accomplir cela, les deux offrant la même solution :
a. qemu-system-i386 -vnc :0 -serial stdio .. virtual.img -cdrom install52.iso -boot d
set tty com0
à l’invite
boot>
.b. qemu-system-i386 -nographic .. virtual.img -fda floppy52.fs -boot a
-nographic
.vnconfig vnd0 floppy52.fs
mount /dev/vnd0c /mnt
mkdir /mnt/etc
echo set tty com0 > /mnt/etc/boot.conf
umount /mnt
vnconfig -u vnd0
yes
pour paramétrer com0
en tant que console série.Parfois, vous voulez que QEMU démarre en tant que script système.
En plus des options ci-dessus, l’option -daemonize
est très pratique,
de même que pour désigner telnet:
pour -serial
et -monitor
.
hddir=/var/vm
USER=qemu
if [ -x /usr/local/bin/qemu ]; then
echo -n 'Qemu: vmi386'
(
ifconfig bridge101 add trunk101 add tap0 up
sh -c "doas -u $USER \
/usr/local/bin/qemu-system-i386 \
-daemonize \
-nographic \
-net nic,vlan=0,macaddr=52:54:00:4e:62:8f \
-net tap,vlan=0,fd=3 \
-m 128 \
-hda $hddir/virtual.img \
-serial telnet:127.0.0.1:1080,server,nowait \
-monitor telnet:127.0.0.1:1081,server,nowait \
-no-fd-bootchk 3<>/dev/tap0"
)
echo "."
fi
qemu
existe, créez-le ou paramétrez
USER=
en lui donnant un utilisateur existant pour utiliser cet exemple./usr/local/share/doc/pkg-readmes/qemu
J’ai écrit historiquement de manière collaborative cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
memcached est un service de mise en cache d’objet mémoire flexible conçu pour alléger la charge des bases de données dans les applications Web dynamiques en stockant des objets en mémoire.
Installez le paquet ‘‘memcached’’.
Pour améliorer la “sécurité” du service :
Paramétrons
le service memcached
pour n’utiliser que l’utilisateur _memcached
,
l’interface locale, et interdire toute activité UDP :
"-u _memcached -l 127.0.0.1 -U 0"
Démarrons le service memcached.
Il est possible d’utiliser la règle PF suivante pour interdire toute connexion sur le port d’écoute du service de memcached :
block in log on egress proto tcp to egress port 11211
La principale documentation est le manpage :
$ man memcached
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Ce problème existait sous OpenBSD 6.3, 6.4.
Il semble que cela soit corrigé depuis OpenBSD 6.6 !
Votre clavier dysfonctionne et accentue de plusieurs fois la touche appuyée sans que vous désiriez la doubler.
Ne cherchez pas à modifier vos paramétrages clavier - ce n’est pas votre clavier qui pose problème en réalité !
C’est l’horloge matérielle par défaut * tsc* qui dans certains cas pose ce problème - que votre architecture soit basée sur un CPU Intel ou AMD n’y change rien.
Il est nécessaire de la changer pour choisir acpihpet0
:
sysctl -w kern.timecounter.hardware=acpihpet0
Pour que le changement soit permanent, veuillez créer, avec des droits
administrateurs, si ce n’est pas déjà fait, le fichier /etc/sysctl.conf
pour y ajouter kern.timecounter.hardware=acpihpet0
.
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Créez un fichier /etc/hostname.interface
- où interface
est le nom
de l’interface réseau - et remplissez-le avec les informations suivantes.
Exemple de fichier /etc/hostname.rtwn0
:
Depuis OpenBSD 6.9, le démon dhcpleased(8) est apparu, pour gérer le protocole dhcpd sur les stations clientes.
Utiliser la configuration autoconf
plutôt que dhcp
, tel que pour
l’exemple :
nwid nom_du_point_d_acces wpakey cle_wpa_impossible_à_deviner
inet autoconf
inet6 autoconf
Selon le manpage hostname.if(5)
actuel, le terme dhcp
est/devient l’abbréviation de la commande
inet autoconf
.
Conformément au changement de syntaxe et recommandation faites depuis OpenBSD 6.4,
le mot clé wpakey
doit être sur la même ligne que le mot clé nwid
ou
join
.
nwid nom_du_point_d_acces wpakey cle_wpa_impossible_à_deviner
dhcp
nwid nom_du_point_d_acces
wpa-key cle_wpa_impossible_à_deviner
dhcp
Ajouter à votre fichier de configuration, le flag : nwflag stayauth
Pour (re?)trouver votre point d’accès, exécutez :
# ifconfig rtwn0 scan
Retrouvez ci-dessous des exemples de configuration - à adapter à vos besoins !
Pour trouver et me connecter facilement aux différents réseaux wifi, je me suis créé un petit script.
Il est rudimentaire et peut être amélioré mais il fonctionne :)
$ vi /usr/local/bin/wifiup
#!/bin/sh
# On réveille la carte :
ifconfig iwn0 up
# On scanne les réseaux pour trouver leur identifiant :
ifconfig iwn0 scan | grep -i nwid
# Choix du réseau :
echo "A quel réseau se connecter ?"
read _NWID
echo "\nPhrase de passe ?"
# Attention, la phrase de passe apparaît en clair l'écran :
read _PASS
# Connexion au réseau utilisant une clé WPA (qui utilise encore du WEP ?) :
ifconfig iwn0 nwid "$_NWID" wpakey "$_PASS"
# Abtention d'une adresse IP :
dhclient iwn0
Pour que ce script puisse être lancé en simple utilisateur, ajouter
l’entrée suivante dans /etc/doas.conf
:
permit nopass $USER as root cmd /usr/local/bin/wifiup
Bien entendu, changez “$USER” par votre login.
Pour lancer le script, il suffit de lancer :
# /usr/local/bin/wifiup
Et vite s’en faire un alias pour plus de confort ! :)
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
En premier lieu, il vous faut activer la vidéo .
Sous OpenBSD, la webcam est souvent identifiée par /dev/video0
.
Afin de vérifier que votre webcam est reconnue, utilisez usbdevs
:
$ usbdevs -v
Controller /dev/usb0:
(…)
port 6 addr 4: high speed, power 200 mA, config 1, Integrated Camera(0xb221), Chicony Electronics Co., Ltd.(0x04f2), rev 7.52
(…)
Ou encore dmesg :
$ dmesg | grep video0
(…)
uvideo0 at uhub3 port 6 configuration 1 interface 0 "Chicony Electronics Co., Ltd. Integrated Camera" rev 2.00/7.52 addr 4
Afin que le logiciel que vous préférez puisse accéder à la webcam sans
les droits administrateurs, il faut modifier les droits d’écriture sur
/dev/video0
.
Cela consiste à vous déclarer propriétaire de /dev/video0
:
$ doas chown votre_nom_d_utilisateur /dev/video0
Note : Si plusieurs utilisateurs utilisent l’ordinateur, il faudra
insérer cette commande au lancement de la session. Si le gestionnaire de
connexion est xenodm
, ça sera
dans le fichier /etc/X11/xenodm/TakeConsole
ou /etc/X11/xenodm/Xstartup
.
Désignez dans ce cas le nom d’utilisateur avec $USER
.
L’astuce est de modifier votre fichier .xsession
, tel que :
if [ -c /dev/video0 ]; then doas chown $USER /dev/video0; fi
Le contrôle des paramètres de la webcam se fait avec la commande
video(1)
, tel que :
$ video -c
Par exemple, le paramétrage de la luminosité ainsi :
video brightness=200
brightness: 128 -> 200
Pour afficher en direct ce que votre caméra filme avec mpv :
$ mpv av://v4l2:/dev/video0
Lire la page fswebcam .
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Lisez notre page de configuration système : [[tutoriel:openbsd-mount-usb]]
Merci de lire le chapitre notre page : [[tutoriel:openbsd-mount-usb#methode-manuelle]]
Pour formater une clé USB, de même que tout type de disque dur, on
utilisera la commande newfs
(8).
Les types de formats de fichiers suivants sont supportés :
Ce sont ceux pris en charge par fstab(5).
Il y a deux manières de s’y prendre :
newfs -t *type* device
où type est le type de format, parmi ceux sus-citésnewfs_*type* device
newfs
est une commande suffisamment intelligente, qui lorsqu’elle est
écrite avec l’option -t
redirige vers l’équivalente de la seconde
écriture.
Après avoir utilisé dmesg
pour identifier notre périphérique comme
expliqué ici, nous allons utiliser la commande newfs_msdos
pour
formater une clé USB en FAT32 :
Admettons que la clé soit remontée en tant que /dev/sd2
et qu’une
partition soit présente dessus.
# newfs_msdos -F 32 /dev/rsd2a
Une fois formatée, la partition apparaîtra en tant que /dev/sd2i
et
pourra être montée et utilisée.
Les clés USB de sécurité, à la norme FIDO/U2F, sont utilisables depuis OpenBSD 6.7, grâce au pilote fido(4).
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Python fait partie du système de base d’OpenBSD.
Cette erreur est générée par le fait de la protection mémoire W^X !
Deux manières de résoudre le problème :
Pour remédier à la situation, nous allons modifier légèrement votre
$HOME
et /usr/local
, avec les droits administrateurs.
/usr/local
,# mkdir -p /usr/local/${my_user}/python
# chown -R ${my_user}:wheel /usr/local/${my_user}
# ln -s /usr/local/${my_user}/python $home/python
… où ${my_user}
représente votre identifiant utilisateur.
Pour l’utilitaire pipenv
, il
faut modifier ceci aussi :
$ mkdir /usr/local/$USER/python/virtualenvs
$ ln -s /usr/local/$USER/python/virtualenvs $HOME/.local/share/virtualenvs
Prenez conscience qu’utiliser cette possibilité aura pour conséquence de
permettre l’exécution de binaire potentiellement dangereux depuis votre
$HOME
.
Mieux vaut éviter !
Il est possible d’ajouter l’option de montage wxallowed
à votre
partition $HOME si vous l’avez créée.
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
# for file in $(pkg_info -Q fonts | grep -v installed); do pkg_add $file; done
# for file in $(pkg_info -Q icon-theme | grep -v installed); do pkg_add $file; done
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Cette documentation traitera de l’usage du gestionnaire de filtrage “pare-feu” nommé PF…
L’outil pfctl
permet de contrôler l’état du parefeu.
Le fichier /etc/pf.conf
permet de gérer la configuration
Par défaut, rien à installer par soi-même… il est inclus de base.
Depuis la version 4.6 d’OpenBSD, il n’est plus nécessaire de l’activer, puisqu’il l’est par défaut.
Cette section traite de l’usage de l’outil pfctl
:
Note : L’usage de l’outil pfctl
nécessite des droits administrateur…
pensez-y !
Quelques informations à-propos des options de pfctl :
-d
: arrête le parefeu-e
: activer, vérifier l’état de pf-ef
: activer le parefeu tout en ciblant le fichier de
configuration, tel que : -ef /etc/pf.conf
-f
: permet de recharger les nouvelles règles à partir du fichier.-F
: permet de vider toutes les règles et autres tables du parefeu-nf
: permet de vérifier les règles écrites dans un fichier,
sans les charger.-r
: permet de faire du reverse dns-s
: afficher les informations d’état…
voir plus bas, pour plus d’infos.-t
: spécifie une action précise sur une table particulière,
tel que : -t <table_nom> -T command adr_ip
-v
: est le mode verbeuxDe plus amples informations dans le manpage correspondant !
Le fichier de configuration principal du pare-feu PF se nomme :
/etc/pf.conf
Il est possible de créer des sous-fichiers de configuration qui seront
appelés par la directive :
include /etc/pf/filename.conf
Le fichier de configuration est décomposé en plusieurs sections :
De plus amples informations dans le manpage correspondant !
Les listes définissent des critères multiples similaires, tels que les noms de ports, des numéros de protocoles, plusieurs adresses IP, etc.
Les listes sont définies en spécifiant les items par l’usage des crochets { }, chaque item pouvant être séparé soit par un espace, soit par une virgule.
block out on fxp0 from { 192.168.0.1, 10.5.32.6 } to any
Une liste peut contenir une autre liste imbriquée.
Là où les listes se trouvent limiter en usage, les macros prennent facilement le relais
Les macros sont l’équivalent de variables dans les langages informatiques.
Elles définissent une valeur ou un ensemble de valeurs… celles-ci peuvent être une ou plusieurs interfaces réseaux, une ou plusieurs adresses ip, un ou plusieurs numéros de ports, etc… voire une partie d’écriture de règles.
Les macros peuvent contenir des listes, d’autres macros.
⇒ Définition :
_
.pass
, in
, out
…Ces macros, une fois définies, sont utilisées dans le contexte des règles.
⇒ Exemple :
iface = "em0"
http_ports = "{ 80 443 }"
pre = "pass in quick on ep0 inet proto tcp from "
post = "to any port { 80, 6667 }"
Pour plus d’informations, lire : https://www.openbsd.org/faq/pf/shortcuts.html#macros
Les tables sont une collection d’adresses et/ou de réseaux.
C’est une manière très efficace et puissante de gérer un ensemble d’informations, consommant moins de ressources processeur et mémoire.
À privilégier, plutôt qu’une liste de macros, dès que vous voulez gérer un ensemble d’adresses ip !
⇒ Définition :
{ }
sera purgée, lors du chargement…const
, counters
, ou persist
⇒ Drapeaux :
const
: empêche que la table soit ultérieurement altérée, une fois chargée.counter
: active le compte des bits et autres paquets par adresse ip.persist
: force le noyau à garder la table, même si aucune règle se
réfère à elle. Ce drapeau permet l’ajout ultérieur d’informations…⇒ Exemple :
iface = "axe0"
table <private> const { 10/8, 172.16/12, 192.168/16 }
table <badips> persist
block on $iface from { <private>, <badips> } to any
# pfctl -t badips -T add 204.92.77.111
Note : Une table peut être gérée par un ou plusieurs fichiers, qui seront une liste d’adresses ip ou de noms de machines. Une ligne commençant par le symbole dièse ‘#’ est considérée comme un commentaire et sera ignorée.
table <spam> persist file "/dir/filename1"
block on fxp0 from <spam> to any
Les ancres sont un ensemble de règles, qui peuvent être manipulées de manière dynamique.
Elles sont au jeu de règles, ce que les tables sont à la gestion dynamique des adresses ip ou réseaux.
Une ancre est une collection de règles… de tables… voire même d’ancres.
Attention : Pour nommer une ancre, veillez à ne pas utiliser un nom
déjà défini auparavant, même s’il définit une table. L’outil pfctl
vous avertira, sinon, d’une collision de noms dans l’espace global de noms…
à juste titre !
⇒ Utilisation :
anchor nom_ancre {
jeu de règles
}
L’ajout dynamique à la main peut se faire ainsi :
# echo "pass in proto tcp from 192.0.2.3 to any port 22" | pfctl -a nom_ancre -f -
Elles peuvent aussi être écrite dans un fichier, qui aura soit un jeu de règles définies, et/ou pourra être géré dynamiquement, tel que :
ancre nom_ancre
load nom_ancre from "/etc/pf/fichier_ancre"
Pour de plus amples informations, lire : https://www.openbsd.org/faq/pf/anchors.html
Les paquets peuvent être assignés à une ou plusieurs queues, afin de gérer la bande passante.
Il faut définir au moins une queue pour la configurer, et ensuite créer des règles qui feront référence à la queue par son nom. Si une queue appelée n’existe pas pour une interface réseau, c’est la queue par défaut qui sera utilisée.
Il DOIT y avoir une queue maître, qui fait référence spécifiquement à une interface réseau. Les autres queues, appelées enfants, sont créées relativement à la queue maître.
⇒ Exemple :
iface = "em0"
queue rq on $iface bandwidth 100M
queue ssh parent rq bandwidth 10M
queue http parent rq bandwidth 80M
queue std parent rq bandwidth 10M default
block return out on $iface inet all set queue std
⇒ Définition des mots clés réservés :
default
: spécifie la queue par défauton
: spécifie une interface réseauparent
: attache une queue à une queue maîtreqlimit
: définit le nombre maximum de paquets capturés dans une queue.
Par défault : 50⇒ Définition de valeurs de bande passante :
Les valeurs de bande passante DOIVENT absolument être des entiers ;
ces valeurs peuvent être suffixées des lettres suivantes K
, M
, ou G
,
qui respectivement représentent le nombre de bits par secondes gérés,
tels que Kilobits, Megabits, ou Gigabits.
Ces valeurs ne doivent pas dépasser la taille de la bande passante allouée à une interface réseau !
⇒ Attributs possibles :
max
: spécifie la limite maximale de bande passante allouée à une queuemin
: cible la taille minimale, réservée, de bande passante à une queue
donnéeburst
: est un attribut qui permet à une bande passante d’être outrepassée
dans un laps de temps donnée, pour une queue précise⇒ Exemples :
queue ssh parent std bandwidth 10M, min 5M, max 25M
queue ssh parent std bandwidth 10M burst 90M for 100ms
La première des règles la plus basique, et sécuritaire est celle de tout bloquer :
block
Il existe des règles de grammaire et de simplifications d’écriture des règles PF.
⇒ Cela ne sert à rien d’écrire ce qui suit :
block in all
block out all
Ni :
block all
Écrire block
suffit !
⇒ De même, il ne sert à rien de spécifier :
block drop
ou :
block return
⇒ Sauf à utiliser ces mots-clés, dans le contexte de certaines règles PF, spécifier la politique de rejet, puis utiliser juste le mot clé block, tel que :
set block-policy return
block
L’usage du mot clé reservé all
ou de l’expression réservé from any to any
ne servent à rien non plus. Ce sont des règles implicites, par défaut !
Pour plus d’informations, lire : https://www.openbsd.org/faq/pf/shortcuts.html#grammar
Le mot clé keep state
permet de gérer le suivi de connexion des flux
sur les protocoles TCP, UDP et/ou ICMP. Ce mot clé permet de gérer les
messages ICMP relatifs à la régulation du trafic, tel que les messages
“source quench”, de fait il n’y a pas besoin de créer de règles spécifiques.
Pour s’assurer de n’autoriser QUE les nouvelles connexions, ou plutôt
l’initiation de nouvelles connexions, on utilisera seulement les drapeaux
S/SA
- SYN sans ACK -… le suivi de connexion gérera le reste correctement.
⇒ Exemple :
pass in on em0 proto tcp flags S/SA keep state
Note : c’est une bonne habitude à prendre de gérer l’état de connexion à partir de nouvelles initialisation !
Veuillez lire la page de la FAQ Filter pour mieux comprendre ce qu’est la notion de suivi d’états, la syntaxe des règles PF à-propos des états, les différentes options possibles, etc…
Ainsi que vu plus haut, en début de page, c’est l’option -s
qui permet
d’obtenir différentes informations relatives aux états du pare-feu.
Cette option utilise des drapeaux pour afficher différemment les informations.
# pfctl -s flag
⇒ Définition des drapeaux :
Voir toutes les informations : -sa
info
: affiche les statistiques globales
-si
nat
: affiche les informations de traduction d’adresses réseaux, de
type nat
, et rdr
.
rules
: affiche les règles de filtrage chargées en mémoire - un peu,
l’équivalent des options ‘-Lnv’ à iptables
-sr
state
: affiche l’état des connexions ouvertes.
-ss
Anchor : option -s Anchor
, avec ou sans un ’s’ final, permet de connaître
le nom des tables utilisées. Les ancres peuvent aussi être gérées en
utilisant directement l’option -sa
, ainsi que l’ajout d’un de ses
drapeaux -f
, -F
, ou -s
…
Label : option -s label
, avec ou sans un ’s’ final, permet d’obtenir
les informations liées à des labels.
-sl
Queue : option -s queue
-sA
- avec un A majuscule ;Table : option -s Tables
, avec ou sans un ’s’ final, permet de connaître
le nom des tables utilisées. Si une table est gérée par une ancre,
il est possible de la contrôler en appelant d’abord l’ancre puis la
table, telle que :
pfctl -a ancre -t table -T command
…
-sT
Note : Pensez à utiliser l’option -vs
, voire -vvs
qui permet
d’avoir un état plus complet de l’information recherchée, si celui est
possible.
Pour de plus amples informations, veuillez lire le manpage correspondant à l’outil ‘pfctl’…
Par défaut, PF gère un nombre maximal d’entrées dans sa table d’états qui est de 10 000.
Pour connaître le nombre d’entrées dans la table d’états, en cours :
# pfctl -ss | wc -l
Si et seulement si vous êtes proche de cette limite, vous pouvez agrandir
le nombre d’entrées dans la table, en paramétrant votre fichier /etc/pf.conf
,
tel que :
set limit states 20000
Ci-dessous, retrouvez un exemple basique de règles PF qui sont donnés pour le flux sur ipv4. Il faudra faire les modifications nécessaires pour ipv6 ;)
block
pass out all keep state
Ces deux règles “disent” :
# $OpenBSD: pf.conf,v 1.54 2014/08/23 05:49:42 deraadt Exp $
#
# See pf.conf(5) and /etc/examples/pf.conf
table <t_bogons> persist file "/etc/pf_table_bogons"
set block-policy return
set optimization normal
set reassemble yes
set ruleset-optimization none
set skip on lo
antispoof for egress
match in all scrub (max-mss 1440 no-df random-id reassemble tcp)
block drop in quick on egress from { <t_bogons> } to any
block drop out quick on egress from any to { <t_bogons> }
# By default, do not permit remote connections to X11
block in on ! lo0 proto tcp to port 6000:6010
# Prevent dns leaks : best to use with unbound, dnscrypt-proxy
block in log on egress inet proto { tcp udp } from any to ! egress port 53
block # block stateless traffic
pass # establish keep-state
⇒ Quelques petites explications :
egress
est un nom définissant toute(s) le(s) interface(s) réseau(x)
correspondant à la ou le(s) route(s) par défaut, vers la ou le(s)
passerelles. La règle antispoof
est une mesure de protection dite
’no spoofing’, afin que ne soit possible de lui “piquer” son ou ses
adresses réseau(x)./etc/pf_table_bogons
est donné en exemple ci-dessous !Les deux versions basiques de règles PF sont exactement les mêmes - la deuxième utilise plus profondément les listes et macros pour ne pas avoir à réécrire certaines portions !
# $OpenBSD: pf.conf,v 1.54 2014/08/23 05:49:42 deraadt Exp $
#
# See pf.conf(5) and /etc/examples/pf.conf
# lists, macros
auth_tcp_ports ="{ http ftp whois }" # ajouter imap, smtp, rsync ou autres flux TCP nécessaires en sortie
auth_tcps_ports = "{ https }" # ajouter imaps, smtps ou autres flux TCP "secure" nécessaires en sortie
auth_udp_ports = "{ domain }" # ajouter tout flux UDP nécessaire en sortie
web_ports = "{ http https }" # modifier entrée services web
table <t_bogons> persist file "/etc/pf_table_bogons"
table <t_abuse_ssh> persist
table <t_abuse_web> persist
set block-policy return
set optimization normal
set reassemble yes
set ruleset-optimization none
set skip on lo
antispoof for lo
antispoof for egress
#scrub in all fragment reassemble no-df max-mss 1440 <= old version; do not using-it!
match in all scrub (max-mss 1440 no-df random-id reassemble tcp)
# Prevent dns leaks : best to use with unbound, dnscrypt-proxy
block in log on egress inet proto { tcp udp } from any to ! egress port 53
block drop in quick on egress from { <t_bogons> } to any
block drop out quick on egress from any to { <t_bogons> }
# block abuses
block in log quick proto tcp from <t_abuse_ssh> to any port ssh
block in log quick proto tcp from <t_abuse_web> to any port $web_ports
block # block stateless traffic
# pass few udp ports
pass quick inet proto icmp all icmp-type { echoreq, unreach }
pass proto udp from any to egress port mdns allow-opts
# pass in
pass in on egress proto tcp to any port ssh flags S/SA modulate state (max-src-conn-rate 3/60, overload <t_abuse_ssh> flush global)
pass in on egress proto tcp to any port $web_ports flags S/SA modulate state (max-src-conn 100, max-src-conn-rate 40/5, overload <t_abuse_web> flush global)
# pass out
pass out log on egress proto tcp to any port $auth_tcp_ports modulate state
pass out log on egress proto tcp to any port $auth_tcps_ports modulate state
pass out on egress proto udp to any port $auth_udp_ports allow-opts keep state
# $OpenBSD: pf.conf,v 1.54 2014/08/23 05:49:42 deraadt Exp $
#
# See pf.conf(5) and /etc/examples/pf.conf
# lists, macros
auth_tcp_ports ="{ http ftp whois }" # ajouter imap, smtp, rsync ou autres flux TCP nécessaires en sortie
auth_tcps_ports = "{ https }" # ajouter imaps, smtps ou autres flux TCP "secure" nécessaires en sortie
auth_udp_ports = "{ domain ntp mdns }" # ajouter tout flux UDP nécessaire en sortie
# ports
web_ports = "{ http https }" # modifier entrée services web
# statefull tracking options - sto
ssh_sto = "(max-src-conn-rate 3/60, overload <t_abuse_ssh> flush global)"
web_sto = "(max-src-conn 100, max-src-conn-rate 40/5, overload <t_abuse_web> flush global)"
# state
flag_syn = "flags S/SA modulate state"
# others
edropin = "block drop in quick on egress from"
edropout = "block drop out quick on egress from"
epassout = "pass out log on egress proto tcp to any port"
inblocktcp = "block in log quick proto tcp from"
inpasstcp = "pass in on egress proto tcp to any port"
table <t_bogons> persist file "/etc/pf_table_bogons"
table <t_abuse_ssh> persist
table <t_abuse_web> persist
set block-policy return
set optimization normal
set reassemble yes
set ruleset-optimization none
set skip on lo
antispoof for { lo, egress }
#scrub in all fragment reassemble no-df max-mss 1440 <= old version; do not using-it!
match in all scrub (max-mss 1440 no-df random-id reassemble tcp)
# Prevent dns leaks : best to use with unbound, dnscrypt-proxy
block in log on egress inet proto { tcp udp } from any to ! egress port 53
$edropin { <t_bogons> } to any
$edropout any to { <t_bogons> }
# block abuses
$inblocktcp <t_abuse_ssh> to any port ssh
$inblocktcp <t_abuse_web> to any port $web_ports
block # block stateless traffic
# pass few udp ports
pass quick inet proto icmp all icmp-type { echoreq, unreach }
pass proto udp from any to egress port mdns allow-opts
# pass in
$inpasstcp ssh $flag_syn $ssh_sto
$inpasstcp $web_ports $flag_syn $web_sto
# pass out
$epassout $auth_tcp_ports $flag_syn
$epassout $auth_tcps_ports $flag_syn
pass out on egress proto udp to any port $auth_udp_ports allow-opts
Ces adresses ne doivent en aucun cas se retrouver sur Internet - malheureusement de petits malins les utilisent, d’où la raison de les filtrer !
Le fichier /etc/pf_table_bogons
doit contenir des adresses CIDR,
telles que :
0.0.0.0
10.0.0.0/8
100.64.0.0/10
127.0.0.0/8
128.0.0.0/16
169.254.0.0/16
172.16.0.0/12
191.255.0.0/16
192.0.0.0/24
192.0.2.0/24
192.88.99.0/24
#192.168.0.0/16
198.18.0.0/15
198.51.100.0/24
203.0.113.0/24
223.255.255.0/24
224.0.0.0/4
240.0.0.0/4
255.255.255.255
⇒ Pour information :
10.0.0.0/8
# private network ( RFC 1918 )100.64.0.0/10
# cf RFC 6598127.0.0.0/8
, 128.0.0.0/16
# Loopback ( RFC 1122 ),
IANA reservations ( RFC 3330 )169.254.0.0/16
, 172.16.0.0/12
# Link Local Block ( RFC 3927 ),
private network ( RFC 1918 )191.255.0.0/16
, 192.0.0.0/24
, 192.0.2.0/24
, 192.88.99.0/24
# ?,
IETF Protocol 5 ( RFC 5736 ), Test-Net 1 ( RFC 1166 ), 6to4 Relay Anycast ( RFC 3068 )192.168.0.0/16
# privates classes networks ( RFC 1918 )
<= à commenter pour pouvoir “contacter” stations/serveurs locaux198.18.0.0/15
, 198.51.100.0/24
# Network Interconnect Device
Benchmark Testing ( RFC 2544 ), Test-Net 2 ( RFC 5737 )203.0.113.0/24
, 223.255.255.0/24
, 224.0.0.0/4
, 240.0.0.0/4
# Test-Net 3
( RFC 5737 ), ?, Class D Reserved ( RFC 3171 ), Class E Reserved ( RFC 1112 ),…255.255.255.255
# limited broadcast destination addressNote : Le site Team Cymru met à jour une liste + ou - régulière des adresses dites “bogons”…
De même que la table gérant les réseaux bogons, il est possible d’utiliser des listes sur internet pour filtrer des adresses IP et/ou des segments entiers de réseaux, qui sont reconnus par plusieurs entités, elles-mêmes reconnues officiellement ou non, pour aider à lutter contre.
table <t_badips> persist file "/dir/badips_ipv4" counters
table <t_badips6> persist file "/dir/badips_ipv6" counters
block drop in quick on egress from { <t_badips> } to any
block drop out quick on egress from any to { <t_badips> }
block drop in quick on egress inet6 from { <t_badips6> } to any
block drop out quick on egress inet6 from any to { <t_badips6> }
Les astuces concernant ICMP, ICMPv6, et Traceroute sont tirées du livre “The Book of PF” !
Retrouvez une “cheat sheet"…
ATTENTION : Les astuces ci-dessous ne sont que des exemples . Il est de votre devoir de les adapter, en ayant bien compris les principes de gestion de PF !
Elles pourraient probablement ne pas fonctionner ou ne pas restituer le résultat attendu, surtout si vous ne savez pas les adapter à vos besoins !
# macros
icmp_types="{ echoreq unreach }"
icmp6_types="{ unreach toobig timex paramprob echoreq routeradv neighbrsol neighbradv }"
(…)
# icmp (pass in+out)
pass quick inet proto icmp icmp-type $icmp_types
pass quick inet6 proto icmp6 icmp6-type $icmp6_types
Note : N’hésitez pas à lire les manpages icmp(4) et icmp6(4)
Voici des règles IPv4 et IPv6 pour le trafic multicast et SSDP liés à la bibliothèque Avahi !
⇒ pour le trafic mDNS :
pass proto udp from any to 224.0.0.251 port mdns allow-opts
pass inet6 proto udp from any to ff02::fb port mdns allow-opts
⇒ pour le trafic SSDP :
pass proto udp from any to 239.255.255.250 port ssdp allow-opts
pass inet6 proto udp from any to { ff02::c, ff05::c, ff08::c } port ssdp allow-opts
Exemple pour du flux torrent : 6881:6891
pass in quick on egress inet proto tcp from any to 192.168.0.3 port 6881:6891 flags S/SA
smb_ports_tcp = "{ 135 137 139 445 }"
smb_ports_udp = "{ 135 137 138 445 }"
# samba in
pass in quick on egress proto tcp from egress:network to egress port $smb_ports_tcp flags S/SA modulate state
pass in quick on egress proto udp from egress:network to egress port $smb_ports_udp allow-opts keep state
# samba out
pass out on egress proto tcp from egress to egress:network port $smb_ports_tcp flags S/SA modulate state
pass out on egress proto udp from egress to egress:network port $smb_ports_udp allow-opts keep state
# syncthing in
pass in quick on egress inet proto tcp from { 192.168.1.0/24 } to egress port 22000 flags S/SA modulate state
pass in quick on egress inet proto udp from { 192.168.1.0/24 } to egress port 21027
# syncthing out
pass out quick on egress inet proto tcp from egress to { 192.168.1.0/24 } port 22000 flags S/SA modulate state
pass out quick on egress inet proto udp from egress to { 192.168.1.0/24 } port 21027
Il n’est pas forcément nécessaire de créer des règles pour utiliser
l’outil traceroute, en effet l’option -I
permet de l’utiliser en ciblant
UDP. Néanmoins, si vous souhaitez obtenir le comportement par défaut, il
faut utiliser les règles suivantes :
pass out on egress inet proto udp to port 33433:33626 # For IPv4
pass out on egress inet6 proto udp to port 33433:33626 # For IPv6
Note : N’hésitez pas à lire le manpage traceroute(8)
Rajoutez dans votre fichier ~/.kshrc
, les alias suivants :
alias pf_clean_all="doas pfctl -F all"
alias pf_clean_counters="doas pfctl -z"
alias pf_clean_info="doas pfctl -F info"
alias pf_clean_queue="doas pfctl -F queue"
alias pf_clean_rules="doas pfctl -F rules"
alias pf_edit="doas nano /etc/pf.conf"
alias pf_info="doas pfctl -si"
alias pf_info_tables="doas pfctl -vvsT"
alias pf_less="doas pfctl -vf /etc/pf.conf"
alias pf_load_table="doas pfctl -T load -f /etc/pf.conf"
alias pf_reload="doas pfctl -f /etc/pf.conf"
alias pf_restart="doas pfctl -d && doas pfctl -ef /etc/pf.conf"
alias pf_start="doas pfctl -ef /etc/pf.conf"
alias pf_stop="doas pfctl -d"
alias pf_test="doas pfctl -nf /etc/pf.conf"
alias pf_view="doas pfctl -sr"
alias pf_view_tables="doas pfctl -sT"
alias pf_watch="doas tcpdump -n -e -ttt -i pflog0"
Exécutez à nouveau : . .kshrc
Maintenant, vous pourrez vous faciliter la vie, en exécutant un des
alias, commençant par pf_*
;-)
ATTENTION : les recommandations de l’IETF - Internet Engineering Task Force -,
voire de l’IANA - Internet Assigned Numbers Authority - sont de supprimer :
drop
- impérativement les codes suivants :
⇒ ICMP :
⇒ ICMP v6 :
Note : Il semble, selon le manpage icmp6(4), que les codes 144 à 147 ne soient pas gérés… par OpenBSD !
L’IANA recommande aussi de filtrer - soit drop
, soit reject
- à la
discrétion de l’administrateur - tous les codes suivants :
⇒ ICMP :
Les autres codes, icmp et icmp6, sont à “limiter” en entrée et/ou en sortie… Pour en savoir plus, veuillez ABSOLUMENT vous informer - cf, la documentation dans la note finale !
Ce qui donne pour le propos les règles suivantes :
# macros
blockicmp = "block drop quick on egress inet proto icmp icmp-type"
blockicmplog = "block drop quick log on egress inet proto icmp icmp-type"
blockicmp6 = "block drop quick on egress inet6 proto icmp6 icmp6-type"
inpassicmplan = "pass in quick on egress inet proto icmp from egress:network to egress icmp-type"
inpassicmpwan = "pass in quick on egress inet proto icmp from any to egress icmp-type"
outpassicmplan = "pass out quick on egress inet proto icmp from egress to egress:network icmp-type"
outpassicmpwan = "pass out quick on egress inet proto icmp from egress to any icmp-type"
icmp6_types="{ echoreq unreach timex paramprob }"
# statefull tracking options
icmp_sto = "keep state (max-src-conn-rate 3/1)"
(…) # autres macros
set block-policy return
(…) # autres set
# block icmp
$blockicmp 3 code 6
$blockicmp 3 code 8
$blockicmplog 4
$blockicmp 6
$blockicmp 15
$blockicmp 16
$blockicmp6 137
$blockicmp6 138
$blockicmp6 139
$blockicmp6 140
$blockicmp6 144
$blockicmp6 145
$blockicmp6 146
$blockicmp6 147
(…) # autres block si nécessaires
block
(…)
# icmp in
$inpassicmplan 0 $icmp_sto
$inpassicmplan 3 code 0 $icmp_sto
$inpassicmplan 3 code 1 $icmp_sto
$inpassicmpwan 3 code 3 $icmp_sto
$inpassicmpwan 8 $icmp_sto
$inpassicmpwan 11 $icmp_sto
$inpassicmplan 12 $icmp_sto
# icmp out
$outpassicmplan 0 $icmp_sto
$outpassicmplan 3 code 0 $icmp_sto
$outpassicmplan 3 code 1 $icmp_sto
$outpassicmpwan 3 code 3 $icmp_sto
$outpassicmpwan 8 $icmp_sto
$outpassicmpwan 11 $icmp_sto
$outpassicmplan 12 $icmp_sto
# icmpv6 (in+out)
pass quick inet6 proto icmp6 icmp6-type $icmp6_types $icmp_sto
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Mais il y a la commande ftp
qui les remplace très bien, même pour
télécharger un fichier en http :
$ ftp -o /chemin/vers/fichier.zip http://URL.com/fichier.zip
Vous exécutez une commande, telle que l’ouverture d’un éditeur texte, -
pour l’exemple : vi
ou nano
- et le système vous répond par cette
erreur :
Error opening terminal: unknown
La raison ? Le système ne reconnaît pas le TERMinal !
Commencez par vérifier quel est ce fameux terminal non reconnu :
$ tset -s
TERM=vt220
Modifions le :
$ export TERM=vt100
Vérifier la prise en charge de ce terminal avec la commande tset
,
ci-dessus !
Normalement, vous pourrez exécuter à nouveau le lancement de votre éditeur de texte console préféré, ou la commande console qui posait problème !
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
~/.profile
Paramétrez vos variables d’environnements et vos
alias
dans votre fichier
personnel ~/.profile
.
Sous OpenBSD, l’environnement par défaut est le Public Domain Korn Shell .
En mettant ces lignes //à la fin du// fichier ~/.profile
, votre
session graphique sera lancée dès que vous vous connecterez dans le tty1
(celui par défaut).
Adaptez le fichier ~/.xinitrc
pour choisir votre session :
if [ "$(tty)" == "/dev/ttyC0" ]; then
startx
fi
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Installez
le
paquet sct
.
Quelques styles de température de couleur :
⇒ Feu de camp : $ sct 4500
⇒ Tempête de poussière sur Mars : $ sct 2000
⇒ Café gratuit toute la nuit : $ sct 8000
sct [temp] sct version
sct est un outil léger pour paramétrer la température de l’écran.
Si l’argument optionnel temp
est donné, la température de couleur est
configurée à cette valeur.
Les arguments sont les suivants :
temp
: optionnel, spécifie la température.sct attend une valeur de température entre 1000 et 10000. La valeur de température par défaut est de 6500.
L’utilitaire sct sort avec un code 0
en cas de succès, et un code
supérieur à 0 si une erreur existe.
⇒ Exécuter sct pour régler la température de l’écran sur un style
“feu de camp” : $ sct 4500
⇒ Afficher les informations de version et de droits d’auteur de sct sur
la sortie standard et sortir avec succès : $ sct version
L’utilitaire sct suit et utilise les normes XStandards(7).
La première version de l’utilitaire sct est apparue en Novembre 2015 dans l’article suivant :
L’utilitaire sct a été écrit par Ted Unangst [[tedu@openbsd.org]], puis ensuite amélioré par Joerg Jung [[mail@umaxx.net]].
sct arrondit les valeurs de température par palier de 500.
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
MPlayer est un lecteur multimédias.
Il peut vous faire écouter des fichiers au format MPEG/VOB, AVI, ASF/WMA/WMV, FLV, RM, QT/MOV/MP4, Ogg/OGM, MKV, VIVO, FLI, NuppelVideo, yuv4mpeg, FILM et RoQ. Mais vous pouvez aussi regarder des films au format VCD, SVCD, DVD, 3ivx, DivX 3/4/5, WMV, et même H.264.
MPlayer prend en charge un grand nombre de sortie vidéos. Il fonctionne avec X11, Xv, OpenGL et en options AAlib ou SDL.
Voici les différentes saveurs de paquets MPlayer :
aa
: active l’ASCII Art, et requiert la bibliothèque graphique aalibjack
: active l’utilisation de jack, et requiert le paquet audio jackInstallez
le
paquet mplayer
.
L’utilisation de l’interface graphique de MPlayer est dépréciée et n’est pas recommandée sur aucune des architectures supportées par OpenBSD. Elle n’est donc pas intégrée dans le paquet de MPlayer.
Utilisez gnome-player ou smplayer à la place.
Mencoder n’est pas censé faire un bon travail de multiplexage avec des formats de conteneurs autres qu’AVI ou MPEG.
Il est possible de rencontrer des problèmes de lenteurs vidéo. Dans ce
cas, vous pouvez désactiver la rotation de l’écran de X.org dans le
fichier /etc/X11/xorg.conf
.
Selon votre configuration, vous pouvez passer les options -framedrop
ou -hardframedrop
à l’usage de mplayer.
Puisque les codecs open source sont de bonne qualité, à l’heure actuelle, les codecs Win32 sont maintenant désactivés.
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Le bureau Lumina !
Page du projet : https://lumina-desktop.org
Installez
le
paquet lumina
.
~/.xsession
Disponible à partir d’OpenBSD 6.1 !
Créer/modifier le fichier de session ~/.xsession
, et y ajouter à minima :
#!/bin/sh
PATH=$PATH:/usr/local/bin start-lumina-desktop
Pensez à redémarrer le service
xenodm
!
Merci de lire notre page du service cups , pour configurer correctement la gestion de l’impression ;)
Pour l’instant, cela ne semble pas possible !
Il faut plutôt s’inspirer d’une des méthodes fournies dans notre page “[[tutoriel:openbsd-mount-usb|Monter un disque / une clé USB en tant qu’utilisateur]]” ;-)
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Le fichier de config /etc/X11/xorg.conf
n’existe pas, par défaut !
Il faut le créer !!!
Quand ajouter l’option machdep.allowaperture
?
Si le log du serveur X vous informe du message suivant :
$ head /var/log/Xorg.0.log
[ 33.839] (WW) checkDevMem: failed to open /dev/xf86 and /dev/mem
(Operation not permitted)
Check that you have set 'machdep.allowaperture=1'
in /etc/sysctl.conf and reboot your machine
refer to xf86(4) for details
[ 33.839] linear framebuffer access unavailable
[ 33.888] (--) Using wscons driver on /dev/ttyC4
[ 33.997]
X.Org X Server 1.19.6
Release Date: 2017-12-20
Donc, comme le dit le message d’avertissement, il est nécessaire
d’éditer le fichier /etc/sysctl.conf
et d’y ajouter la variable
suivante : machdep.allowaperture=1
, puis il faut redémarrer la machine
- non, apparemment, redémarrer le serveur X ne suffit pas !
Si votre affichage vidéo saccade, vous souffrez de tearing
.
Une manière de le régler est d’ajouter à votre fichier /etc/X11/xorg.conf
,
les options suivantes, dans la Section "Device"
:
Option "TearFree" "true"
- cette option principale est
par défaut désactivée ; donc, il faut l’activer !Option "SwapbuffersWait" "true"
- normalement cette option est
activée par défautOption "VSync" "true"
- normalement cette option est
activée par défaut - elle gère, entres autres, le tearing vertical
.Il peut être intéressant de désactiver l’extension du compositeur ; il
faut donc rajouter la gestion de l’option Composite
dans la
Section "Extensions"
- bien-sûr, si cette dernière n’existe pas dans votre fichier de config,
créez-la, telle que :
Section "Extensions"
# fixes tearing with vdpau/vsync
Option "Composite" "Disable"
EndSection
Section "Device"
Identifier "intel"
Driver "intel"
Option "HotPlug" "true"
Option "TearFree" "true" #false by default (avoid tearing)
EndSection
Section "Device"
Identifier "intel" #modesetting, or Intel Graphics
Driver "intel" #modesetting
Option "AccelMethod" "sna" #sna by default
Option "DDC" "true" #true by default
Option "DRI" "true"
Option "HotPlug" "true"
Option "NoAccel" "false" #false by default
Option "RelaxedFencing" "true" #true if G33 Model & >
Option "SwapbuffersWait" "true" #true by default (avoid tearing)
Option "TearFree" "true" #false by default (avoid tearing)
Option "Throttle" "true" #true by default
Option "Tiling" "true" #true by default
Option "TripleBuffer" "true" #true by default
#Option "VideoRAM" ???
Option "VSync" "true" #true by default (avoid tearing)
EndSection
Section "Monitor"
Identifier "Monitor0"
EndSection
Section "Screen"
Identifier "Screen0"
Device "intel"
Monitor "Monitor0"
DefaultDepth 24 #Choose the depth (16|24)
SubSection "Display"
Depth 16
Modes "1920x1080" "1400x1050" "1290X1024" "1280X960" "1024x768" "800x600"
EndSubSection
SubSection "Display"
Depth 24
Modes "1920x1080" "1400x1050" "1290X1024" "1280X960" "1024x768" "800x600"
EndSubSection
EndSection
Section "ServerLayout"
Identifier "Default Layout"
Screen "Screen0"
EndSection
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Gigolo est une interface graphique pour se connecter facilement à des systèmes de fichiers distants utilisant GIO/GVfs. Il permet de rapidement connecter/monter un système de fichiers distant et de gérer des signets à ce propos.
GVfs est un système de fichiers virtuel dans l’espace utilisateur, succédant à GnomeVfs mais ne dépendant pas de Gnome lui-même. Il requiert seulement une version récente de GLib et un système DBus proprement paramétré. Il fournit alors les accès transparent à des ressources distantes, telles que des connexions FTP ou SFTP (SSH), SMB (partages Windows), ou des ressources spéciales telles que la Corbeille (trash://), la Gravure (burn://) ou même les accès à votre caméra/appareil photo digital (gphoto2://).
Installez
le
paquet gigolo
.
Dans un premier temps, le plus simple est de créer un ou plusieurs signets :
Cela vous permettra de créer des signets pour un des services suivants :
Retrouvez de la documentation dans /usr/local/share/doc/gigolo/
.
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
D-Bus est un système de bus de messages. C’est un moyen simple pour permettre aux applications de discuter entre elles.
En plus de la communication inter-processus (IPC), D-Bus aide à coordonner le cycle de vie des processus ; il est ainsi plus simple et fiable de coder une “instance unique” d’une application ou d’un service (daemon) et à exécuter les applications et services à la demande, lorsque leurs services sont requis.
dbus
et ensuite,apmd
et
messagebus
Certains gestionnaires de sessions, tel que Gnome , gèrent D-Bus toujours de manière pratique automatiquement !
Les modifications suivantes ne seront donc pas prises en compte !!!
Pour démarrer une instance du service de D-Bus, il faut ajouter le code suivant à votre script gérant votre session X, avant le démarrage de gestionnaire de fenêtre :
~/.xinitrc
Pour rappel, ce fichier sert à démarrer un environnement de bureau depuis votre session locale, sans exécution d’un gestionnaire d’affichage :
if [ -x /usr/local/bin/dbus-launch -a -z "${DBUS_SESSION_BUS_ADDRESS}" ]; then
eval `dbus-launch --sh-syntax --exit-with-session`
fi
~/.xsession
Pour rappel, ce fichier est à utiliser en relation avec un gestionnaire d’affichage, tel xenodm :
if [ -x /usr/local/bin/dbus-launch -a -z "${DBUS_SESSION_BUS_ADDRESS}" ]; then
eval `dbus-launch --sh-syntax --exit-with-x11`
fi
N’oubliez pas de lire le fichier /usr/local/share/doc/pkg-readmes/dbus
Vous pouvez aussi lire :
/usr/local/share/doc/dbus/
/usr/local/share/examples/dbus/
,
voire /usr/local/share/examples/dbus-glib/
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
cwm est un gestionnaire de fenêtres, léger et efficace, présent par défaut dans OpenBSD.
Si vous utilisez le gestionnaire de connexion xenodm
,
présent par défaut lui-aussi, vous pouvez démarrer cwm
en l’appelant
dans le fichier ~/.xsession
:
xsetroot -solid steelblue &
# feh --bg-scale /Images/background.jpg
cwm
La première ligne permet de définir une couleur de fond. Vous pouvez la remplacer par la seconde actuellement commentée afin de définir un fond d’écran à partir d’une image.
cwm
peut se contrôler aussi bien avec le clavier que la souris.
Par la suite, nous utiliserons les mêmes abréviations que dans le fichier de configuration, à savoir :
C
: CtrlM
: AltS
: Shift4
: Touche “windows”Pour déplacer une fenêtre, il faut maintenir M appuyé puis glisser-déposer avec la souris.
Pour la redimensionner, c’est avec un clic-milieu.
Un clic-gauche sur le bureau vous affiche la liste des fenêtres ouverts.
Un clic-milieu affiche la liste des groupes de fenêtres (sortes d’espace de travail).
Un clic-droit affiche le menu des applications que vous aurez configuré dans le fichier de configuration.
Les raccourcis claviers par défaut sont (non-exhaustif) :
M-?
: invite de commande pour lancer un programme.CM-Entrée
: ouvre un terminal.CM-Suppr
: verrouille la session.M-Tab
: circule entre les fenêtres.M-/
: recherche une fenêtre. Appuyez ensuite sur C-a pour les lister
toutes.CM-x
: ferme la fenêtre.CM-f
: met la fenêtre en plein écran.CM-=
, CMS-=
, CM-m
: respectivement, maximise la fenêtre
verticalement, horizontalement et totalement.CMS-r
: relance cwmCMS-q
: quitte cwm~/.cwmrc
La configuration de cwm se déroule en éditant un fichier .cwmrc
dans
votre dossier personnel : ~/.cwmrc
Vous pouvez y définir notamment :
borderwidth 2 # Épaisseur des bordures
color activeborder "#2aa198" # Couleur des bordures des fenêtres sélectionnées
color inactiveborder "002B36" # Couleur des bordures si la fenêtre est inactive
gap 20 0 0 0 # je souhaite avoir une marge en haut de l'écran
# de 20 pixels
# Configuration de l'apparence des menus
color font "#839496" # Couleur du texte
color selfont "#eee" # Couleur du texte sélectionnée
color menubg "#002b36" # Couleur d'arrière plan
color menufg "#2aa198" # Couleur de bordure des éléments sélectionnées
fontname "Hack:pixelsize=14" # La police des menus
# Les commandes terminal et de verouillage.
# Autant utiliser les défauts d'OpenBSD
command term st
command lock "slock" # activer avec C-M-Suppr
command " Web " firefox
command " Mail " thunderbird
command " Files " pcmanfm
command ">> next " "mpc next"
command "<< prev " "mpc prev"
command "|> toggle" "mpc toggle"
command " top " "xterm -e top"
Vous pouvez mettre des fenêtres directement dans certains groupes pour facilement vous y retrouver :
# Groupes, à retrouver avec xprop
# autogroup n "name,class"
autogroup 2 "Navigator,Firefox"
autogroup 3 "mutt,mutt"
autogroup 3 "mutt,st-256color"
Pour voir un groupe : M-n
où n
est le chiffre correspondant au groupe.
Sur un clavier azerty, c’est &é"’(…
Pour envoyer une fenêtre dans un groupe, c’est MS-n
.
bind-key M-ampersand group-only-1
bind-key M-eacute group-only-2
bind-key M-quotedbl group-only-3
bind-key M-apostrophe group-only-4
bind-key M-parenleft group-only-5
bind-key M-minus group-only-6
bind-key M-egrave group-only-7
bind-key M-underscore group-only-8
bind-key M-ccedilla group-only-9
bind-key M-agrave group-toggle-all
# Déplacer les fenêtres dans un groupe
bind-key MS-ampersand window-movetogroup-1
bind-key MS-eacute window-movetogroup-2
bind-key MS-quotedbl window-movetogroup-3
bind-key MS-apostrophe window-movetogroup-4
bind-key MS-parenleft window-movetogroup-5
bind-key MS-minus window-movetogroup-6
bind-key MS-egrave window-movetogroup-7
bind-key MS-underscore window-movetogroup-8
bind-key MS-ccedilla window-movetogroup-9
Ces raccourcis permettent d’agencer très rapidement les fenêtres en tuile pour occuper tout l’espace disponible (comme dwm)
# Du tiling !!!
bind-key M-t window-vtile
bind-key M-Return window-vtile
bind-key MS-t window-htile
Vous pouvez lancer des commandes avec un raccourci clavier. Par exemple ceci ouvre firefox :
bind-key M-w firefox
Pour redimensionner avec le bouton droit de la souris, on peut désactiver le raccourci précédent :
# Souris
# Désactive le redimensionnement avec le clic milieu
unbind-mouse M-2
# Alt+ clic droit redimensionne
bind-mouse M-3 window-resize
Cette documentation a été écrite de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Iridium est une libre, ouverte, et gratuite modification du code de la base du navigateur Chromium , avec de la confidentialité activée sur beaucoup de clés : la transmission automatique de requêtes partielles, les mots clés, la télémétrie aux services centralisant sont inhibés et exécutés que seulement avec le consentement.
Installez
le
paquet iridium
.
Depuis OpenBSD 6.6, le logiciel de confidentialité KeePassXC est installable.
Pour fonctionner correctement avec iridium, il est nécessaire d’installer le module KeePassXC-Browser.
Lire la page KeePassXC pour avoir plus d’informations concernant le module KeePassXC-Browser
Ajouter au fichier de configuration unveil
de
iridium unveil.main
:
/usr/local/bin r
/usr/local/bin/keepassxc-proxy rx
Ainsi le proxy de KeePassXC pourra communiquer avec le module KeePassXC-Browser.
iridium sur OpenBSD est sécurisé par pledge(2) et unveil(2) - afin de limiter les appels systèmes et les accès au système de fichier.
Retrouvez ces fichiers dans le répertoire /etc/chromium
et tout particulièrement :
/etc/iridium/pledge.main
/etc/iridium/unveil.main
Si votre navigateur plante lorsque vous utilisez protonmail ou une autre
bibliothèque de chiffrement javascript, dirigez-vous dans chrome://flags
puis indiquez :
Experimental Validate Asm.js and convert to WebAssembly when valid
à false
.J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Firefox-esr est un navigateur web conforme aux normes, pleinement équipés, construit sur la base du code de Mozilla par des centaines de contributeurs dans le monde. Il est extensible à-travers des centaines d’extensions, contributions d’utilisateurs, et de fonctionnalités :
Installez
le
paquet firefox-esr
.
Ces fonctionnalités ne sont utilisables qu’avec Firefox Quantum, et tout particulièrement à partir de la version 59.x !
Il est important que votre architecture matérielle gère OpenGL 4, et WebGL 2 ; autrement, OUBLIEZ !
⇒ Par défaut, l’accélération graphique OpenGL est désactivée. Il est possible de l’activer de deux manières :
MOZ_ACCELERATED=1
layers.acceleration.force-enable
pour la positionner sur true
.HW_COMPOSITING
et OPENGL_COMPOSITING
dans la section
Accélération graphique.⇒ Pour activer le compositeur basé sur Rust, deux manières possibles :
MOZ_WEBRENDER=1
gfx.webrender.enabled
pour la
positionner sur true
.WEBRENDER
dans la section Accélération graphique.Pour désactiver l’anti-aliasing, il est nécessaire de créer la variable
d’environnement suivante GDK_USE_XFT=0
.
Pour une intégration propre avec les composants des environnements de bureau, Firefox-ESR a besoin d’une instance de D-Bus fonctionnelle.
Veuillez lire D-Bus [système de bus de messages] / OpenBSD
Pour ajouter le support audio et vidéo HTML5,
installez
le
paquet ffmpeg
.
Pour utiliser Firefox en mode KerberosV :
LD_LIBRARY_PATH=/usr/local/heimdal/lib
shlib_dirs
dans le fichier /etc/rc.conf.local
Si vous désirez spécifier l’usage de Kerberos en ciblant certains domaines,
écrivez “about:config” dans la barre d’URL, puis modifiez la clé
network.negotiate-auth.trusted-uris
en ajoutant votre domaine, tel que :
.example.com
.
À-propos de la gestion des liens mailto :
network.protocol-handler.app.mailto
.
/usr/local/bin/thunderbird
new string
)Firefox sur OpenBSD est sécurisé par pledge(2) et unveil(2) - afin de limiter les appels systèmes et les accès au système de fichier.
Par défaut, seuls les répertoires /tmp
et ~/Downloads
sont autorisés
en écriture. De même, la lecture des fichiers locaux est autorisé en
préfixant le chemin vers le fichier par file://
.
Si votre répertoire personnel ~/Downloads
n’existe pas, créez-le puis
relancez Firefox.
Les permissions pour chaque type de processus sont localisées par défaut
dans des fichiers contenus dans etc/firefox
qui est une copie de
/usr/local/lib/firefox-esr/browser/defaults/preferences/
lors de
l’installation.
Du fait d’unveil(2), il est nécessaire de gérer finement les gestionnaires MIME.
Par exemple pour permettre l’utilisation d’un lecteur PDF avec Firefox, il faut :
déclarer par défaut le lecteur PDF en tant gestionnaire MIME, tel que
$ xdg-mime default xpdf.desktop application/pdf
$ xdg-mime default mupdf.desktop application/pdf
modifier le fichier /etc/firefox-esr/unveil.main
pour gérer les droits
sur le binaire correspondant, tel que :
/usr/local/bin/xpdf rx
/usr/local/bin/mupdf rx
Ainsi vous pourrez lire le fichier PDF avec l’option “Ouvrir avec…”.
$ xdg-mime query default application/pdf
permet de connaître le lecteur
PDF par défaut.
Le support des webcams est normalement géré par Firefox, qui par défaut
a accès aux périphériques vidéo /dev/video
et /dev/video0
.
⇒ OpenBSD ≥ 6.9 : Il faut aussi : - activer l’enregistrement vidéo - puis vérifier le support et accéder à la webcam - et pour finir l’enregistrement audio .
⇒ OpenBSD ≥ 6.4 : Pour que la fonctionnalité WebRTC fonctionne correctement, il faut activer l’enregistrement audio .
Si Firefox-esr a un comportement étrange, essayez de créer un nouveau profil :
-ProfileManager
, puis vous cliquez sur [ Create Profile ]Si Firefox-esr ne démarre pas, essayez de le démarrer en mode
console, avec l’option -safe-mode
- cela aura pour effet d’essayer à le démarrer après avoir
désactiver toutes vos extensions, vos thèmes.
Pour exécuter les deux versions en même temps, Firefox et celle-ci, vous devez créer des profils différents :
firefox -p
firefox-esr -p
Il suffit de créer et d’attribuer un profil différent…
Êtes-vous sûr d’avoir installé le paquet Cups et son pendant gtk-+2 ou 3 ?!
Cette caractéristique de média CSS est fonctionnelle à partir de la v67.
privacy.resistFingerprinting
est paramétrée sur true
, la gestion de cette option ne fonctionnera pas
; ce sera le schéma light
qui sera choisi par défaut.Après l’installation, n’oubliez pas de lire le fichier
/usr/local/share/doc/pkg-readmes/firefox-esr
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Chromium et un projet open source de navigation qui vise à créer un moyen plus sûr, rapide et stable pour que tous les utilisateurs d’Internet puissent utiliser le Web.
Certains utilisateurs préfèrent Chromium à Google Chrome car ils jugent inutiles ou néfastes les apports de Google Chrome par rapport à Chromium (en particulier les fonctionnalités de pistage télémétrie).
Malgré tous les défaut en terme de vie privée qu’on peut tout de même attribuer à cette version libérée, il reste un navigateur très intéressant en terme de sécurité. De plus, l’équipe d’OpenBSD y a ajouté des fonctionnalités très intéressants, notamment le support de pledge et unveil .
Installez
le
paquet chromium
.
Dirigez-vous dans les préférences de chrome puis modifiez au moins les paramètres suivants : (utilisez la barre de recherche pour trouver facilement)
Connexion automatique
Utiliser un service de prédiction afin de compléter les recherches et les URL saisies dans la barre d'adresse
Utiliser un service de prédiction pour charger les pages plus rapidement
Utiliser un service Web pour résoudre les erreurs de navigation
Navigation sécurisée
Contribuer à l'amélioration de la navigation sécurisée
Envoyer une demande "Interdire le suivi" pendant la navigation
. Ça ne vous rend que plus identifiable.Me proposer de traduire les pages qui sont écrites dans une langue que je ne connais pas
Afficher des notifications lorsque de nouvelles imprimantes sont détectées sur le réseau
Poursuivre l'exécution des applications en arrière-plan après la fermeture de Chromium
Bloquer les cookies tiers
Ensuite, configurez après avoir noté dans la barre d’URL : chrome://flags
UI Layout for the browser's top chrome
: Normal
.Identity consistency between browser and cookie jar
: Disabled
SafeSearch URLs reporting
: disabled
C’est une fonctionnalité spécifique native à Chrome - qui ne tient pas compte des paramètres personnels de session utilisateur X !
Nécessite v78 ≥ : Il est possible d’activer le mode Dark en définissant
l’URL suivante :
chrome://flags/#enable-force-dark
Ne pas confondre avec le mode CSS prefers-color-scheme !
Ce mode est un mode de gestion de préférence du schéma de couleurs par le biais de la feuille CSS. Si le site web que vous visitez propose cette fonctionnalité, ce mode tient compte de vos préférences utilisateurs de votre session X. C’est “automatique”.
Les extensions suivantes semblent essentielles :
Depuis OpenBSD 6.6, le logiciel de confidentialité KeePassXC est installable.
Pour fonctionner correctement avec Chromium, il est nécessaire d’installer le module KeePassXC-Browser.
Lire la page KeePassXC pour avoir plus d’informations concernant le module KeePassXC-Browser
Ajouter au fichier de configuration unveil
de
Chromium unveil.main
:
/usr/local/bin r
/usr/local/bin/keepassxc-proxy rx
Ainsi le proxy de KeePassXC pourra communiquer avec le module KeePassXC-Browser.
Chromium sur OpenBSD est sécurisé par pledge(2) et unveil(2) - afin de limiter les appels systèmes et les accès au système de fichier.
Retrouvez ces fichiers dans le répertoire /etc/chromium
et tout particulièrement :
/etc/chromium/pledge.main
/etc/chromium/unveil.main
Par défaut, Chromium a accès au périphérique /dev/video
.
⇒ OpenBSD ≥ 6.9 : Il faut aussi activer l’Gérer la vidéo sous OpenBSD !
⇒ OpenBSD ≥ 6.4 : Pour que la fonctionnalité WebRTC fonctionne correctement, il faut activer l’Gestion du Son / OpenBSD.
Si votre navigateur plante lorsque vous utilisez protonmail ou une autre
bibliothèque de chiffrement javascript, définissez l’URL chrome://flags
puis indiquez :
Experimental Validate Asm.js and convert to WebAssembly when valid
à false
.Activez la variable d’environnement : ENABLE_WASM=1
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Utiliser Hugo sous OpenBSD est possible, sans soucis.
Il existe en tant que paquet tiers, installable par le gestionnaire de paquets :
# pkg_add hugo
Hugo Static Site Generator v0.53 openbsd/amd64 BuildDate: unknown
Bon, maintenant soyons réaliste, cette version date d’un an et a son lot de bogues.
Quoiqu’il en soit le projet Hugo semble fournir pour chaque nouvelle version des archives tar.gz qu’il suffit de télécharger et décompresser ; il y a trois fichiers généralement dedans, le fichier LICENSE
, README.md
et le binaire hugo
. Les archives sont à destination des architectures 32 bits (donc i386), 64 bits (donc amd64), et ARM.
Pour autant que dans votre variable d’environnement PATH
vous ayez inclu ~/bin/
, il suffit de créer un lien symbolique dedans pour pouvoir utiliser ce nouveau binaire.
Le propos de cet article est de “remonter” les différents écueils liés à ces binaires officiels, qui parfois générent des changements dans la configuration de Hugo, voire des dysfonctionnements.
La dernière version fonctionnelle est : la 0.59.1.
Hugo Static Site Generator v0.54.0-B1A82C61 openbsd/amd64 BuildDate: 2019-02-01T09:41:10Z
Malheureusement, un simple hugo server
ne fonctionne pas !
L’erreur restituée : Error: Error building site: EOF
Au suivant !
Hugo Static Site Generator v0.55.0-4333CC77 openbsd/amd64 BuildDate: 2019-04-08T16:41:18Z
Depuis la version 0.60.0, il y a un changement du “moteur” par défaut, qui est le goldmark.
Cela implique de modifier le fichier de configuration pour ajouter ce qui suit, pour le format toml :
[markup.goldmark.renderer]
unsafe = true
Il y a un bogue dans la restitution du code HTML au sein des shortcodes.
Le message suivant Page.Hugo is deprecated and will be removed in a future release. Use the global hugo function.
informe simplement que la variable .Hugo
est obsolète, dépréciée ; il est recommandé de la remplacer par la fonction globale hugo
. Donc, parcourez tous vos fichiers _default
, partials
, voire shortcodes
et remplacez !
Voir la page Hugo Documentation : Variables > Hugo
Le message suivant Page's .RSSLink is deprecated and will be removed in a future release. Use the Output Format's link
informe que la variable .RSSLink
est osbolète et dépréciée.
Il est recommandé d’utiliser le formatage de sortie , tel que : {{`` with .OutputFormats.Get "RSS" }}{{ .RelPermalink }}{{ end }}
Voir la page Hugo Documentation : Templates > Output formats
Le message suivant Page's .URL is deprecated and will be removed in a future release. Use .Permalink or .RelPermalink.
explique en fait que la variable .URL
ne doit plus être utilisée dans le corps d’une page. Donc, parcourez tous vos fichiers _default
, partials
, voire shortcodes
et remplacez la variable .URL
au minimum par .Permalink
.
.URL
qui est toujours permise dans le contexte des menus !
(cf: Hugo Documentation : Variables > Menus
)Il est donc recommandé de ne plus utiliser la syntaxe {{``% shortcode %}}
mais de lui préférer la syntaxe {{``< shortcode >}}
et d’utiliser la fonction markdownify
.
Voir la page : Hugo Documentation : Functions > Markdownify .
Les nœuds de taxonomies ont un nouvel accesseur nommé .Page
qui simplifie l’usage aux différentes variables, telle que .Titre
.
Au lieu d’utiliser l’ensemble suivant {{ range .Data.Terms.Alphabetical }}
, utilisez plutôt {{ range .Site.Taxonomies.tags }}
.
Par un beau matin, vous cherchez à vous connecter à votre serveur Nextcloud avec vos identifiants.
Et, ce jour-là, le drame arrive : impossible de vous connecter, l’URL est renvoyée vers login?redirect_url=/apps/files/
et vos identifiants sont redemandés !
Pas la peine de chercher dans votre configuration, si un changement est intervenu ; ce n’est pas non plus un problème lié à l’authentification, voire à la 2FA .
Vérifiez :
netcloud
: 0750
cache
: 0755
0750
semble être fonctionnel, sinon 0755
.www
, mais cela peut différer selon votre système d’exploitation, voire le service web utilisé (tel, Apache, Nginx, …)Sur OpenBSD, j’ai remarqué un petit problème : lors de la mise à jour de PHP, les droits sur les répertoires cache
et tmp
dans votre chroot (càd
normalement : /var/www
), ceux-ci étaient non seulement réinitialisés pour root:daemon
, mais aussi sur 0700
plus le sticky bit
activé.
Il semble nécessaire de les réattribuer à l’utilisateur et au groupe web www
, et de remettre des droits en lecture, écriture sur 0755
.
Le Chiffrement Intégral de Disque (Full Disk Encryption, en anglais) est une opération simple à réaliser sous OpenBSD.
Elle nécessite l’usage du binaire de chiffrement bioctl
qui utilise le sous-système softraid
- même si cela utilise le principe du RAID logiciel, ne pas confondre avec la mise en place de RAID, qui est un processus assez similaire, dans l’usage de binaire et sous-système ; les deux usages cumulés sont impossibles.
Dans cet article, nous verrons succinctement comment chiffrer dès l’installation un disque entier et l’utiliser soit avec une passphrase de sécurité, soit avec une clé USB .
Dès le démarrage du binaire d’installation, l’invite de commande de l’installateur propose le choix suivant :
Code : sh
Welcome to the OpenBSD/*** X.X installation program.
(I)nstall, (U)pgrade, (A)utoinstall or (S)hell? s
Il faut choisir d’aller dans le shell ; tapez donc s puis la touche ENTRÉE .
En admettant que le disque principal se nomme sd0
…
Dans un premier temps, il nous faut nous assurer que le nœud existe réellement :
# cd /dev && sh MAKEDEV sd0
Assurons-nous que le disque dur soit vierge de toutes données :
# dd if=/dev/urandom of=/dev/rsd0c bs=1m
Ce processus remplit le disque dur dans son entier de données aléatoire. Cela permet d’éviter la déduction par une tierce personne de l’espace disque réellement utilisé.
Initialisons le disque dur à l’aide de l’outil fdisk
:
Si vous avez démarré sur un Bios, utilisant la structure de partitionnement MBR , la commande sera :
# fdisk -iy sd0
Par contre si vous utilisez une structure GPT , généralement utilisée dans le contexte d’un Bios UEFI, mais peut aussi être utilisée dans le contexte des BIOS “historiques” (PC BIOS), l’usage deviendra :
# fdisk -iy -g -b 960 sd0
softraid
pour utiliser le binaire bioctl
qui permet le chiffrement du disque, excluant l’usage d’un RAID.La commande disklabel
nous sert à créer le schéma de partitionnement :
Code : sh
# disklabel -E sd0
Label editor (enter '?' for help at any prompt)
sd0>
Ajoutons une partition de la taille totale, de type RAID :
Code : sh
sd0> a a
offset: [64]
size: [39825135] *
FS type: [4.2BSD] RAID
sd0>
Puis, enregistrons et quittons :
Code : sh
sd0> w
sd0> q
No label changes.
Créons le périphérique chiffré sd1
sur la partition a
; nous le ferons en utilisant le binaire bioctl
:
Code : sh
# bioctl -c C -l sd0a softraid0
New passphrase:
Re-type passphrase:
sd1 at scsibus2 targ 1 lun 0: <OPENBSD, SR CRYPTO, 005> SCSI2 0/direct fixed
sd1: 19445MB, 512 bytes/sector, 39824607 sectors
softraid0: CRYPTO volume attached as sd1
Nous verrons comment utiliser une clé USB pour déverouiller le système au moment du démarrage en lieu et place de la passphrase !
Mais dans un premier temps, il nous faut créer le nœud du périphérique sd1
; répétez donc l’étape du makedev
en remplaçant par sd1
.
Ensuite, il faut remplir de zéro ou de données aléatoires le premier secteur de ce nouveau périphérique, soit :
# dd if=/dev/zero of=/dev/rsd1c bs=1m count=1
ou par :
# dd if=/dev/urandom of=/dev/rsd1c bs=1m count=1
Cela étant fini, il sera possible de reprendre le processus d’installation, après avoir écrit exit
dans l’invite de commande shell (appelé prompt, en anglais)
Lorsque le processus d’installation demandera sur quel disque il faut installer le système d’exploitation, ne vous trompez pas, répondez bien sd1
, tel que :
Code : sh
Available disks are: sd0 sd1.
Which disk is the root disk? ('?' for details) [sd0] sd1
Dans l’état actuel, une fois le système d’exploitation OpenBSD installé, lors du démarrage, il sera demandé de taper la passphrase correspondante. Néanmoins, il est possible et intéressant de pouvoir utiliser une clé USB - ce qui est même recommandé, car celle-ci sera chiffrée elle aussi - en lieu et place !
Donc, après le redémarrage du système d’exploitation, il faudra connecter la clé USB, pour l’initialiser , créer le schéma de partitionnement adéquat puis la chiffrer . Ce processus peut normalement être fait après l’usage de `biotcl` … il faudra adapter ce qui doit l’être !
En admettant que la clé soit reconnue en tant que périphérique sd2
…
Comme lors du processus d’installation, nous utiliserons à nouveau fdisk
, tel que :
# fdisk -iy sd2
Nous avons juste besoin d’une partition de type RAID, d’un seul Mo !
1024
, au lieu de 1M
!Code : sh
# disklabel -E sd2
Label editor (enter '?' for help at any prompt)
sd0> a a
offset: [64]
size: [39825135] 1M
FS type: [4.2BSD] RAID
sd0> w
sd0> q
No label changes.
Maintenant, chiffrons notre clé USB :
Code : sh
# bioctl -c C -k sd2a -l sd0a softraid0
sd3 at scsibus3 targ 1 lun 0: <OPENBSD, SR CRYPTO, 005> SCSI2 0/direct fixed
sd3: 19445MB, 512 bytes/sector, 39824607 sectors
softraid0: CRYPTO volume attached as sd3
Et voilà !
Il ne vous reste plus qu’à connecter votre clé USB, pour pouvoir démarrer votre système d’exploitation avant le démarrage de celui-ci. La passphrase correspondante ne vous sera pas demandée !
img
. Ne le laissez pas à la portée de tout le monde. Protégez-le !Pour sauvegarder la clé USB, en faire une image et pouvoir en créer une deuxième ou la restaurer au besoin, nous utiliserons l’utilitaire dd
, tel que :
# dd bs=8192 skip=1 if=/dev/rsd2a of=bckp-key.img
Je vous encourage TRÈS FORTEMENT à chiffrer ce fichier .img avec GPG, puis à détruire le fichier .img ; par exemple, sous OpenBSD :
$ gpg2 --output bckp-key.gpg --encrypt --recipient courriel@domaine.tld bckp-key.img
$ rm -fP bckp-key.img
Bien sûr, cela nécessite que vous ayez créer une clé GPG pour votre courriel !
gpg2 --output bckp-key.img --decrypt bckp-key.gpg
Pour la restaurer, il faudra utiliser dd
, tel que :
# dd bs=8192 seek=1 if=bckp-key.img of=/dev/rsd2a
Pour créer une nouvelle clé USB de secours, il faudra l'initialiser , créer la table de partitionnement , et copier la sauvegarde comme si c’était une restauration . ;)
Le but de cet article est de montrer comment créer un menu de navigation pour le SSG qu’est Hugo.
Nous verrons deux manières différentes pour créer :
La documentation officielle en anglais :
Les différentes entrées du menu sont écrites dans le fichier de configuration config.toml
. Pour information, il existe deux autres formats, JSON et YAML. Nous partirons, du prédicat, d’un site n’ayant qu’une seule langue. Si la conception d’un menu multilangue est subtilement différente, le fonctionnement reste exactement le même.
menu
languages
Par défaut, Hugo génére un site pour la langue anglaise ; pour le paramètrer dans votre langue native, il faut modifier au moins la variable defaultContentLanguage
, par exemple pour la langue française :
defaultContentLanguage = "fr"
, qui peut agrémentée de la variable languageCode = "fr-FR"
.
Généralement, le fichier HTML
sera crée dans le répertoire layouts/partials/
, et quelque soit son nom, pour l’exemple, nous l’appelerons nav.html
par soucis de simplicité, il sera appelé depuis le fichier layouts/_default/baseof.html
.
{{ partial "nav.html" . }}
C’est typiquement le genre de menu qui renvoie vers des éléments au sein de la page, mais il est possible de renvoyer vers une page nommée.
Pour exemple : http://huc.fr.eu.org
Fichier : config.toml
|
|
On remarque donc la présence de variables strictement nécessaires :
identifier
: un identifiant, strictement nécessaire et unique à chaque entréename
: le nomurl
: le nom de l’ancre, ou de la page, à cibler. La présence du symbole #
signifie que le lien ciblé est une ancre dans la page ; son absence cible un article précisément nommé.Ainsi que de certaines utiles :
weight
: c’est le poids du lien dans le menu, plus le poids est faible, plus le lien est “important”.pre
: permet d’injecter du code avant le texte.post
: permet d’injecter du code après le texte - n’est pas présentée iciLe reste, sachant qu’il existe d’autres variables, je vous renvoie à la documentation officielle.
Fichier : config.toml
|
|
Bien-sûr, allez lire la documentation officielle !
Admettons que vous voulez diriger vers des pages, et non pas des ancres… il vous faudra donc créer dans le répertoire content
les articles correspondants portant les noms servant de valeur à la variable url
.
Exemple :
Code : sh
content/
contact.md
projects.md
whoiam.md
Bien sûr, il est possible de mixer liens vers des pages et des ancres. À vous de modifier en conséquence…
Fichier : layout/partials/nav.html
|
|
On parcourt tout simplement l’ensemble de la variable .Site.Menus.main
pour restituer le code correspondant.
Maintenant si dans le fichier de configuration, vous ajoutez et remplissez la variable pre
, il vous faudra modifier le fichier HTML ainsi, par exemple :
{{ $icon := printf "<i class=\"%s\"></i>" .Pre }}
{{ $text := print $icon " " .Name | safeHTML }}
Cet exemple nous permet d’injecter du code HTML afin d’ajouter une icône avant le texte, ce qui est utile dans le contexte de la bibliothèque Font Awesome ou de toute autre semblable.
Pour obtenir un menu dropdown, tel que vous voyez en haut de page sur ce site , le plus simple est d’utiliser le framework Bootstrap.
En tenant compte du fait que vous savez intégrer la bibliothèque JS et la feuille CSS …
Dans le répertoire content
, il est nécessaire :
sections
sous-sections
Voici un exemple de structure de répertoires :
Code : sh
content/
dev/
_index.md
javascript/
_index.md
article.md
python/
_index.md
article.md
shell/
_index.md
article1.md
article2.md
article3.md
On remarque la présence de fichier _index.md
dans chaque répertoire. Le nom des fichiers article*.md
n’a pas d’importance.
De même le nom des répertoires importe peu en soit, par contre veillez bien à la correspondance avec la variable url
dans le fichier de configuration.
_index.md
Chaque répertoire a son propre fichier _index.md
dont le but est simplement d’activer le répertoire qui doit comporter à minima le Front Matter, au format YAML
, qui suit :
Fichier : _index.md
|
|
Si vous voulez qu’il ne soit pas indexé, rajouter la variable noindex: true
. (ce qui est évidemment utile dans le contexte de génération de flux de syndication
).
config.toml
La structure du fichier de configuration est sensiblement la même !
Fichier : config.toml
|
|
On remarque tout particulièrement :
parent
qui permettent de définir que l’entrée de menu en question a pour parent celui qui porte l’identifiant nommé. Dans cet exemple, elles ont pour valeur dev
et renvoie à l’entrée de menu qui a identifier = "dev"
, qui est bien aussi leur répertoire parent, dans la structure de répertoires
.Si vous avez un site multilangue , il faudra adapter l’exemple ci-dessus pour le faire correspondre…
Fichier : layout/partials/nav.html
|
|
“Voilà, c’est fini !”
Nous avons ainsi vu comment créer un menu simple ou un menu dropdown pour Hugo.
N’oubliez pas de vous amuser, puis de publier vos articles, et si besoin de vous faire aider par la communauté anglaise de Hugo.
Enjoy-ID! Enjoy-IT!
Parmi les flux de données, Hugo est capable de créer plusieurs flux dont RSS (actuellement, à la norme 2.0).
Hugo est donc capable de générer un flux RSS , ou de type JSON , mais pas ATOM - pour ce dernier, nous verrons comment faire dans le chapitre ad hoc.
Un petit tour sur la documentation officielle Hugo :
Commençons par les détails techniques suivants à-propos de la gestion de différents éléments ; chaque format de flux a ses propres spécificités, certaines sont communes ou peuvent se ressembler. Merci de lire les RFC adéquates.
Les trois formats de flux gérent un élément author
dans les différentes
entrées générées. Quant à l’auteur du site, là où ATOM et JSON ont leur
élément author
avec leurs spécificités, RSS a son propre élément
managingEditor
, voire webMaster
.
Il faut configurer le bloc author
dans le fichier de configuration,
de telle manière :
[params]
[params.author]
email = "courriel@domaine.tld"
name = "Nom Prénom"
Là où ATOM et RSS sont capables de générer un élément catégory
, JSON
utilise l’élément tag
.
Dans tous les cas, j’ai utilisé la taxonomie des tags pour les créer.
Il faut configurer la taxonomie dans le fichier de configuration, de telle manière :
[taxonomies]
tag = "tags"
Là où RSS a son élément copyright
,
link
qui permet de
cibler un fichier de licence - telle une licence CC
-
ainsi que son élément rights
.Il faut configurer la variable copyright
dans le fichier de configuration.
Là où RSS et JSON ont leur élément description
du flux, ATOM n’en a pas,
mais il est possible d’utiliser l’élément subtitle
.
Concernant l’usage de l’élément description
, j’utilise personnellement
la variable site.Params.description
.
Il faut configurer la variable description
dans le fichier de configuration.
Seul ATOM et RSS sont capables de générer un élément generator
, bien
qu’ATOM le fasse plus finement.
On peut utiliser les variables spécifiques à Hugo.
Pour RSS, l’identifiant d’une entrée est l’élément guid
. ATOM et JSON
ont un élément id
. ATOM a aussi son identifiant de site.
Il est important de veiller à ce que cet identifiant soit unique ; il y a plusieurs manières de les générer :
<id>{{ .Permalink }}</id>
tag
, définie par la RFC 4151,
de type tag:identifiant,DATE:alphanumerique
et où tag:identifiant,DATE
ne doit pas changer sur l’ensemble du site, seule la partie alphanumerique
sera l’objet de l’unicité de l’article ou de l’identifiant du site :
2019
; la préférence peut être
donnée à la forme YYYY-MM-DD
où l’année, le mois et le jour
sont séparés par un tiret -
, telle que 2019-10-07
qui peut
correspondre à la date de création de votre domaine, par exemple.alphanumerique
est un ensemble de lettres et de chiffres.{{ $url := urls.Parse .Permalink }}{{ $id := print "tag:" $url.Host ",2019-10-07:" }}<id>{{ $id }}website</id>
<id>{{ $id }}{{ anchorize .RelPermalink }}</id>
<id>
par <guid>
.
De même, si vous utilisez la notation par tag ou par UURI,
il vous faudra ajouter l’attribut isPermalink
, tel que :
isPermaLink="false"
UURI
définie par la RFC 4122 -
qui est humainement incompréhensible ; l’avantage avec Hugo est qu’on
peut la générer dynamiquement en utilisant la fonction sha
, tout
particulièrement sha1
conforme à la version 5 de ladite numérotation,
telle que :{{ $uuid := sha1 .Permalink }}<id>urn:uuid:{{substr $uuid 0 8}}-{{substr $uuid 10 4}}-{{substr $uuid 15 4}}-{{substr $uuid 20 4}}-{{substr $uuid 25 12}}</id>
Là où RSS gère l’élément image
pour afficher le logo,
icon
pour l’image de
favicon, et logo
pour votre… logo !Le code Hugo suivant, que j’utilise dans chacun des modèles, permet de limiter le nombre d’entrées selon :
disable_feed
sur true
, elles ne sont
pas incluses.range
pour générer dynamiquement le
nombre d’entrées - l’usage de la fonction dans le modèle pour JSON
différe légérement de celui pour les modèles ATOM et RSS - :{{- $limit := (cond (le site.Config.Services.RSS.Limit 0) 65536 site.Config.Services.RSS.Limit) -}}
{{- $pages := where site.RegularPages ".Params.disable_feed" "!=" true -}}
{{- if ge $limit 1 -}}{{- $pages = $pages | first $limit -}}{{- end -}}
config.toml
home
, section
et les deux
taxonomy
, taxonomyTerm
.Personnellement, je renomme le nom du flux RSS en modifiant dans le
fichier de configuration, la variable baseName
à rss
parce que je ne
pense pas que celui-ci doit porter le nom index
.
En effet, le nom rss.xml
est plus parlant !
[outputs]
home = ["HTML", "RSS"]
[outputFormats.RSS]
baseName = "rss"
_default
.index.xml
.J’ai créé mon propre modèle, tenant compte du fait d’être multilangue.
{{ printf `<?xml version="1.0" encoding="utf-8" standalone="yes" ?>` | safeHTML }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ if eq .Title site.Title }}{{ site.Title }}{{ else }}{{ with .Title }}{{.}}{{ T "on" }}{{ end }}'{{ site.Title }}'{{ end }}</title>
<link>{{ .Permalink }}</link>
{{ with site.Params.description -}}<description>{{ . }}</description>{{- end }}
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
<generator>Hugo {{ Hugo.Version }}</generator>
<image>
<description>Logo</description>
<height>128</height>
<link>{{ .Permalink }}</link>
<title>{{ if eq .Title site.Title }}{{ site.Title }}{{ else }}{{ with .Title }}{{.}}{{ T "on" }}{{ end }}'{{ site.Title }}'{{ end }}</title>
<url>{{ site.BaseURL }}img/Logo.png</url>
<width>128</width>
</image>
{{ with site.LanguageCode }}<language>{{.}}</language>{{end}}
{{ with site.Params.author.email }}<managingEditor>{{.}}{{ with site.Params.author.name }} ({{.}}){{end}}</managingEditor>
<webMaster>{{.}}{{ with site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}
{{ with site.Copyright }}<copyright>© {{ $.Date.Format "2006" | safeHTML }} {{ site.Author.name }}; {{.}}</copyright>{{end}}
{{ if not .Date.IsZero }}<lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
{{ with .OutputFormats.Get "RSS" }}{{ printf `<atom:link href=%q rel="self" type=%q />` .Permalink .MediaType | safeHTML }}{{ end }}
{{- $limit := (cond (le site.Config.Services.RSS.Limit 0) 65536 site.Config.Services.RSS.Limit) -}}
{{- $pages := where site.Pages ".Params.disable_feed" "!=" true -}}
{{- if ge $limit 1 -}}{{- $pages = $pages | first $limit -}}{{- end -}}
{{- range first $limit $pages }}
<item>
<title>{{ .Title }}</title>
<link>{{ .Permalink }}</link>
{{ with .Summary }}<description>{{ . | html }}</description>{{end}}
{{ with site.Params.author.email }}<author>{{.}}{{ with site.Params.author.name }} ({{.}}){{end}}</author>{{end}}{{ $url := printf "%s" "/tags/" | absLangURL }}
{{ with .Params.tags }}{{ range . }}<category domain="{{ $url }}{{urlize .}}/">{{.}}</category>{{end}}{{end}}
<guid>{{ .Permalink }}</guid>
<pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
</item>
{{ end }}
</channel>
</rss>
Nativement Hugo ne génére pas de flux Atom. Il faut tout créer ; ce n’est pas bien difficile !
Il est nécessaire de modifier le fichier de configuration pour :
Depuis Hugo 0.20, il faut ajouter :
[mediaTypes]
[mediaTypes."application/atom+xml"]
suffix = "xml"
Là, nous avons donc implémenté un nouveau type de format ayant pour mime
type : application/atom+xml
, et pour nom d’extension : xml
.
Depuis Hugo 0.44, pour que cela fonctionne correctement il faut ajouter :
[mediaTypes]
[mediaTypes."application/atom+xml"]
suffixes = ["xml"]
suffix
en suffixes = ['xml']
!La déclaration du format de sortie, à ajouter :
[outputFormats.Atom]
baseName = "atom"
isPlainText = false
mediaType = "application/atom+xml"
Puis, il faut ajouter "ATOM"
à votre variable home
, tel que :
[outputs]
home = ["HTML", "ATOM", "RSS"]
Le modèle peut simplement être créé dans le répertoire layouts/
et se
nommer index.atom.xml
, ou être dans son sous-répertoire _default/
et
se nommer, par exemple : home.atom.xml
.
{{ printf `<?xml version="1.0" encoding="utf-8" standalone="yes" ?>` | safeHTML }}
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="{{ with site.Language.Lang }}{{.}}{{end}}">
<id>{{ .Permalink }}</id>
<title>{{ if eq .Title site.Title }}{{ site.Title }}{{ else }}{{ with .Title }}{{.}}{{ T "on" }}{{ end }}'{{ site.Title }}'{{ end }}</title>
{{ with site.Params.description -}}<subtitle>{{ . }}</subtitle>{{- end }}
{{ with .OutputFormats.Get "ATOM" }}{{ printf `<link href=%q rel="self" type=%q />` .Permalink .MediaType | safeHTML }}{{end}}
{{ range .AlternativeOutputFormats -}}
<link href="{{ if eq .Name "HTML" }}{{ $.Permalink }}{{ else }}{{ printf `%s%s.%s` $.Permalink (.Name | lower) (index .MediaType.Suffixes 0) }}{{end}}" rel="alternate" {{ printf "type=%q" .MediaType.Type | safeHTMLAttr }} />
{{end}}{{ if site.IsMultiLingual }}{{ range site.Languages }}{{ if ne .Lang site.Language.Lang }}{{ $lang := .Lang }}
{{ with $.OutputFormats.Get "ATOM" }}{{ printf `<link href=%q hreflang=%q rel="alternate" type=%q />` (print $lang "/" .Name "." (index .MediaType.Suffixes 0) |absURL) $lang .MediaType | safeHTML }}{{end}}
{{ range $.AlternativeOutputFormats -}}
<link href="{{ if eq .Name "HTML" }}{{ printf `%s/` $lang | absURL }}{{ else }}{{ printf `%s/%s.%s` $lang (.Name | lower) (index .MediaType.Suffixes 0) | absURL }}{{end}}" hreflang="{{ $lang }}" rel="alternate" {{ printf "type=%q" .MediaType.Type | safeHTMLAttr }} />
{{end}}{{end}}{{end}}{{end}}{{ with site.Copyright }}{{ $lang := site.Language.Lang }}
<link href="http://creativecommons.org/publicdomain/zero/1.0/legalcode.{{ $lang }}" hreflang="{{ $lang }}" rel="license" />
<link href="http://creativecommons.org/publicdomain/zero/1.0/deed.{{ $lang }}" hreflang="{{ $lang }}" rel="license" />
<rights>© {{ $.Date.Format "2006" | safeHTML }} {{ site.Params.author.name }}</rights>{{end}}
<icon>/img/favicon.ico</icon>
{{ with site.Params.logo }}<logo>{{.}}</logo>{{end}}
{{ if not .Date.IsZero }}<updated>{{ .Date.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</updated>{{ end }}
{{ with site.Params.author.name }}
<author>
<name>{{.}}</name>
{{ with site.Params.author.email }}<email>{{.}}</email>{{end}}
<uri>{{ $.Permalink }}</uri>
</author>{{end}}
<generator uri="https://gohugo.io" version="{{ Hugo.Version }}">Hugo</generator>
{{- $limit := (cond (le site.Config.Services.RSS.Limit 0) 65536 site.Config.Services.RSS.Limit) -}}
{{- $pages := where site.RegularPages ".Params.disable_feed" "!=" true -}}
{{- if ge $limit 1 -}}{{- $pages = $pages | first $limit -}}{{- end -}}
{{- range first $limit $pages }}
<entry>
<id>{{ .Permalink }}</id>
<link href="{{ .Permalink }}" rel="alternate" type="text/html" />
<title>{{ .Title }}</title>{{ with site.Params.author }}
<author>
<name>{{.}}</name>
</author>{{end}}{{ $url := printf "%s" "/tags/" | absLangURL }}{{ with .Params.tags }}{{ range . }}
<category term="{{.}}" scheme="{{ print $url (urlize .) | absLangURL }}/" />{{end}}
{{end}}
{{ with .Content }}<content type="html">{{ `<![CDATA[` | safeHTML }}{{.}}]]></content>{{end}}
{{ with .Summary }}<summary type="html">{{ `<![CDATA[` | safeHTML }}{{.}}]]></summary>{{end}}
<published>{{ .Date.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</published>
{{ if gt .Lastmod .Date }}<updated>{{ .Lastmod.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</updated>{{end}}
</entry>
{{ end }}
</feed>
Pour générer le flux JSON, nous nous conformerons à la norme JSON Feed v1.
La déclaration de sortie de format à ajouter :
[outputFormats.JSON]
mediaType = "application/json"
baseName = "feed"
suffix = "json"
IsHTML = false
IsPlainText = true
noUgly = false
rel = "alternate"
Puis, il faut ajouter la déclaration JSON
à votre variable home
, tel que :
[outputs]
`home = ["HTML", "ATOM", "JSON", "RSS"]
En plus de la limite
mentionnée plus haut, nous
récupèrons le nombre de page, pour boucler correctement car le dernier
item
ne doit pas être suivi du symbole ‘,’ :
{{- $length := (len $pages) -}}
Et en fin de boucle range
, nous ajoutons :
{{ if ne (add $index 1) $length }},{{ end }}
Ainsi tant qu’il y a un élément suivant, il est précédé du symbole ‘,’ jusqu’au dernier.
{{- $limit := (cond (le site.Config.Services.RSS.Limit 0) 65536 site.Config.Services.RSS.Limit) -}}
{{- $pages := where site.RegularPages ".Params.disable_feed" "!=" true -}}
{{- if ge $limit 1 -}}{{- $pages = $pages | first $limit -}}{{- end -}}
{{- $length := (len $pages) -}}
{
"version": "https://jsonfeed.org/version/1",
"title": "{{ site.Title }}",
"home_page_url": "{{ site.BaseURL }}",
{{ with .OutputFormats.Get "JSON" -}}"feed_url": "{{.Permalink}}",{{- end }}
{{ with site.Params.description -}}"description": "{{ . }}",{{- end }}
{{ with site.Params.author.name }}
"author": {
"avatar": "{{ with site.Params.logo }}{{ . }}{{ end}}",
"name": "{{ . }}",
"url": "http://huc.fr.eu.org"
},
{{- end }}
{{ with site.Params.logo }}"icon": "{{ . }}",{{- end }}
"favicon": "/img/favicon.ico",
"items": [ {{- range $index, $elements := $pages -}}
{
"id": "{{ .Permalink }}",
"url": "{{ .Permalink }}",
"title": "{{ .Title | plainify }}",
{{ with site.Params.Author }}"author": { "name": "{{ . }}" }{{ end }}{{ with .Content }},
"content_text": {{ . | plainify | jsonify }},
"content_html": {{ . | safeHTML | jsonify }}{{ end }}{{ with .Summary }},
"summary": {{ . | plainify | jsonify }}{{ end }}{{ with .Params.tags }},
"tags": [{{ range $tindex, $tag := . }}{{ if $tindex }}, {{ end }}"{{ $tag| htmlEscape }}"{{ end }}]{{ end }}{{ if .PublishDate }},
"date_published": "{{ .PublishDate.Format "2006-01-02T15:04:05-01:00" | safeHTML }}"{{ end }}{{ if gt .Lastmod .Date }},
"date_modified": "{{ .Lastmod.Format "2006-01-02T15:04:05-01:00" | safeHTML }}"{{ end }}
}{{ if ne (add $index 1) $length }},{{ end }}{{- end }}
]
}
tag
sur le site Tag URIIntégrer une fonction de recherche au sein du site généré par Hugo peut se faire de différentes manières.
On va implémenter une manière très simple avec JQuery+UI, et cela nous prendra vraiment très peu de temps.
Étant donné qu’on peut parcourir l’ensemble des pages du site grâce à
la variable globale site.Pages
, on va se servir du mécanisme de la
méthode autocomplete()
fournie par la bibliothèque JQueryUI, pour
restituer les différents résultats selon le texte écrit.
Bien sûr, j’assume le fait que vous savez intégrer les appels de scripts JQuery et JQueryUI au sein de votre propre site.
Pour la partie JQuery, nous utilisons la gestion des événements de la
méthode autocomplete()
, à la différence près est que la variable
projects
va être implémentée par le biais de la fonction Hugo range
.
Le code JQuery :
<script>
$(function() {
var projects = [
{{- range site.Pages -}}
{{- $url := .RelPermalink -}}
{{- $title := .LinkTitle -}}
{
value: "{{ $title }}",
label: "{{- if eq $url $baseURL }}{{ site.Params.description }}{{ else if in $url "tags" }}{{- T "pageListTitle" }}{{ $title }}{{ else }}{{- safeHTML .Params.description -}}{{ end -}}",
url:"{{ $url }}"
},
{{- end -}}
];
$("#search").autocomplete({
minLength: 0,
source: projects,
focus: function( event, ui ) {
$("#search").val( ui.item.label );
return false;
},
select: function( event, ui ) {
$("#search").val( ui.item.label );
$("#replyer").val( ui.item.value );
return false;
}
})
.data('ui-autocomplete')._renderItem = function(ul, item) {
return $('<li>')
.append('<a href="' + item.url + '" alt="'+ item.label + '">' + item.value + '</a>' )
.appendTo(ul);
};
});
</script>
Quant à la partie HTML, elle est très simple ; il faut à minima les deux
éléments input
suivants :
<input class="form-control" id="search" placeholder="{{ T "searchHolderTitle" }}">
<input aria-hidden="true" id="replyer" class="hidden">
input
est celui qui “capte” le texte recherché{{ i18n "searchHolderTitle" }}
est juste pour le
contexte multilangue de ce site ; à remplacer par du texte selon votre goût…Que vous faites suivre du code Hugo puis du code JQuery
L’ensemble du code :
<div id="search">
<input class="form-control" id="search" placeholder="{{ T "searchHolderTitle" }}">
<input aria-hidden="true" id="replyer" class="hidden">
{{- $baseURL := site.BaseURL | absLangURL -}}
<!-- Javascript -->
<script>
$(function() {
var projects = [
{{- range site.Pages -}}
{{- $url := .RelPermalink -}}
{{- $title := .LinkTitle -}}
{
value: "{{ $title }}",
label: "{{- if eq $url $baseURL }}{{ site.Params.description }}{{ else if in $url "tags" }}{{- T "pageListTitle" }}{{ $title }}{{ else }}{{- safeHTML .Params.description -}}{{ end -}}",
url:"{{ $url }}"
},
{{- end -}}
];
$("#search").autocomplete({
minLength: 0,
source: projects,
focus: function( event, ui ) {
$("#search").val( ui.item.label );
return false;
},
select: function( event, ui ) {
$("#search").val( ui.item.label );
$("#replyer").val( ui.item.value );
return false;
}
})
.data('ui-autocomplete')._renderItem = function(ul, item) {
return $('<li>')
.append('<a href="' + item.url + '" alt="'+ item.label + '">' + item.value + '</a>' )
.appendTo(ul);
};
});
</script>
</div>
Et, voilà ! En quelques minutes, un “moteur de recherche” interne intégré à votre site Hugo.
Pour ce qui est de la démonstration, c’est ce qu’il y a dans le menu, en haut à droite de chacune des pages du site.
range
: Hugo Documentation : Functions > Range
- lien en anglaisautocomplete()
: https://jqueryui.com/autocomplete - lien en anglaisAutocomplete()
de JQueryUI : lire la documentation - lien en anglaisUn shortcode Hugo est un fichier contenant un type précis d’éléments HTML pour pouvoir augmenter les possibilités d’Hugo.
Lors d’un appel de ce shortcode depuis un fichier MD , un traitement est fait afin de remplacer l’appel du shorcode par le traitement restitué par le shortcode lui-même.
Il est ainsi possible par ce biais d’appeler des iframes, des figures, etc… voire un fichier MD lui-même.
Les shortcodes s’enregistrent dans le répertoire layout/shortcodes/
.
Pour l’instant, j’utilise le paquet tiers fournis par l’équipe OpenBSD :
Hugo Static Site Generator v0.53 openbsd/amd64 BuildDate: unknown
Mes usages pour l’instant sont très basiques ; en soit ce que je fais au-travers de plusieurs pourraient être directement écrit dans le fichier MD au format HTML, et zou, basta…
Néanmoins, il faut avouer que pour l’inclusion d’exemples de code, surtout dans un site multilangue est franchement utile.
Gestion des abbréviations, élément abbr
HTML :
Source brute vers le shortcode : abbr
<abbr {{ .Get 1 | printf `title=%q` | safeHTMLAttr }}>{{ .Get 0 | safeHTML }}</abbr>
L’appel du shortcode est simple :
Code : shortcode
{{< abbr accronym "Meaning of Acronym" >}}
accronym
est l’acronyme ou l’abbréviationMeaning of Acronym
est la signification de l’acronymeExemple : HTML est écrit ainsi :
Code : shortcode
{{< abbr HTML "HyperText Markup Language" >}}
La gestion des ancres dans une même page est un peu plus délicate :
Source brute vers le shortcode : anchor
{{ $txt := .Get 0 | safeHTML }}{{ $name := .Get 1 | lower | safeHTML }}{{ $anchor := anchorize $name }}
<a href="{{ printf "%s" .Page.RelPermalink }}#{{ $anchor }}" title="{{ i18n "shortcodeAnchorTitle" }}{{ $name }}">{{ $txt }}</a>
L’appel du shortcode :
Code : shortcode
{{< anchor "Texte" "Cible" >}}
Exemple : Ce lien renvoie au chapitre Description, et est écrit ainsi :
Code : shortcode
{{< anchor "lien" "description" >}}
Ahhh, la gestion des citations, autrement dit des éléments blockquote
m’en a fait baver. :p
En même temps, j’ai voulu pour des histoires d’esthétiques CSS les “améliorer”.
Basiquement, il suffit :
<blockquote>{{ $file := .Get 0 | readFile | htmlUnescape | safeHTML }}{{ $file }}</blockquote>
Mon shortcode est un poil plus évolué, car le site étant multilangue, il appele le shortcode interne dédiée à la gestion multilange, le reste n’étant que de la mise en forme CSS :
Source brute vers le shortcode : blockquote
<div class="info-quote"><p class="text-white-50">{{ T "quoteTitle" }}{{ if .Get 1 }} <em>{{ .Get 1 | safeHTML }}</em>{{ end }}</p></div><div class="quote"><blockquote>{{ $name := .Get 0 }}{{ $file := urlize (print "/content/inc/" $name) | readFile | htmlUnescape | safeHTML }}{{ $file }}</blockquote></div>
L’appel du shortcode est :
Code : shortcode
{{< blockquote "blockquote-filename" lang >}}
blockquote-filename
est le nom du fichier à appeler contenant la
citation à montrer.lang
est le nom de la langue cible, tel en
, fr
, etc…
""
Exemple :
Code : shortcode
{{< blockquote "web-hugo-shortcode-example-blockquote" fr >}}
Restitue :
Citation : fr
Ceci est une citation, en français, ni plus ni moins.
L’inclusion de code !
Pour pouvoir utiliser cette fonction, j’ai créé à la racine du répertoire
content/
un sous répertoire nommé inc
- vous pouvez très bien
l’appeler autrement, à vous d’adapter lors de l’appel du shortcode - ;
puis je créé mes fichiers à inclure dans ce répertoire.
Encore une fois, de manière basique, il suffit de :
Code : html
{{ $file := .Get 0 | readFile }}{{ $lang := .Get 1 }}{{ $opt := "" }}<div class="code">{{ highlight $file $lang $opt }}</div>
Mon shortcode, un poil plus évolué , du fait d’être multilangue :
Source brute vers le shortcode : code
{{ $name := .Get 0 }}{{ $file := urlize (print "/content/inc/" $name) | readFile }}{{ $lang := .Get 1 }}{{ $opt := "" }}
<div class="info-code"><p class="text-white-50">{{ i18n "codeTitle" }} <em>{{ $lang }}</em></p></div><div class="code">{{ highlight $file $lang $opt }}</div>
L’appel du shortcode :
Code : shortcode
{{< code "code-filename" language >}}
code-filename
est le nom du fichier à appeler contenant le code à
montrer.language
est le nom du langage cible, tel sh
, PHP
, python
, etc…
""
Exemple : Regardez bien, vous en avez un, juste au-dessus… lors de l’appel du premier shortcode concernant ce shortcode !
Un tout petit shortcode pour gérer un bout de texte en couleur… Néanmoins, pour cela, j’ai défini dans ma feuille de style, des types de couleurs nommées.
Source brute vers le shortcode : color
<span {{ .Get 0 | printf `class=%q` | safeHTMLAttr }}>{{ .Inner }}</span>
L’appel du shortcode est simple :
Code : shortcode
{{< color "css-name" >}}text{{< /color >}}
css-name
est le nom de la déclaration CSStext
est le texte à coloriserExemple : Ceci est un texte vert , celui qui suit est orangé , cet autre est rouge , etc…
L’inclusion d’un exemple de fichier est un dérivé du shortcode code , mais au lieu de produire un bloc de code précédé d’un entête présentant le code, j’appelle un entête qui restitue le nom de fichier tel que désiré.
Donc, basiquement c’est le même shortcode que pour code.
De manière plus évolué, cela donne ainsi :
Source brute vers le shortcode : file
{{ $name := .Get 0 | safeHTML }}{{ $file := urlize (print "/content/inc/" $name) | readFile }}{{ $lang := .Get 1}}{{ $filename := .Get 2 }}{{ $opt := "linenos=table" }}
<div class="info-file"><p class="text-white-50">{{ i18n "fileTitle" }}<em>{{ $filename }}</em></p></div><div class="code">{{ highlight $file $lang $opt }}</div>
L’appel du shortcode :
Code : shortcode
{{< file "example-file" language "filename" >}}
/example-file
est le nom du fichier à appeler contenant le contenu
d’un fichier à montrer.language
est le nom du langage cible, tel sh
, PHP
, python
, etc…
""
filename
est le nom du fichier - celui qui est affiché.Exemple : y’a-t-il vraiment besoin encore de le prouver ? Regardez bien juste au-dessus ;)
Il est vrai que Markdown a un code prévu pour l’inclusion d’image, mais
j’ai crée ce shortcode pour pouvoir spécifier une taille d’image et
renvoyé vers l’image source par le biais d’un élément HTML a
appliqué
sur l’élément HTML img
.
Prenons en considération que les images sont fournies en tant qu’assets :
Source brute vers le shortcode : img
1{{/* runner for assets/image */}}
2{{- $src := resources.Get (printf "%s%s" "/images/" (.Get "s")) -}}{{- $alt := .Get "a" | safeHTML -}}{{- $width := printf "%s" (.Get "w") -}}
3{{- $img := $src -}}
4{{- with $width -}}{{- $img = $src.Resize (printf "%sx" $width) -}}{{- end -}}
5{{- with $img -}}
6<figure>
7 <a href="{{ $src.RelPermalink }}" title="{{ $alt }}">
8 <picture>
9 <!-- <source srcset="/img/.avif" type="image/avif"> -->
10 {{- with .Resize (printf "%dx%d webp" .Width .Height) }}
11 <source srcset="{{ .RelPermalink }}" type="image/webp">
12 {{ end }}
13 <img alt="{{ $alt }}" loading="lazy" src="{{ .RelPermalink }}" type="{{ .MediaType }}" height="{{ .Height }}" width="{{ .Width }}">
14 </picture>
15 </a>
16 <figcaption>{{ $alt }}</figcaption>
17</figure>
18{{- end -}}
L’appel du shortcode :
Code : shortcode
{{< img a="alt" s="src" w="width" >}}
Les paramètres nommés sont :
a
: l’équivalent de l’attribut alt
s
: l’équivalent de l’attribut src
w
: l’équivalent de l’attribut width
Exemple :
Cette image représentant mon logo, ayant pour titre “Mon Logo”, a une taille de 192 px , redimensionnée à la taille de 124 pixels, et est au format PNG .
Concernant les images au format SVG, je les gère différemment du précédent shortcode :
Source brute vers le shortcode : figure-svg
1{{/* runner for assets/svg */}}
2{{- $class := .Get "class" -}}{{- $src := resources.Get (printf "%s%s" "/svg/" (.Get "src")) -}}{{ $title := .Get "title" }}
3{{ with $src }}
4<figure class="{{ if $class }}{{ $class }}{{ end }}">
5 <a href="{{ .RelPermalink }}" title="{{ $title }}">
6 {{ .Content | safeHTML }}
7 </a>
8 {{ if $title }}<figcaption aria-hidden="true" class="hidden" hidden>{{ $title }}</figcaption>{{ end }}
9</figure>
10{{ end }}
L’appel du shortcode :
Code : shortcode
{{< figure-svg class="class-name" src="image.svg" title="the title" >}}
Exemple :
Ce shortcode est utilisé pour la gestion de l’élément HTML kbd
.
Source brute vers le shortcode : kbd
{{ $k := .Get 0 | safeHTML }}<kbd>{{ $k }}</kbd>
L’appel du shorcode :
Code : shortcode
{{< kbd key >}}
key
est le nom de la touche clavier !Exemple : voici le rendu de la touche A !
Ce shortcode a deux versions légérement différentes. J’ai commencé avec la première , puis un jour, je me suis demandé comment faire pour “injecter” aussi le nom d’une ancre ; la v2 est née !
Pour gérer les liens internes entre les pages de ce site, je me suis évertué à mettre en place le shortcode suivant :
Source brute vers le shortcode : inside
1{{ $link := .Get 0 }}{{ $link := replace $link ":" "/" }}{{ $url := (print ( relLangURL $link ) "/") }}
2{{ if .Get 1 }}{{ $txt := .Get 1 }}
3<a class="inside" href="{{ $url }}" title="{{ i18n "lnkInsideTitle" }}{{ with .Site.GetPage $link }}{{ .Title }}{{ end }}">{{ $txt }}</a>
4{{ else }}
5{{ with .Site.GetPage $link }}{{ $title := .Title }}<a class="inside" href="{{ $url }}" title="{{ i18n "lnkInsideTitle" }}{{ $title }}">{{ $title }}</a>{{ end }}
6{{ end }}
De même, j’ai créé une définition CSS, nommée inside
, qui me permet de
modifier légérement le rendu pour les liens internes.
L’appel du shortcode :
Code : shortcode
{{< inside "section:subsection:pagename" "Title" >}}
:
Exemples :
Cette version est subtilement différente :
Source brute vers le shortcode : inside2
1{{ $link := .Get "l" }}{{ $link := replace $link ":" "/" }}{{ $url := (print ( relLangURL $link ) "/") }}{{ $anchor := .Get "a" }}
2{{ if .Get "t" }}{{ $txt := .Get "t" }}<a class="inside" href="{{ $url }}{{ if $anchor }}#{{ $anchor }}{{ end }}" title="{{ i18n "lnkInsideTitle" }}'{{ with .Site.GetPage $link }}{{ .Title }}{{ end }}'">{{ $txt }}</a>
3{{ else }}
4{{ with .Site.GetPage $link }}{{ $title := .Title }}<a class="inside" href="{{ $url }}{{ if $anchor }}#{{ $anchor }}{{ end }}" title="{{ i18n "lnkInsideTitle" }}'{{ $title }}'">{{ $title }}</a>{{ end }}
5{{ end }}
L’appel du shortcode :
Code : shortcode
{{< inside2 l="section:subsection:pagename" t="title" a="anchor-name" >}}
Les paramètres nommés sont :
a
: cible une ancre dans le document appelé ; bien-sûr, cette ancre
doit exister… dans le document en question. Peut-être omise !l
: nom du lien interne ; les noms de sections et pages sont séparés
par le symbole :
t
: le titre. Peut être omis, dans ce cas-là sera affiché celui de
la page appelée.Exemple :
Les blocs d’alertes ou de notes sont des blocs de code HTML présentant un texte et mis en valeur selon un identifiant, qui est traduit selon la langue utilisée.
La valeur de cet identifiant peut être :
danger
pour afficher une alerte de type ‘danger’ qui aura une teinte
rougéeinfo
pour afficher un message de type ‘information’ qui aura une
teinte bleutéesuccess
pour afficher un message de type ‘succès’ qui aura une
teinte vertetip
pour afficher un message de type ‘astuce’ qui aura une teinte
jaune.warning
pour afficher un message de type ‘attention’ qui aura une
teinte orangée, jaunâtre.Bien-sûr, ces teintes dépendent des déclarations CSS.
Le shortcode en lui-même :
Source brute vers le shortcode : note
{{ $class := .Get 0 }}{{ $wrd := T (printf "alert-%s" $class) }}
<div class="info-tab {{ $class }}-icon">{{ $wrd }}</div><div class="alert alert-{{ $class }}" role="alert">{{ .Inner | .Page.RenderString }}</div>
L’appel du shortcode est :
Code : shortcode
{{< note id >}}
Ceci est un message
{{< /note >}}
Exemples :
Ce shortcode n’existe pas pour gérer les tags générés par Hugo, mais pour
gérer l’URL d’un tag au sein d’une page Markdown. Le shortcode va
générer un élément a
HTML adéquat. Il tient compte de la gestion
multilangue du site.
Au sein de la page Markdown, j’intégre un mot qui se veut être un renvoi vers la page tag ad hoc.
Côté CSS, j’ai défini l’attribut ::after
sur la définition .tag
pour
ajouter par la CSS l’information (tag)
précédé du terme en question.
Ce qui permet visuellement de le différencier des autres liens.
Source brute vers le shortcode : tag
{{ $txt := .Get 0 }}{{ $href := "/" | relLangURL}}{{ $href := (printf "%s%s%s" $href "/tags/" $txt) | urlize }}<a class="tag" href="{{ $href }}">{{ $txt }}</a>
L’appel du shortcode :
Code : shortcode
{{< tag tag-name >}}
Exemple : le mot Hugo est un lien vers l’URL des articles contenant le tag “Hugo”.
Pour faire un lien vers la documentation officielle d’Hugo, je me suis amusé à écrire ce shortcode :
Code : shortcode
{{< gohugo n="pagename" s="section" a="anchor-name" >}}
n
est le nom de la page dans la documentation du site Gohugo.ios
est le nom de la section dans la documentation du site Gohugo.ioa
est le nom de l’ancre à cibler dans la pageSource brute vers le shortcode : gohugo
{{ $section := .Get "s" }}{{ $name := .Get "n" }}{{ $anchor := .Get "a" }}<a href="https://gohugo.io/{{ $section }}/{{ $name }}/{{ if $anchor }}#{{ $anchor}}{{ end }}" title="{{ i18n "shortcodeGoHugoTitle" }}{{ humanize $section }} > {{ humanize $name }}">{{ i18n "shortcodeGoHugoDocTitle" }}{{ humanize $section }} > {{ humanize $name }}</a>
Exemple: Le lien vers la page Hugo Documentation : Content management > Shortcodes Hugo.
Voici le shortcode correspondant :
Code : shortcode
{{< gohugo n="shortcodes" s="content-management" >}}
Utilisant souvent des renvois vers les manpages officiels d’OpenBSD, je me suis crée le shortcode suivant :
Code : shortcode
{{< man title digit >}}
digit
) est fourni, le shortcode le restituera à la
fois, dans l’URL reconstituée, que dans le texte affiché. Dans l’URL, ce
sera de type txt.digit
; le texte affiché aura le chiffre entouré des
parenthèses, tel que txt(digit)
.Source brute vers le shortcode : man
{{ $txt := .Get 0 }}{{ $nb := .Get 1}}
<a class="man" href="https://man.openbsd.org/{{ $txt }}{{ if $nb }}{{ print "." $nb }}{{ end }}" title="{{ i18n "manpageTitle" }}{{ $txt }}">{{ $txt }}{{ if $nb }}{{ print "(" $nb ")" }}{{ end }}</a>
Exemples :
De même pour l’encyclopédie Wikipédia, le shortcode créé est le suivant :
Code : shortcode
{{< wp "url-article" >}}
Source brute vers le shortcode : wp
{{ $txt := .Get 0 }}{{ $title := print (i18n "wpTitleArticle") $txt }}<a href="https://{{ .Site.Language.Lang }}.wikipedia.org/wiki/{{ $txt }}" title="{{ $title }}">Wikipedia :: {{ $txt }}</a>
Exemples :
Pour finir, n’hésitez pas à vous amuser avec les shortcodes, faites-vous aider sur le forum de la communauté, malheureusement pour nous francoph(on|il)es, en anglais.
Pour déployer un site fait avec le générateur de site statique Hugo, il existe plusieurs solutions :
Dans le contexte de déploiement “simple”, il suffit de créer le script de
déploiement nommé deploy
à la racine du projet Hugo !
Déployer un site avec rsync
est très simple. rsync est l’outil pour
de la synchronisation de données ; il le fait, et il le fait bien.
Après avoir installé l’outil :
# apt install rsync
# pkg_add rsync
- pour information, depuis OpenBSD v6.5,
il existe nativement dans le système de base, l’outil openrsync
;
reproduisant le comportement de rsync, il est asujetti au même problème décrit ci-dessous -En assumant le fait que vous avez une authentification SSH sur le serveur où vous désirez vous synchroniser, et mieux une authentification par clé SSH.
#!/bin/sh
user=userid
host=servername
port=22
dir_dist=/remote_folder/
file_id="$HOME/.ssh/id_ed25519"
hugo && rsync -avz --delete -e "ssh -i ${file_id} -p ${port}" public/ "${user}"@"${host}":"${dir_dist}"
userid
est l’identifiant utilisateur SSHservername
est le nom FQDN
ou l’adresse IP du serveur SSH vers lequel se connecterremote_folder
est le nom réel du répertoire distant sur lequel se connecter.Cet exemple montre le déploiement d’un site avec rsync utilisant une connexion SSH.
SshFS peut être installé par votre gestionnaire de paquets :
# apt install sshfs
# pkg_add sshfs
L’avantage de SshFS est que c’est un outil qui permet de se connecter que votre utilisateur SSH soit soumis ou non à un chroot SSH en montant le répertoire distant dans l’espace utilisateur local. Attention, cela ralentit l’accès réseau, rien de grave, mais à savoir…
Sous OpenBSD, c’est un peu plus délicat ; du fait de fonctionner principalement
sur ce SE
, j’expliquerais
pour celui-ci. Au cas où, adaptez à votre cas.
En effet, sous OpenBSD, il est nécessaire d’avoir des droits administrateur,
et il est recommandé d’avoir paramétré
doas
.
Pour monter localement le système de fichier :
$ doas sshfs -C -p $port -o allow_other -o uid=$(id -u $USER) -o gid=$(id -g $USER) ${id}@${host}:${dir_dist} "${dir_mount}"
Une fois connecté, le répertoire distant est monté localement là où vous le désirez.
C’est le moment d’utiliser rsync
mais au lieu de chercher à se
connecter - puisque c’est déjà fait -, l’outil va permettre de synchroniser
d’un répertoire source local vers le répertoire source distant, monté localement.
rsync s’utilise donc ainsi :
cd "${dir_local}" && rsync -av --delete --human-readable --progress --stats "." "${dir_mount}"
Pour le démonter proprement, ce sera :
$ doas umount "${dir_mount}"
Ceci étant dit, voici à quoi peut ressemble le fichier de déploiement dans ce contexte SshFS + rsync :
#!/bin/sh
#set -x
[ -n "$TERM" ] && clear
ROOT="$(dirname "$(readlink -f -- "$0")")"
id=userid
host=servername
port=22
### the directory where your web site files should go
## dir_dist: relative to chroot SSH
dir_dist="/www/"
dir_local="$ROOT/public/"
dir_mount="$HOME/servers/${id}/"
file_id="$HOME/.ssh/id_ed25519"
rsync_opts="--human-readable --progress --stats "
################################################################################
###
##
# Fonctions
##
###
################################################################################
_mount() {
[ ! -d "${dir_mount}" ] && mkdir -p "${dir_mount}"
# for Debian
[ -d "${dir_mount}" ] && sshfs -C -p $port -o uid=$(id -u $USER) -o gid=$(id -g $USER) -o IdentityFile="${file_id}" ${id}@${host}:${dir_dist} "${dir_mount}"
# for OpenBSD
[ -d "${dir_mount}" ] && doas sshfs -C -p "${port}" -o allow_other -o uid=$(id -u $USER) -o gid=$(id -g $USER) -o IdentityFile="${file_id}" "${id}"@"${host}":"${dir_dist}" "${dir_mount}"
}
_rsync() {
cd "${dir_local}" || exit
rsync -av --delete $rsync_opts "." "${dir_mount}"
}
_umount() {
fusermount -u "${dir_mount}" # pour Debian
doas umount "${dir_mount}" # pour OpenBSD
}
################################################################################
###
##
# Execution
##
###
################################################################################
hugo
status="$?"
if [ "${status}" -eq 0 ]; then
if _mount; then
_rsync
_umount
fi
fi
userid
est l’identifiant utilisateur SSHservername
est le nom FQDN
ou l’adresse IP du serveur SSH vers lequel se connecterdir_mount
est le nom du répertoire local vers lequel le répertoire
distant va être monté.lftp est un couteau suisse de la connexion réseau. Il fait du FTP, FTPS, de la synchronistation de document, sur IPv4, IPv6, au-travers des protocoles HTTP(S) ; il fait même du trafic bittorent, voire partiellement du WebDAV… et il est capable de se connecter en SFTP !
Voilà le “miracle” : un client réseau sachant faire du mirroring de données en SFTP !!!
Donc, installez avec votre gestionnaire de paquets le binaire :
# apt install lftp
# pkg_add lftp
#!/bin/sh
#set -x
[ -n "$TERM" ] && clear
ROOT="$(dirname "$(readlink -f -- "$0")")"
id=userid
host=servername
port=22
### the directory where your web site files should go
## dir_dist: relative to chroot SSH
dir_dist="/www/"
dir_local="$ROOT/public/"
file_id="$HOME/.ssh/id_ed25519"
hugo
lftp -e "set ftp:ssl-allow no; set sftp:connect-program ssh -a -x -i ${file_id}; mirror -e -R ${dir_local} ${dir_dist}; quit;" -p "${port}" sftp://"${id}":"${passwd}"@"${host}"
userid
est l’identifiant utilisateur SSHservername
est le nom FQDN
ou l’adresse IP du serveur SSH vers lequel se connecterrclone est un puissant outil en ligne de commande pour gérer le stockage de fichiers à-travers de nombreuses solutions de type nuage informatique, systèmes de fichers divers et variés, mais aussi basiquement par le biais du protocol SFTP.
Installez avec votre gestionnaire de paquets le binaire :
# apt install rclone
# pkg_add rclone
La configuration par l’usage de l’option config
tel que : $ rclone config
sftp
lorsque l’invite
vous pose la question.L’invite de commande de rclone est en anglais, mais elle est aisée à utiliser. Je vous renvoie à la page de la documentation SFTP, dont la référence est dans la section Documentation ; allez-y absolument faire un tour de lecture !
Le fichier de configuration se trouvera être écrit dans votre répertoire
personnel ~/.config/rclone/rclone.conf
, par défaut.
Il sera de ce type :
[nom_remote]
type = sftp
host = adresse_ip ou FQDN
user = id_ssh
port = 22
key_file = ~/.ssh/id_ed25519
key_use_agent = true
pubkey_file = ~/.ssh/id_ed25519.pub
use_insecure_cipher = false
md5sum_command = none
sha1sum_command = none
Il ne reste plus qu’à utiliser rclone dans votre script de déploiement d’Hugo :
#!/bin/sh
#set -x
[ -n "$TERM" ] && clear
ROOT="$(dirname "$(readlink -f -- "$0")")"
id=userid
host=servername
port=22
### the directory where your web site files should go
## dir_dist: relative to chroot SSH
dir_dist="/www/"
dir_local="$ROOT/public/"
file_id="$HOME/.ssh/id_ed25519"
rclone_remote="nom_remote"
hugo
rclone sync -i "${dir_local}" "${rclone_remote}":"${dir_dist}"
Voilà, c’est fini.
Maintenant, vous savez déployer votre site statique Hugo, que avec rsync/ssh
, sshfs+rsync
, lftp
, voire par rclone
.
La documentation officielle :
pysnmp est une librairie en Python, multiplateforme pour SNMP , capable d’agir en tant qu’agent, gestionnaire, proxy, sur les trois versions du protocole SNMP, de “discuter” sur les protocoles réseaux IPv(4|6).
Le propos est de (dé) montrer l’utilisation de pysnmp avec l’authentification forte de la v3 de SNMP.
Sous OpenBSD, Installez
le paquet py3-snmp
Malheureusement, cette version ne semble pas (pleinement ?) fonctionnelle.
Donc, installons-le par le biais de l’outil pip
:
# python3.7 -m pip install --upgrade --user pysnmp
L’équipe OpenBSD a créé ses propres MIB - ce sont des arborescences de données, que l’on peut aussi appeler “base de données arborescente” -
pysnmp nativement n’est pas capable de les interroger. Mais heureusement, on peut lui “donner à manger”.
Avec pysnmp est fourni un outil nommé mibdump.py
- depuis la v4.3 ;
avant il fallait utiliser build-pysnmp-mib.py
-, et lui indiquer le
chemin des MIB d’OpenBSD.
Ces MIB sont fournis dans le répertoire /usr/share/snmp/mibs/
.
$ for file in /usr/share/snmp/mibs/*; do mibdump.py $file; done
Source MIB repositories: /usr/share/snmp/mibs, file:///usr/share/snmp/mibs, http://mibs.snmplabs.com/asn1/@mib@
Borrow missing/failed MIBs from: http://mibs.snmplabs.com/pysnmp/notexts/@mib@
Existing/compiled MIB locations: pysnmp.smi.mibs, pysnmp_mibs
Compiled MIBs destination directory: /home/zou/.pysnmp/mibs
MIBs excluded from code generation: INET-ADDRESS-MIB, PYSNMP-USM-MIB, RFC-1212, RFC-1215, RFC1065-SMI, RFC1155-SMI, RFC1158-MIB, RFC1213-MIB, SNMP-FRAMEWORK-MIB, SNMP-TARGET-MIB, SNMPv2-CONF, SNMPv2-SMI, SNMPv2-TC, SNMPv2-TM, TRANSPORT-ADDRESS-MIB
MIBs to compile: OPENBSD-BASE-MIB
Destination format: pysnmp
Parser grammar cache directory: not used
Also compile all relevant MIBs: yes
Rebuild MIBs regardless of age: no
Dry run mode: no
Create/update MIBs: yes
Byte-compile Python modules: yes (optimization level no)
Ignore compilation errors: no
Generate OID->MIB index: no
Generate texts in MIBs: no
Keep original texts layout: no
Try various file names while searching for MIB module: yes
Created/updated MIBs: OPENBSD-BASE-MIB
Pre-compiled MIBs borrowed:
Up to date MIBs: OPENBSD-BASE-MIB, SNMPv2-CONF, SNMPv2-SMI, SNMPv2-TC
Missing source MIBs:
Ignored MIBs:
Failed MIBs:
(…)
je n’ai volontairement recopié que la sortie écran du premier fichier
Les lignes à vérifier sont :
MIBs to compile
qui nous montre quel fichier est compiléCreated/updated MIBs
qui nous restitue le nom du nouveau fichier
compiléIgnored MIBs
et Failed MIBs
qui peut informer des informations MIB
défectueuses ou ignoréesUne fois le traitement terminé, les nouveaux fichiers compilés ont été
créés dans : ~/.pysnmp/mibs/
Mais avant de (sa?)voir comment utiliser les fichiers MIB nouvellement créés, voyons comment utiliser pysnmp dans le contexte de SNMPv3. Je m’attarderais très particulièrement sur la manière de l’utiliser avec l’authentification forte.
Appelons l’outil :
from pprint import PrettyPrinter
from pysnmp.hlapi import *
from pysnmp.smi.view import MibViewController
pp = PrettyPrinter(indent=4)
Puis paramétrons les variables nécessaires pour l’authentification forte, à savoir :
host = "localhost"
user = "uenc"
authkey = "zx4pyrfyeu5x5c3kxqirhtsxksbmawju"
privkey = "XHVBzYUpP8dKns75BaSwq6t7SUgF6oMz"
j’ai repris celles de l’exemple, dans l’article sur l’outil natif à OpenBSD, snmp , ni plus ni moins.
Une des premières choses à déclarer est le Contrôleur de Vue MIB, qui nécessite la création d’un moteur SNMP :
# create SNMP Engine and MIB view Controller
se = SnmpEngine()
mvc = se.getUserContext('mibViewController')
if not mvc:
mvc = MibViewController(se.getMibBuilder())
Et, maintenant, nous allons voir comment appeler les MIB d’OpenBSD !
# get Object Identity and Type
oi = ObjectIdentity('iso.org.dod.internet.private.enterprises.openBSD.memMIBObjects')
oi.addMibSource('~/.pysnmp/mibs/')
oi.loadMibs('OPENBSD-BASE-MIB')
oi.loadMibs('OPENBSD-CARP-MIB')
oi.loadMibs('OPENBSD-MEM-MIB')
oi.loadMibs('OPENBSD-PF-MIB')
oi.loadMibs('OPENBSD-RELAYD-MIB')
oi.loadMibs('OPENBSD-SENSORS-MIB')
oi.loadMibs('OPENBSD-SNMPD-CONF')
oi.resolveWithMib(mvc)
ObjectIdenttity()
: en premier, nous construisons un objet identifiant,
selon un OID précis que nous recherchons - ici le nombre d’interfaces
vues par la MIB PF d’OpenBSDaddMibSource()
: référence le chemin où ont été créé les fichiers MIB
précédemmentloadMibs()
: pour appeler chacun des fichiers MIB créés précédemment
resolvedWithMib()
: nous permet d’appliquer le Contrôleur de Vue MIB
sur l’objetContinuons avec la gestion des données utilisateurs nécessaires à l’identification :
uud = UsmUserData(user, authKey=authkey, privKey=privkey,
authProtocol=usmHMAC384SHA512AuthProtocol,
privProtocol=usmAesCfb128Protocol)
Pour information, les différentes valeurs du protocole de chiffrement d’authentification sont :
usmNoAuthProtocol
pour aucun protocolusmHMACMD5AuthProtocol
pour le chiffrement MD5
usmHMACSHAAuthProtocol
pour SHA
usmHMAC128SHA224AuthProtocol
pour SHA-224
usmHMAC192SHA256AuthProtocol
pour SHA-256
usmHMAC256SHA384AuthProtocol
pour SHA-384
usmHMAC384SHA512AuthProtocol
pour SHA-512
Concernant le chiffrement du protocole de confidentialité, ces valeurs sont :
usmNoPrivProtocol
si aucunusmDESPrivProtocol
pour DES
usmAesCfb128Protocol
pour AES
(Pour information, il en existe d’autres, mais ce sont surtout des “drafts”, du moins pour l’instant !)
Nous avons besoin de construire le générateur de la commande get
:
gc = getCmd(se, uud, UdpTransportTarget((host, 161)), ContextData(),
ObjectType(oi))
# return results
errorIndication, errorStatus, errorIndex, varBinds = next(gc)
# Display informations
if errorIndication:
print(str(errorIndication))
elif errorStatus:
print('%s at %s' % (str(errorStatus.prettyPrint()),
errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
else:
for varBind in varBinds:
oid = varBind[0]
value = varBind[1]
print(oid)
print(value)
ne pas s’inquiéter du temps que mets la requête à s’afficher ; cela est dû au chiffrement des informations
L’exécution nous retourne ceci :
1.3.6.1.4.1.30155.5
Pour finir, nous venons de voir que discuter avec l’outil pysnmp sur SNMPv3 avec authentification forte EST possible.
Le plus délicat est de récupérer les informations dans les MIB. Trés vite, vous allez avoir à buter sur des erreurs incompréhensibles, et difficiles à résoudre. Et, ça, ça le don de m’énerver ! (enfin presque…)
Usage:
command [options] [arguments]
Options:
-h
, --help
Display this help message-q
, --quiet
Do not output any message-V
, --version
Display this application version
--ansi
Force ANSI output--no-ansi
Disable ANSI output-n
, --no-interaction
Do not ask any interactive question
--no-warnings
Skip global warnings, show command output only-v
|vv
|vvv
, --verbose
Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debugAvailable commands:
check
check dependencies of the server environmenthelp
displays help for a commandlist
Lists commandsstatus
show some status informationupgrade
run upgrade routines after installation of a new release. The release has to be installed before.config
config:app:delete
Delete an app config valueconfig:app:get
Get an app config valueconfig:app:set
Set an app config valueconfig:import
Import a list of configsconfig:list
List all configsconfig:system:delete
Delete a system config valueconfig:system:get
Get a system config valueconfig:system:set
Set a system config valuedb
db:add-missing-indices
Add missing indices to the database tablesdb:convert-filecache-bigint
Convert the ID columns of the filecache to BigIntdb:convert-mysql-charset
Convert charset of MySQL/MariaDB to use utf8mb4db:convert-type
Convert the Nextcloud database to the newly configured oneencryption
encryption:change-key-storage-root
Change key storage rootencryption:decrypt-all
Disable server-side encryption and decrypt all filesencryption:disable
Disable encryptionencryption:enable
Enable encryptionencryption:encrypt-all
Encrypt all files for all usersencryption:list-modules
List all available encryption modulesencryption:set-default-module
Set the encryption default moduleencryption:show-key-storage-root
Show current key storage rootencryption:status
Lists the current status of encryptionfederation
federation:sync-addressbooks
Synchronizes addressbooks of all federated cloudsfiles
files:cleanup
cleanup filecachefiles:recommendations:recommend
files:scan
rescan filesystemfiles:scan-app-data
rescan the AppData folderfiles:transfer-ownership
All files and folders are moved to another user - shares are moved as well.group
group:add
Add a groupgroup:adduser
add a user to a groupgroup:delete
Remove a groupgroup:list
list configured groupsgroup:removeuser
remove a user from a groupintegrity
integrity:check-app
Check integrity of an app using a signature.integrity:check-core
Check integrity of core code using a signature.integrity:sign-app
Signs an app using a private key.integrity:sign-core
Sign core using a private key.log
log:file
manipulate logging backendlog:manage
manage logging configurationlog:tail
Tail the nextcloud logfilelog:watch
Watch the nextcloud logfilebackground
background:ajax
Use ajax to run background jobsbackground:cron
Use cron to run background jobsbackground:webcron
Use webcron to run background jobsmaintenance
maintenance:data-fingerprint
update the systems data-fingerprint after a backup is restoredmaintenance:mimetype:update-db
Update database mimetypes and update filecachemaintenance:mimetype:update-js
Update mimetypelist.jsmaintenance:mode
set maintenance modemaintenance:repair
repair this installationmaintenance:theme:update
Apply custom theme changesmaintenance:update:htaccess
Updates the .htaccess filemigrations
migrations:execute
Execute a single migration version manually.migrations:generate
migrations:generate-from-schema
migrations:migrate
Execute a migration to a specified version or the latest available version.migrations:status
View the status of a set of migrations.security
security:certificates
list trusted certificatessecurity:certificates:import
import trusted certificatesecurity:certificates:remove
remove trusted certificateupdate
update:check
Check for server and app updatesuser
user:add
adds a useruser:delete
deletes the specified user and all datas useruser:disable
disables the specified useruser:enable
enables the specified useruser:info
show user infouser:lastseen
shows when the user was logged in last timeuser:list
list configured usersuser:report
shows how many users have accessuser:resetpassword
Resets the password of the named useruser:setting
Read and modify user settingsnotification
notification:generate
Generate a notification for the given userversions
versions:cleanup
Delete versions: delete versions of the given user(s), if no user is given all versions will be deletedversions:expire
Expires the users file versions: expire file versions of the given user(s), if no user is given file versions for all users will be expired.app
app:check-code
check code to be compliantapp:disable
disable an appapp:enable
enable an appapp:getpath
Get an absolute path to the app directoryapp:install
install an appapp:list
List all available appsapp:remove
remove an appapp:update
update an app or all appsmail
mail:account:create
creates IMAP accountmail:account:export
Exports a user’s IMAP account(s)circles
circles:clean
remove all extra data from databasecircles:fixuniqueid
fix Unique Id issue.deck
deck:export
Export a JSON dump of user datatalk
talk:command:add
Add a new commandtalk:command:add-samples
Adds some sample commands: /wiki, …talk:command:delete
Remove an existing commandtalk:command:list
List all available commandstalk:command:update
Add a new commandtalk:signaling:add
Add an external signaling server.talk:signaling:delete
Remove an existing signaling server.talk:signaling:list
List external signaling servers.talk:stun:add
Add a new STUN server.talk:stun:delete
Remove an existing STUN server.talk:stun:list
List STUN servers.talk:turn:add
Add a TURN server.talk:turn:delete
Remove an existing TURN server.talk:turn:list
List TURN servers.twofactorauth
twofactorauth:cleanup
Clean up the two-factor user-provider association of an uninstalled/removed providertwofactorauth:disable
Disable two-factor authentication for a usertwofactorauth:enable
Enable two-factor authentication for a usertwofactorauth:enforce
Enabled/disable enforced two-factor authenticationtwofactorauth:state
Get the two-factor authentication (2FA) state of a userdav
dav:create-addressbook
Create a dav addressbookdav:create-calendar
Create a dav calendardav:list-calendars
List all calendars of a userdav:move-calendar
Move a calendar from an user to anotherdav:remove-invalid-shares
Remove invalid dav sharesdav:send-event-reminders
Sends event remindersdav:sync-birthday-calendar
Synchronizes the birthday calendardav:sync-system-addressbook
Synchronizes users to the system addressbookMettre à jour NC (Nextcloud ) n’est pas compliqué en soit… Soit, vous le faites :
Cet article a juste pour propos d’expliquer succinctement le processus manuel sous OpenBSD. L’instance que j’administre est donc sous OpenBSD, desservie par le serveur web Nginx, et le couple PHP+MySQL (en l’occurence actuellement PHP 7.3)
C’est le processus que j’utilise depuis plusieurs années, depuis la version 15.*, qui en fait se veut simple, pratique et rapide.
La première chose que je fais est de désactiver le domaine au niveau de nginx :
Code : sh
# rm -f /etc/nginx/sites-enabled/mon-domaine.net
# nginx -t && rcctl restart nginx
Partons du principe que l’utilisateur web est www
.
Les actions qui suivent sont à faire avec ces droits : $ su -l www
cd www/nextcloud
sed -i -e 's#/htdocs#/var/www/htdocs#' config/config.php
php-7.3 occ maintenance:mode --on
Astuce d’informaticien :
www\
:v
qui sera bien utile.Code : sh
$ cd ../
$ v="17.0.1"
$ for ext in bz2 bz2.sha256; do curl -O https://download.nextcloud.com/server/releases/nextcloud-$v.tar.$ext; done
$ sha256 -c nextcloud-$v.tar.bz2.sha256
Si par exemple, le résultat du SHA est (SHA256) nextcloud-$v.tar.bz2: OK
, c’est tout bon.
Passons à la phse d’installation :
nextcloud
en le renommant suivi de la date de transformation et du numéro de l’ancienne versionCode : sh
$ oldvers="16.0.6"
$ date="$(date '+%Y%m%d%H%M%S')"
$ oldnc="nextcloud-${date}-${oldvers}"
$ mv nextcloud ${oldnc}
$ tar xjvf nextcloud-$v.tar.bz2
$ rm -fP config/CAN_INSTALL
Là, il faut être un peu plus attentif :
cp ${oldnc}/config/config.php nextcloud/config/
cp all ${oldnc}/apps diff to new nextcloud-app
nextcloud/
.Code : sh
$ webuser="www"
$ chown -R "${webuser}":www nextcloud
$ find nextcloud/ -type d -exec chmod 750 {} \;
$ find nextcloud/ -type f -exec chmod 640 {} \;
cd nextcloud/
occ
: php-7.3 occ upgrade
php-7.3 occ maintenance:mode --off
Pour finir, ré-édition du fichier de configuration pour supprimer /var/www
: sed -i -e 's#/var/www/htdocs#/htdocs#' config/config.php
Code : sh
# cd /etc/nginx/sites-available/
# ln -s mon-domaine.net ../sites-enabled/
# nginx -t && rcctl restart nginx
Et, voilà !
Attention si vous ne faites que recopier tel quel ce TL;DR, vous allez au casse-pipe !
Code : sh
// stop web services
# rm -f /etc/nginx/sites-enabled/mon-domaine.net
# nginx -t && rcctl restart nginx
// connexion as user web
# webuser="www"
# su -l $webuser
$ cd /var/www/htdocs/mon-domaine.net/www/nextcloud/
$ sed -i -e 's#/htdocs#/var/www/htdocs#' config/config.php
$ php-7.3 occ maintenance:mode --on
// downlad archives, and checksum
$ cd ../
$ v="17.0.1"
$ for ext in bz2 bz2.sha256; do curl -O https://download.nextcloud.com/server/releases/nextcloud-$v.tar.$ext; done
$ sha256 -c nextcloud-$v.tar.bz2.sha256
// Untar
$ oldvers="16.0.6"
$ date="$(date '+%Y%m%d%H%M%S')"
$ oldnc="nextcloud-${date}-${oldvers}"
$ mv nextcloud ${oldnc}
$ tar xjvf nextcloud-$v.tar.bz2
$ rm -fP config/CAN_INSTALL
// cp config
$ cp ${oldnc}/config/config.php nextcloud/config/
// cp only apps not native; dont recopy this command as-is:
$ cp all ${oldnc}/apps diff to new nextcloud/apps
// egual for themes, if need
$ cp all ${oldnc}/themes to new nextcloud/themes
$ chown -R "${webuser}":www nextcloud
$ find nextcloud/ -type d -exec chmod 750 {} \;
$ find nextcloud/ -type f -exec chmod 640 {} \;
// occ upgrage process
$ cd nextcloud/
$ php-7.3 occ upgrade
$ php-7.3 occ maintenance:mode --off
$ sed -i -e 's#/var/www/htdocs#/htdocs#' config/config.php
// exit
// restart web services
# cd /etc/nginx/sites-available/
# ln -s mon-domaine.net ../sites-enabled/
# nginx -t && rcctl restart nginx
Si la mise à jour échoue, avec l’un de ces messages d’erreurs :
Tel que :
Code : sh
$ php-7.3 occ help upgrade
Nextcloud is not installed - only a limited number of commands are available
Command "upgrade" is not defined.
help [--format FORMAT] [--raw] [--] [<command_name>]
Première chose à s’assurer est de vérifier que vous avez bien recopié l’ancien fichier de configuration vers le nouveau répertoire de configuration.
Si oui, et que le problème perdure, essayez : php-7.3 occ maintenance:repair
Lorsque vous vous connectez à l’interface web, vous avez le message suivant :
Citation :
Erreur
On dirait que vous essayez de réinstaller votre Nextcloud. Toutefois, le fichier CAN_INSTALL est absent de votre répertoire de configuration. Veuillez créer le fichier CAN_INSTALL dans votre dossier de configuration pour continuer
Allez supprimer le fichier CAN_INSTALL
qui se trouve dans le nouveau répertoire de configuration
Essayez : php-7.3 console.php files:scan --all
Pour rappel, les différentes commandes occ, bien utiles : php occ list
Retrouvez une liste d’informations bien pratique sur la page occ .
Munin est un outil de surveillance des ordinateurs. Il présente ces informations par le biais d’une interface web, qui visualise des graphiques statiques, générés toutes les 5 minutes, par défaut. Un certain nombre de plugins de monitoring divers sont utilisables sans gros effort.
Munin permet de monitorer facilement la performance de tout matériel informatique (ordinateurs, réseaux, applications, mesures diverses, etc.). Il permet de discerner les problèmes de performance des ressources.
Il est toujours utile de lire les documentations pkg-readmes
fournies ; celles disponibles sont dans /usr/local/share/doc/pkg-readmes/
, à-propos de :
Code : sh
# pkg_add munin-node
Pour information, cela installe en dépendance quelques paquets de plus, dont p5-Net-CIDR
- ce paquet est utile pour la configuration de l’option cidr_allow
dans le fichier de configuration du nœud de munin
; s’il n’est pas installé, faites-le !
Si vous désirez le support des moniteurs SNMP
, il faut installer le paquet p5-Net-SNMP
.
Le fichier de configuration est /etc/munin/munin-node.conf
.
Une fois configuré, il est nécessaire de démarrer le service de munin :
Code : sh
# rcctl enable munin_node
# rcctl start munin_node
Ce fichier de configuration du nœud, le client si vous préférez, est simple à paramétrer.
Vous pouvez changer principalement :
global_timeout
: le délai timeout pour toute transaction. Par défaut, c’est une période de 15 minutes ; à écrire en nombre de secondes.timeout
: c’est le timeout de connexion pour les plugins. Par défaut, de 60 secondes.host_name
: le nom de votre hôteallow
: permettre la connexionhost
: nom d’hôte ou adresse ip à surveiller - préférez à changer par 127.0.0.1
et/ou ::1
.port
: le numéro du port d’écoute, par défaut : 4949
D’autres variables sont configurables ; à vous d’éditer le fichier et de vous renseigner pour savoir quoi paramétrer !
Pour finir, il est recommandé d’exécuter le script de configuration du nœud munin, à savoir :
Code : sh
# munin-node-configure --shell --suggest | sh
Il est nécessaire de modifier le fichier de configuration du journal /etc/newsyslog.conf
pour créer une rotation des journaux générés par munin.
Ajoutez-y :
Code :
# munin-node
/var/log/munin/munin-node.log root:wheel 644 7 250 * Z
munin-node-configure --shell
munin-run nom-plugin config
munin-run nom-plugin
Pour information, le répertoire est /usr/local/libexec/munin/plugins/
; pour les activer, il suffit de faire un lien symbolique d’un plugin en particulier vers /etc/munin/plugins
, puis de redémarrer les services de munin.
Certains plugins nécessitent une configuration supplémentaire, inscrite dans les commentaires d’entêtes du script. Il est alors nécessaire de modifier le fichier /etc/munin/plugin-conf.d/openbsd-packages
en ajoutant les informations nécessaires.
C’est le cas des plugins suivants :
requisites
: n'activer cette option que sur du flux HTTP, et non HTTPS !
network
: HTTP loadtime of a page
Permet de surveiller l’accès à un site web, soit la page d’acceuil, soit une page dédiée.
Exemple :
Code :
[http_loadtime]
env.target http://huc.fr.eu.org,http://huc.fr.eu.org/fr/sys/openbsd/munin-monitoring-openbsd/
#env.requisites true
system
: Interrupt activity
Relatif aux différentes interruptions d’activités - spécifique à OpenBSD.
nginx
Non seulement, il faut modifier le fichier openbsd-packages
, tel que :
Code :
[nginx*]
env.url http://localhost/nginx_status
Mais en plus, il faut rajouter une configuration serveur au serveur web nginx. Il n'est donc pas possible de le monitorer avec httpd.
user
: root
do_searches
: false
ou true
pour permettre les interrogations adéquates. Certains plugins pf_ peuvent nécessiter l’ajout de la variable d’environnementpf
Code :
[pf_*]
user root
#env.do_searches yes
user
: root
smbstatus
: restituer le chemin vers le binaire ad hocignoreipcshare
: false
ou true
pour ignorer ou non les partages IPC$samba
Code :
[samba]
user root
env.smbstatus /usr/local/bin/smbstatus
env.ignoreipcshare 1
snmp
Recommandations :
perldoc Munin::Plugin::SNMP
community
ne devrait pas être paramétrée sur public
.Exemple :
Code :
[snmp_*]
env.warning 10
env.critical 5 # need for _print_*
env.version 2
env.community private
Une fois que cela est fait, il faut modifier le fichier de configuration du serveur pour lui ajouter votre nœud munin …
Concernant les règles pour PF , il faut ouvrir en entrée et sortie , vers et depuis le serveur munin :
4949/tcp
161
, 162
en udp
et tcp
- cela dépend de votre configuration SNMP
, bien sûr.snmp est le client SNMP par défaut sous OpenBSD, intégré dans le système de base depuis 6.6 !
Il est bien sûr nécessaire qu’un agent soit installé, configuré sur la machine à interroger. Sous OpenBSD, c’est le service natif snmpd .
La documentation se fait au-travers du manpage, tels que :
Premier aspect qui “saute aux yeux” est que snmp est fourni avec un ensemble de sous-commandes, qui ont leurs propres options.
Pour information : les OID sont des identifiants d’objets.
snmp get
pour récupèrer le varbind OID depuis un agent SNMP. Il est
possible de spécifier plusieurs OID.snmp getnext
pour récupèrer le varbind qui suit l’OID requis. Il est
aussi possible d’en spécifier plusieurs.snmp walk
récupère toutes les branches d’un OID.snmp bulkget
récupère les 10 prochains varbind suivant chaque OID.snmp bulkwalk
récupère tous les varbind qui sont des branches de l’OID.snmp set
permet de définir un ou plusieurs varoid, ainsi que son
format de type de données.snmp trap
envoie un message de capture à un agent.snmp mibtree
permet de faire un dump (une sauvegarde) de l’arborescence
des objets compilés au format MIB.Les deux sous commandes bulk*
, ainsi que trap
ne sont fonctionnelles
qu’à partir de SNMP v2.
Pour info, la sous commande get
est aussi utile pour récupèrer les
messages d’erreurs.
Oui, c’est possible ; mais du fait que c’est une version “historique”, qu’il n’est plus recommandé de l’utiliser, passons à la suite…
Il n’y a pas de réelle sécurité avec SNMPv2. Elle se base principalement
sur l’option community
et les deux options read-*
.
Exemple :
$ snmp walk -v 2c -c public $(hostname) sysDescr
Cet exemple nous montre l’interrogation d’un agent sur le protocole v2c
faisant partie de la communauté public
.
Un petit mot sur l’option community
, ne cherchez pas à la faire fonctionner
avec SNMPv3, elle a été supprimée du protocole.
Les options principales sont :
-A
spécifie le mot de passe utilisateur de l’agent à interroger.-a
spécifie le protocole de chiffrement lié à l’option -A
.
-a
est paramétrée sur MD5
.
Attention, l’option équivalente pour le service snmpd hmac
est,
elle, basée sur hmac-sha1
. Donc, dans le cas d’un agent SNMPd
fonctionant sous OpenBSD configuré par défaut à interroger, il faudra
veiller à spécifier SHA1
.-l
spécifie le niveau de sécurité. Par défaut, la valeur est noAuthNoPriv
.
authNoPriv
est requise par l’une des deux options -A
ou -k
.authPriv
est requise par l’une des deux options -K
ou -X
.-u
spécifie le nom de l’utilisateur-v
spécifie la version du protocole SNMP utilisé-X
spécifie le mot de passe de confidentialité de l’utilisateur-x
spécifie le protocole de chiffrement de confidentialité. Les options
sont des
ou aes
.Ces options sont utiles voire nécessaires pour faire de l’authentification dite forte .
Il y a bien sûr d’autres options possibles :
-E
, -e
, -n
, -Z
.-K
, -k
(ces deux dernières options sont l’équivalent
des options -A
et -X
mais encodées sous forme hexadécimale).bulk*
, walk
.udp
, tcp
, (et leur équivalent IPv6 : upd6
et tcp6
) ou unix
.
Les adresses IPv6 doivent être mises entre crochets { }
.Lire le manpage snmp pour en savoir plus sur l’utilité des ces options.
Ci-dessous, retrouvez quelques exemples d’utilisation avec le protocole SNMPv3. Il est bien entendu que nous n’abordons pas la partie de la configuration de l’agent interrogé. Sous OpenBSD , la configuration d’un agent SNMP se fait par le biais du service SNMPd .
Dans chaque cas, les paramètres utilisés sont liés à ceux configurés dans le service SNMPd.
Exemple :
$ snmp walk -u "test" -v 3 $(hostname) sysDescr
Dans cet exemple, nous interrogeons l’agent avec un nom d’utilisateur
nommé test
, sans aucun niveau de sécurité.
Exemple :
$ snmp walk -A "secret007" -a SHA -l authNoPriv -u "uauth" -v 3 192.168.1.3 sysdescr
Ici, nous interrogeons l’agent ayant pour adresse 192.168.1.3
avec un
nom utilisateur uauth
, une clé d’authentification secret007
et un
niveau de sécurité spécifié à authNoPriv
.
Quelques mots sur l’authentification forte : elle est à favoriser IMPÉRATIVEMENT !
Exemple :
$ snmp walk -A "zx4pyrfyeu5x5c3kxqirhtsxksbmawju" -a SHA-512 -l authPriv -u "uenc" -v 3 -X "XHVBzYUpP8dKns75BaSwq6t7SUgF6oMz" -x aes $(hostname) sysdescr
Dans cet exemple, nous interrogeons localement l’agent,
uenc
,zx4pyrfyeu5x5c3kxqirhtsxksbmawju
” basée
sur le protocole de chiffrement SHA-512
,authPriv
,XHVBzYUpP8dKns75BaSwq6t7SUgF6oMz
”
basé sur le protocole de chiffrement aes
.usmStatsDecryptionErrors.0
Le protocole de chiffrement que vous utilisez n’est pas celui attendu
par l’agent interrogé. Corrigez la valeur de votre option -x
.
usmStatsUnsupportedSecLevels.0
Le niveau de sécurité que vous cherchez à utiliser n’est pas celui attendu
par l’agent interrogé. Corrigez la valeur de votre option -l
.
usmStatsWrongDigests.0
Le protocole de chiffrement que vous utilisez n’est pas celui attendu
par l’agent interrogé. Corrigez la valeur de votre option -a
.
*** = No Such Object available on this agent at this OID
Vous essayez de parcourir un arbre avec la sous commande get
,
n’est-ce pas !?
Alors, soit vous recommencez en :
walk
Received report:
Vous venez de parcourir un arbre avec la sous commande walk
, et vous
avez pour retour juste ce message Received report:
sans rien de plus.
Utilisez la sous commande get
à la place, cela vous permettra d’obtenir
le message d’erreur adéquat.
snmp: Invalid privacy protocol specified after -3x flag:
Le niveau du protocole de sécurité que vous avez spécifié est incorrect.
Corrigez la valeur de votre option -l
.
snmp: ***: Unknown object identifier
Vous avez spécifié un OID inconnu. Vérifiez et corrigez l’OID recherché.
OpenBSD intègre par défaut dans le système de base snmpd qui est le démon du service SNMP.
La documentation se fait au-travers des différents manpages, tels que :
La configuration du serveur snmpd se fait, à minima, au-travers d’un seul fichier de configuration, à créer : /etc/snmpd.conf
.
Il existe trois versions du protocol ; la v1 est l’historique à ne plus utiliser ; la v2 apporte des prémices de sécurité ; la v3 est la plus sécurisante, néanmoins, il faut utiliser les niveaux de sécurité et de chiffrement les plus forts. (Pour info, dans certaines conditions, la v3 est aussi faillible et sujette à vulnérabilités).
Après avoir écrit le fichier de configuration, il faut donner les droits d’exécution adéquates et utilisateur au fichier de configuration :
Code : sh
# chown root:_snmpd /etc/snmpd.conf
# chmod 0600 /etc/snmpd.conf
Plusieurs options peuvent être paramétrées :
filter-routes
(yes|no): permet au noyau de filter les messages de mise à jour des routes dans le socket.listen on
address [tcp|udp]: spécifie l’adresse locale qui doit écouter les messages SNMP entrants. Il est possible de la spécifier plusieurs fois. Les deux protocoles TCP et UDP sont gérés.read-only
: spécifie la communauté autorisée en lecture seule. Par défaut, la valeur est public
read-write
(community string | disabled) : Soit spécifie la communauté autorisée en lecture et écriture, soit désactive l’écrite définitivement. Par défaut, la valeur est private
seclevel
: spécifie le niveau le plus bas de sécurité que snmpd(8) accepte. Par défault, la valeur est none
. Si l’une des deux autres options auth
ou enc
est choisie, snmpd(8) n’acceptera que les requêtes SNMPv3. enc
oblige à ce que les messages soient chiffrés et une authentification valide, autrement ils seront supprimés.socket
, les différentes options system
et celles relatives à trap
. Je renvoie au manpage ;)Les deux options read_*
ne servent QUE pour une configuration SNMP v2.
Des macros peuvent être définies. Considérez-les comme des variables. On ne peut utiliser des mots clés réservés. Elles commencent forcément par une lettre, un chiffre ou le symbole ‘_
’ suivi de tout autre caractère.
Avec SNMPv3, Il est possible de définir plusieurs utilisateurs par le biais de l’option user
, tel que :
user
name authkey key auth hmac enckey key enc cipher
authkey
est requis pour authentifier les messages en spécifiant une clé. Si la clé est omise, pas d’authentification.auth
hmac permet de cibler l’algorithme HMAC à utiliser. Par défaut, la valeur est hmac-sha1
. La valeur la plus forte est hmac-sha512
.enckey
key est la clé de chiffrement utilisé pour chiffrer et déchiffrer les messages dans un soucis de confidentialité. Sans, le compte utilisateur n’acceptera jamais l’entrée des messages ou ne chiffrera pas les messages sortants.enc
cipher est l’algorithme utilisé. Par défaut, sa valeur est des
. Sa valeur la plus forte est aes
.Il faut bien comprendre que le nom de l’utilisateur, les caractères donnant la valeur des clés key
sont des choix purement arbitraires. À vous de les spécifier…
Les OID sont les identifiants des objets. Je renvoie au manpage, si besoin de les gérer.
snmpd
-n
Ainsi la commande snmpd -n
permettra de s’assurer de la validité de l’ensemble de la configuration, à tout moment.
À chaque modification du fichier de configuration , il faudra relancer le service ad hoc.
Pour débuter, commençons par :
Code :
listen on 192.168.1.3 udp
read-only community macompub
read-write community macompriv
À minima, nous n’avons besoin de rien de plus. C’est très basique et permet de tester/s’assurer du bon fonctionnement, de la bonne compréhension.
Testons la réponse :
Code : sh
$ snmp walk -v 2c -c macompub $(hostname) sysDescr
sysDescr.0 = STRING: OpenBSD omv.huc.fr.eu.org 6.6 GENERIC.MP#2 amd64
$ snmp walk -v 2c -c macompub $(hostname) ifName
ifName.1 = STRING: em0
ifName.2 = STRING: enc0
ifName.3 = STRING: lo0
ifName.4 = STRING: pflog0
Ce sont des exemples d’interrogation et réponses.
Commençons avec un exemple sans sécurité :
Code :
seclevel none
user "test"
Après le rédémarrage du service :
Code : sh
$ snmp walk -u "test" -v 3 $(hostname) sysDescr
sysDescr.0 = STRING: OpenBSD omv.huc.fr.eu.org 6.6 GENERIC.MP#2 amd64
$ snmp walk -u "test" -v 3 $(hostname) ifName
ifName.1 = STRING: em0
ifName.2 = STRING: enc0
ifName.3 = STRING: lo0
ifName.4 = STRING: pflog0
Code :
seclevel auth
user "uauth" authkey "secret007"
Après le rédémarrage du service :
Code : sh
$ snmp walk -A "secret007" -a SHA -l authNoPriv -u "uauth" -v 3 192.168.47.3 sysdescr
sysDescr.0 = STRING: OpenBSD omv.huc.fr.eu.org 6.6 GENERIC.MP#2 amd64
Configurons le serveur par un exemple fort :
Code :
listen on 192.168.1.3 tcp
seclevel enc
user "uenc" authkey "zx4pyrfyeu5x5c3kxqirhtsxksbmawju" auth hmac-sha512 enckey "XHVBzYUpP8dKns75BaSwq6t7SUgF6oMz" enc aes
Après le redémarrage du service :
Code : sh
$ snmp walk -A "zx4pyrfyeu5x5c3kxqirhtsxksbmawju" -a SHA-512 -l authPriv -u "uenc" -v 3 -X "XHVBzYUpP8dKns75BaSwq6t7SUgF6oMz" -x aes $(hostname) sysdescr
sysDescr.0 = STRING: OpenBSD omv.huc.fr.eu.org 6.6 GENERIC.MP#2 amd64
$ snmp walk -A "zx4pyrfyeu5x5c3kxqirhtsxksbmawju" -a SHA-512 -l authPriv -u "uenc" -v 3 -X "XHVBzYUpP8dKns75BaSwq6t7SUgF6oMz" -x aes $(hostname) ifname
ifName.1 = STRING: em0
ifName.2 = STRING: enc0
ifName.3 = STRING: lo0
ifName.4 = STRING: pflog0
rcctl enable snmpd
rcctl start snmpd
Après avoir activé et démarré le service, il est possible de vérifier le fonctionnement du service, tel que :
Code : sh
$ ps aux | grep snmpd
_snmpd 41593 0.0 0.1 772 3124 ?? SU 10:32PM 0:00.07 snmpd: snmpe (snmpd)
root 55283 0.0 0.0 820 1492 ?? Ip 10:32PM 0:00.01 /usr/sbin/snmpd
_snmpd 42220 0.0 0.1 752 2756 ?? Ip 10:32PM 0:00.02 snmpd: traphandler (snmpd)
root 80301 0.0 0.0 332 1256 p0 S+p 10:33PM 0:00.01 grep snmpd
$ netstat -ant | grep snmp
0xfffffd8105572100 stream 0 0 0xfffffd810e7e70e8 0x0 0x0 0x0 /var/run/snmpd.sock
Voilà, pour la partie serveur !
Et les clients ?
Depuis OpenBSD 6.6, le client natif est snmp
Pour information, il y a sur chaque système OpenBSD, dans le répertoire /usr/share/snmp/mibs/
l’ensemble de fichiers MIB qui renferment toutes informations utiles :
Code : sh
$ ls -al /usr/share/snmp/mibs/
total 184
drwxr-xr-x 2 root wheel 512 Oct 12 18:34 ./
drwxr-xr-x 3 root wheel 512 Oct 12 18:34 ../
-r--r--r-- 1 root wheel 2331 Oct 12 18:34 OPENBSD-BASE-MIB.txt
-r--r--r-- 1 root wheel 8805 Oct 12 18:34 OPENBSD-CARP-MIB.txt
-r--r--r-- 1 root wheel 3283 Oct 12 18:34 OPENBSD-MEM-MIB.txt
-r--r--r-- 1 root wheel 39486 Oct 12 18:34 OPENBSD-PF-MIB.txt
-r--r--r-- 1 root wheel 18559 Oct 12 18:34 OPENBSD-RELAYD-MIB.txt
-r--r--r-- 1 root wheel 4635 Oct 12 18:34 OPENBSD-SENSORS-MIB.txt
-r--r--r-- 1 root wheel 2547 Oct 12 18:34 OPENBSD-SNMPD-CONF.txt
Il peut être utile de les “donner à manger” aux différents clients des autres systèmes de surveillance/métrologie/monitoring, tel Nagios , Munin , etc…
OpenBSD intègre par défaut dans le système de base un serveur web, nommé httpd, depuis 5.7. C’est un serveur qui se veut sécurisé, tant par le fonctionnement chrooté que par la séparation des privilèges, l’usage de chiffrements forts, de courbes elliptiques, et autres paramétres forts pour TLS , par défaut.
httpd est un serveur HTTP de fichiers statiques, qui supporte les appels directs ou asynchrones FastCGI (soit par socket Unix - c’est mieux -, soit par TCP /IP ). Il est bien sûr possible de gérer les connexions TLS, via la bibliothèque LibreSSL, et fonctionne sur la double couche de protocole IPv4 et IPv6.
Une configuration flexible d’hôtes virtuels est possible, soit par nom d’hôte, soit par adresse IP.
Enfin, la journalisation se fait soit via syslog
, soit par des journaux
d’accès et d’erreurs dédiés aux différents hôtes virtuels.
Ce que ne gère pas httpd :
les entêtes HTTP.
l’URL Rewriting ?
Quoi d’autres ?!
Site web : https://bsd.plumbing/
La configuration du serveur httpd se fait, à minima, au-travers d’un seul
fichier de configuration, à créer : /etc/httpd.conf
.
Exemple :
Code : httpd
prefork 3
types { include "/usr/share/misc/mime.types" }
server "adr_ip" {
...
}
La configuration d’hôte virtuel, étant à envisager, il est préférable de
créer un fichier par hôte et de l’inclure dans le fichier de configuration
par le biais du mot clé include
.
Voici les paramètres de niveau global :
chroot
: spécifie le répertoire
chroot(2)
. S’il n’est pas
spécifié, il a pour valeur /var/www/
qui est le répertoire home de
l’utilisateur web www
.default type
: spécifie les types de média utilisés pour une extension
donnée ou un type de fichier. S’il n’est pas spécifié, le type par défaut
est application/octect-stream
.logdir
: spécifie le répertoire où les journaux seront écrits. Par défaut,
il fait référence au répertoire enfant logs/
à l’intérieur du chroot.prefork
: le nombre de processus du serveur. Par défaut, httpd utilise
3 processus serveur. Augmenter cette valeur améliore la performance
et prévient les délais de connexion au serveur.Des macros peuvent être définies. Considérez-les comme des variables. On
ne peut utiliser des mots clés réservés. Elles commencent forcément par
une lettre, un chiffre ou le symbole ‘_
’ suivi de tout autre caractère.
Exemple :
Code : httpd
ip_ext="10.0.0.1"
server "default" {
listen on $ip_ext port 80
...
}
Dans cet exemple, la macro est la variable ip_ext
; sa valeur étant 10.0.0.1
.
La gestion des hôtes virtuels se fait dans chaque section server
, en
déclarant le nom du serveur entre double-quotes.
Pour plus d’informations, lire la section SERVERS
du manpage httpd.conf(5)
.
La section types
configure les types de média supportés. Si rien n’est
spécifié, par défaut, httpd gére les types de média pour :
text/css
, text/html
, text/plain
image/gif
, image/jpeg
, image/png
, image/svg+xml
application/javascript
.Exemple :
types { include "usr/share/misc/mime.types" }
ou
Code : httpd
types {
text/css css
text/html html htm
text/plain txt
image/gif gif
image/jpeg jpeg jpg
image/png png
application/javascript js
application/xml xml
}
Avant de chercher à ajouter un nouveau type, assurez-vous qu’il ne soit
pas déjà inclus dans le fichier /usr/share/misc/mimes.types
; si ce n’est
pas le cas, ajoutez-le en suivant.
httpd
-n
Ainsi la commande httpd -n
permettra de s’assurer de la validité de
l’ensemble de la configuration, à tout moment.
Par convention/préférence, il est intéressant de créer un répertoire /etc/httpd.d/
dans lequel sera écrit les configurations serveurs des hôtes virtuels, tel que :
# mkdir -p /etc/httpd.d
Modification du fichier de configuration /etc/httpd.conf
:
types { include "usr/share/misc/mime.types" }
Puis utilisez le mot clé include
pour ajouter la configuration d’un hôte
virtuel au fur et à mesure des besoins, tel que
include "etc/httpd.d/nom-de-domaine.conf"
La gestion des logs est intéressante.
no log
dans votre section server
.log syslog
log access "nom-fichier-acces.log"
log error "nom-fichier-erreurs.log"
Néanmoins, sachez qu’il est possible d’intégrer les différentes options
entre crochets, tel que : Code : httpd
log {
access "nom-fichier-acces.log"
error "nom-fichier-erreurs.log
}
Et, pour finir, vous pouvez y intégrer l’option style
qui va vous permettre
de définir le style de journalisation désiré, tel que :
common
ou combined
: ces deux styles imitent le format de journalisation
des standards des serveurs web Apache ou nginx. common
est le type
par défaut, si aucun n’est spécifié.forwarded
étend le style combined
en ajoutant deux champs d’information
contenant la valeur des entêtes X-Forwarded-For
et X-Forwarded-Port
(respectivement, la première doit retourner l’adresse ip du client,
la seconde celle du port de connexion sur le serveur). Intéressant
quand httpd est derrière un proxy web, tel nginx ou relayd.connection
imite le format de journalisation du serveur
relayd(8)
.
Chaque entrée du journal est un résumé de chaque connexion qui peut
contenir de multiples requêtes.httpd peut faire de l’authentification web.
Dans un premier temps, il faut utiliser l’outil htpasswd(5) , (accessible nativement depuis OpenBSD 5.6), tel que :
Code : httpd
# cd /var/www/
# htpasswd nom-fichier identifiant
Password:
Retype Password:
Par mesure de sécurité, ensuite, attribuez-lui des droits
en exécution 0400
, accessible rien que par l’utilisateur web www
.
Puis ensuite dans une des directives location
ou server
, ajoutez ce
qui ressemble à :
authenticate "! Acces sous Restriction !" with "/nom-fichier"
Pour autant que vous avez installer PHP sur le serveur, httpd peut servir du contenu php, par le biais de la directive location
, tel que :
Exemple :
Code : httpd
location "*.php" {
fastcgi socket "/run/php-fpm.sock"
}
Il est nécessaire que le socket FastCGI corresponde bien à celui de PHP-FPM.
slowcgi(8) est un serveur FastCGI de connexion CGI , lui aussi intégré dans le système de base d’OpenBSD, depuis la version 5.4.
httpd peut servir du contenu CGI, disponible depuis le répertoire enfant cgi-bin/
du chroot web, par le biais de la directive location
, tel que :
Exemple :
Code : httpd
location "/cgi-bin/*.cgi" {
fastcgi socket "/run/slowcgi.sock"
root "/"
}
Là aussi, il est nécessaire que le nom du socket FastCGI corresponde bien.
ATTENTION : Il semble important de mettre en place une authentification web pour protéger le contenu délivré par les scripts CGI !
httpd prend très bien en charge la configuration TLS.
Exemple :
Code : httpd
listen on adresse_ip tls port 443
hsts preload
tls {
certificate "/etc/ssl/chezmoi.tld-fullchain.pem"
key "/etc/ssl/private/chezmoi.tld.key"
ticket lifetime 3600
}
hsts
active la gestion HTTP Strict Transport Security. Les options suivantes sont possibles :
max-age
en nombre de secondes - paramètre le temps maximum durant lequel cet hôte peut être considéré comme hôte HSTS.preload
confirme et authentifie que le site est autorisé à être inclu dans la liste de préchargement des navigateurs web.subdomains
signale que les sous-domaines doivent être considérés comme hôtes HSTS. Il semble important par mesure de sécurité d'utiliser cette option lors de fonctionnement avec des sous-domaines, même si ces derniers ont leurs propres certificats TLS
.tls
permet de spécifier la configuration TLS du serveur. Les différentes options sont comprises dans les crochets. Les options suivantes sont possibles :
certificate
- nécessaire - pour spécifier le certificat serveur, encodé au format PEM.key
- nécessaire - pour spécifier le fichier de clé privée, encodée lui aussi au format PEM. ATTENTION : ce fichier doit absolument résider en-dehors du chroot web
.ciphers
,dhe
,ecdhe
- par défaut, sont actives : X25519
, P-256
et P-384
-,ocsp
- il faudra générer un fichier OCSP au format DER avec l’outil
oscpcheck(8)
-,protocols
TLS - sachant que seul TLSv1.2 est actif par défaut -ticket lifetime
en nombre de secondes - qui par défaut est de 2 heures.Il ne sert à rien de spécifier une valeur d’option par défaut, puisque par défaut, sans écriture, c’est la valeur qui lui est appliquée !
httpd peut faire de l’auto-indexation de répertoire et ainsi afficher le contenu d’un répertoire en particulier. Ajoutez tout simplement, soit dans une directive server
, soit location
:
directory auto index
La documentation se fait au-travers des différents manpages, tels que :
Munin est un outil de surveillance des ordinateurs. Il présente ces informations par le biais d’une interface web, qui visualise des graphiques statiques, générés toutes les 5 minutes, par défaut. Un certain nombre de plugins de monitoring divers sont utilisables sans gros effort.
Munin permet de monitorer facilement la performance de tout matériel informatique (ordinateurs, réseaux, applications, mesures diverses, etc.). Il permet de discerner les problèmes de performance des ressources.
Il est toujours utile de lire les documentations pkg-readmes
fournies ; celles disponibles sont dans /usr/local/share/doc/pkg-readmes/
, à-propos de :
Code : sh
# pkg_add munin-node munin-server
Un utilisateur _munin
a été créé et le répertoire web, par défaut, est dans /var/www/htdocs/munin/
. Ce répertoire reçoit les droits de l’utilisateur _munin
et du groupe web www
.
Pour information, cela installe en dépendance quelques paquets de plus, dont p5-Net-CIDR
- ce paquet est utile pour la configuration de l’option cidr_allow
dans le fichier de configuration du nœud de munin
; s’il n’est pas installé, faites-le !
Si vous désirez le support des moniteurs SNMP
, il faut installer le paquet p5-Net-SNMP
.
Deux fichiers de configuration principaux sont dans /etc/munin
:
munin.conf
relatif au serveur lui-mêmemunin-node.conf
relatif au nœud de surveillance local.Une fois, ces fichiers configurés, il est possible de démarrer les deux services de munin.
Généralement, il y a peu de choses à changer, néanmoins, pour informations, certaines variables peuvent être configurées.
dbdir
: répertoire de la base de donnée de muninhtmldir
: répertoire de destination des données graphiques générées.logdir
: répertoire des journaux de muninrundir
: répertoire où s’exécute le processus munin.Si vous préférez une exécution du processus par cron plus que par script CGI, vous pouvez modifier les deux variables graph_strategy
et html_strategy
.
Par défaut sera configurée une arborescence basique basée sur localhost, tel que :
Code :
[localhost]
address 127.0.0.1
user_node_name yes
Si vous préférez une arborescence par nom de domaine, modifiez/commentez/ajoutez localhost
par le nom de domaine désiré, tel huc.fr.eu.org
. Bien sûr, il est possible de surveiller autant d’hôtes que désiré.
Il est possible de gérer les différents nœuds par groupe ; cela permet de regrouper les informations. Je vous renvoie aux documentations officielles et autres manpages.
Les noms de nœuds, de groupe de nœuds ainsi que les adresses IPv6 doivent être encadrés de [ ]
.
Exemple :
Code :
# server name
[srvr.huc.fr.eu.org]
# address IP
address 192.168.1.1
use_node_name yes
# first pc
[pc1.huc.fr.eu.org]
address 192.168.1.10
use_node_name yes
Pour recevoir les alertes par mail, il est nécessaire de renseigner une ou plusieurs adresses de contact, tel que :
Code :
contact.root.command mail -s "Munin notification" email
contact.other-user.command mail -s "Munin notification" email-user
Ceci étant un exemple, remplacez par les informations nécessaires à votre situation.
La partie de la configuration du fichier de nœud étant expliquée sur sa propre page, il suffit de suivre les informations et de les adapter au nœud du serveur lui-même
Après avoir configuré les deux fichiers de configuration ci-dessus, il est important de paramétrer une tâche cron, tel que :
Code :
# crontab for munin-server
*/5 * * * * su -s /bin/sh _munin /usr/local/bin/munin-cron
Il est nécessaire de modifier le fichier de configuration du journal /etc/newsyslog.conf
pour créer une rotation des journaux générés par munin.
Ajoutez-y :
Code :
# munin-server
/var/www/logs/munin/munin-cgi-graph.log www:_munin 644 7 250 * Z
/var/www/logs/munin/munin-cgi-html.log www:_munin 644 7 250 * Z
/var/www/logs/munin/munin-graph.log _munin:_munin 644 7 250 * Z
/var/www/logs/munin/munin-html.log _munin:_munin 644 7 250 * Z
/var/www/logs/munin/munin-limits.log _munin:_munin 644 7 250 * Z
/var/www/logs/munin/munin-update.log _munin:_munin 644 7 250 * Z
# munin-node
/var/log/munin/munin-node.log root:wheel 644 7 250 * Z
Ce sont tous les journaux gérés et nécessaires à minima pour munin.
Ici, je vous renvoie à mon article de découverte du serveur httpd, et tout particulièrement aux informations d’utilisations .
Modification du fichier de configuration /etc/httpd.conf
pour y ajouter :
Code :
include "/etc/httpd.d/munin.conf"
Création du fichier de config du serveur pour nagios /etc/httpd.d/munin.conf
:
Code :
server "192.168.1.3" {
listen on * port 80
root "/htdocs/munin"
# location "/cgi-bin/munin-cgi*" {
# fastcgi socket "/run/slowcgi.sock"
# root "/"
# }
location "/" {
directory index index.html
}
}
Les fichiers dans le répertoire web de munin doivent avoir les droits de l’utilisateur _munin
et du groupe web www
, par défaut.
Du fait du chroot web, il est nécessaire de faire les modifications systèmes suivantes :
Code : sh
# mkdir -p /var/www/{logs,var/run}/munin
# chown _munin: /var/www/{logs,var/run}/munin
mais en plus de modifier la configuration du fichier du serveur :
Code :
htmldir /var/www/htdocs/munin
logdir /var/www/logs/munin
rundir /var/www/var/run/munin
Concernant les règles pour PF , il faut ouvrir en entrée et sortie, vers et depuis les nœuds :
4949/tcp
161
, 162
en udp
et tcp
- cela dépend de votre configuration SNMP
, bien sûr.Pensez à activer et démarrer les services nécessaires, si ce n’est pas fait !
Code : sh
# rcctl enable munin_node munin_asyncd slowcgi httpd
# rcctl start munin_node munin_asyncd slowcgi
# httpd -n && rcctl start httpd
Citation :
Failed to create rundir (/var/run/munin): Permission denied at /usr/local/libexec/munin/munin-update line 39.
Citation :
[FATAL] There is nothing to do here, since there are no nodes with any plugins. Please refer to http://munin-monitoring.org/wiki/FAQ_no_graphs at /usr/local/libexec/munin/munin-html line 40.
munin-node
?Une spéciale dédicace à Solene Rapenne qui fait partie de l’équipe d’OpenBSD, et qui m’a bien aider pour démarrer ce projet.
Nagios est un moniteur d’hôtes et de services conçu pour vous informer sur vos machines clientes, utilisateurs finaux ou gestionnaires.
Le démon de surveillance exécute des contrôles intermittents sur les hôtes et les services que vous spécifiez à l’aide de “plugins” externes qui retournent les informations d’état à Nagios. En cas de problèmes, le démon peut envoyer à des contacts administratifs dans une variété de pays différents par différents biais (courriel, messagerie instantanée, SMS, etc.) des informations sur l’état actuel ; les rapports peuvent tous être consultés par l’intermédiaire d’un navigateur Web.
Il est toujours utile de lire les documentations pkg-readmes
fournies ; celles disponibles sont dans /usr/local/share/doc/pkg-readmes/
, à-propos de :
Afin de fonctionner avec le serveur web natif à OpenBSD, dixit
httpd(8)
, installez les paquets nagios-*-chroot
spécifiques pour l’usage avec ce serveur web natif :
Code : sh
# pkg_add nagios-4.3.1p1-chroot nagios-web-4.3.1p2-chroot
quirks-3.182 signed on 2019-11-15T10:35:39Z
nagios-4.3.1p1-chroot:libltdl-2.4.2p1: ok
nagios-4.3.1p1-chroot:monitoring-plugins-2.2p8: ok
useradd: Warning: home directory `/var/www/nagios' doesn't exist, and -m was not specified
nagios-4.3.1p1-chroot: ok
nagios-web-4.3.1p2-chroot:femail-1.0p1: ok
nagios-web-4.3.1p2-chroot:femail-chroot-1.0p3: ok
nagios-web-4.3.1p2-chroot:argon2-20171227: ok
nagios-web-4.3.1p2-chroot:php-7.3.11: ok
nagios-web-4.3.1p2-chroot:php-gd-7.3.11: ok
nagios-web-4.3.1p2-chroot: ok
The following new rcscripts were installed: /etc/rc.d/nagios /etc/rc.d/php73_fpm
See rcctl(8) for details.
New and changed readme(s):
/usr/local/share/doc/pkg-readmes/femail-chroot
/usr/local/share/doc/pkg-readmes/nagios
/usr/local/share/doc/pkg-readmes/php-7.3
Le répertoire web par défaut est /var/www/nagios
; des scripts CGI sont installés dans /var/www/cgi-gin/nagios/
.
Code : sh
# cd /var/www/
# mkdir -p etc/ssl
# cp /etc/{resolv.conf,hosts,localtime} etc/
# install -m 444 -o root -g bin /etc/ssl/cert.pem /etc/ssl/openssl.cnf /var/www/etc/ssl
# chmod -R 444 etc/*
# chmod -R a+X etc/
# cp /bin/sh /var/www/bin/
La commande de test de la configuration de nagios est :
Code : sh
$ su -m _nagios -c "/usr/local/sbin/nagios -v /etc/nagios/nagios.cfg"
Exemple :
Code : sh
$ su -m _nagios -c "/usr/local/sbin/nagios -v /etc/nagios/nagios.cfg"
Nagios Core 4.3.1
Copyright (c) 2009-present Nagios Core Development Team and Community Contributors
Copyright (c) 1999-2009 Ethan Galstad
Last Modified: 02-23-2017
License: GPL
Website: https://www.nagios.org
Reading configuration data...
Read main config file okay...
Read object config files okay...
Running pre-flight check on configuration data...
Checking objects...
Checked 8 services.
Checked 1 hosts.
Checked 1 host groups.
Checked 0 service groups.
Checked 1 contacts.
Checked 1 contact groups.
Checked 24 commands.
Checked 5 time periods.
Checked 0 host escalations.
Checked 0 service escalations.
Checking for circular paths...
Checked 1 hosts
Checked 0 service dependencies
Checked 0 host dependencies
Checked 5 timeperiods
Checking global event handlers...
Checking obsessive compulsive processor commands...
Checking misc settings...
Total Warnings: 0
Total Errors: 0
Things look okay - No serious problems were detected during the pre-flight check
Ensuite, penser à activer et démarrer le service nagios
avec le contrôleur
rcctl(8)
.
php73_fpm
php-fpm-73
avec l’option -t
, par exemple.Le fragment de configuration
pour httpd
nécessaire est expliqué dans mon article présentant httpd.
Les commandes suivantes sont à exécuter à chaque installation d’un module PHP, pecl, et opcache :
Code : sh
# cd /etc/php-7.3.sample
# for i in *; do ln -sf ../php-7.3.sample/$i ../php-7.3/; done
Du fait de la prison /var/www
:
Code : sh
# mkdir -p /var/www/etc/ssl
# install -m 444 -o root -g bin /etc/ssl/cert.pem /etc/ssl/openssl.cnf /var/www/etc/ssl/
slowcgi
./var/www/cgi-bin/
sont accessibles grâce à
slowcgi(8)
. Ceux de nagios sont fournis dans le répertoire enfant nagios/
.Ici, je vous renvoie à mon article de découverte du serveur httpd, et tout particulièrement aux informations d’utilisations .
Modification du fichier de configuration /etc/httpd.conf
pour y ajouter :
Code :
include "/etc/httpd.d/nagios.conf"
Création du fichier de config du serveur pour nagios /etc/httpd.d/nagios.conf
:
Code :
server "192.168.1.3" {
listen on * port 80
root "/"
location "/cgi-bin/nagios/*.cgi" {
authenticate "! Nagios Restricted !" with "/nagios.ht"
fastcgi socket "/run/slowcgi.sock"
root "/"
}
location "/" {
authenticate "! Nagios Restricted !" with "/nagios.ht"
directory index index.php
root "/nagios"
}
location "*.php" {
fastcgi socket "/run/php-fpm.sock"
root "/nagios"
}
}
Il est hautement recommandé de créer une authentification web avec accès restreint !
Sachant que le compte admin par défaut est nagiosadmin
, utilisons l’outil htpasswd
:
Code : sh
# htpasswd nagios.ht nagiosadmin
Réfléchissez bien avant de vouloir changer de nom d’administrateur, car il faudra le modifier au moins dans le fichier objects/contacts.cfg
…
Ensuite, il faut lui donner des droits d’exécution 0400
, et utilisateur web www
, autrement l’authentification ne se fera pas.
Il est ensuite possible de configurer d’autres utlisateurs, de la même manière auquels un rôle sera attribué, tel que celui d’operator
.
Tous les fichiers de configuration se trouvent dans /etc/nagios
- qui se trouve être un alias de /var/www/etc/nagios
:
use_authentication
: Seulement le temps de tester que tout fonctionne, il est possible de mettre la valeur à O
pour désactiver l’authentification - ATTENTION, c'est une très mauvaise idée de fonctionner sans authentification !
authorized_for_*
: si vous avez paramétré un rôle particulier, ou tout autre nom d’utilisateur, vous pouvez l’ajouter selon ce qui est désirable d’être utilisé par ce rôle, ou cet utilisateur.show_context_help
: utile pour avoir une aide contextuelle*_sound
qui émettront un son caractéristique lié à l’erreur remontée.lock_author_names
sur la valeur 1
permet d’empêcher le changement de nom d’utilisateur.admin_email
: remplacer la valeur par défaut, par votre courriel.date_format
: choisir la valeur euro
use_timezone
: paramètrer Europe/Paris
Les fichiers de configuration se trouvent dans le répertoire enfant objects
:
alias
: remplacer par un alias d’administration personnalisé, si besoin.contact_name
: remplacer par votre identifiantemail
: remplacer par votre courriel administrateurCitation :
It appears as though you do not have permission to view information for any of the hosts you requested…
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI and check the authorization options in your CGI configuration file.
cgi.cfg
, cf les options authorized_*
?Cherchez votre oubli !
Autres moniteurs réseaux :
Suivant les recommandations que l’on retrouve sur mon autre article , à-propos des règles à mettre en place pour autoriser ou bloquer le flux ICMP, voici les règles PF adéquates, pour tout BSD qui utilise Packet Filter, dont OpenBSD :
(…)
icmp_block_types="{ 4 6 15 16 17 18 31 32 33 34 35 36 37 38 39 }"
(…)
block drop quick on egress inet proto icmp icmp-type 3 code 6
block drop in quick on egress inet proto icmp icmp-type 3 code 7
block drop quick on egress inet proto icmp icmp-type 3 code 8
block drop quick on egress inet proto icmp icmp-type $icmp_block_types
(…)
limit
d’Iptables n’existe pas pour PF !
Il semble que c’est géré finement par le noyau BSD d’OpenBSD.(…)
icmp_types="{ 8 11 12 }"
(…)
block log
pass out
(…)
pass in quick on egress inet proto icmp from any to egress icmp-type { 3 code 3, 3 code 4 }
pass in quick on egress inet proto icmp from any to egress icmp-type $icmp_types
pass out quick on egress inet proto icmp from egress to any icmp-type { 3 code 3, 3 code 4 }
pass out quick on egress inet proto icmp from egress to any icmp-type $icmp_types
Bien-sûr, vous pouvez autoriser tous les autres codes qui peuvent être autorisés et dont les recommandations sont de limiter. Les trois codes mis en exergue sont un minima !
Reprenant le principe des informations renfermées dans mon autre article , à-propos des recommandations faites pour autoriser ou bloquer le flux ICMPv6, voici les règles PF adéquates pour tout BSD qui utilise Packet Filter, dont OpenBSD :
Ces types ICMPv6 sont à rejeter absolument :
icmp6_block = "{ 100 101 127 138 139 140 144 145 146 147 150 200 201 }"
block drop quick log on egress inet6 proto icmp6 icmp6-type $icmp6_block
⇒ Gestion d’une station :
icmp6_auth = "{ unreach toobig timex paramprob echoreq echoreq neighbradv neighbrsol }"
pass out quick on egress inet6 proto icmp6 from any to ff02::2 icmp6-type { routersol, listenrepv2 }
pass in quick on egress inet6 proto icmp6 from fe80::/64 to ff02::1 icmp6-type { routeradv }
pass quick on egress inet6 proto icmp6 icmp6-type $icmp6_auth allow-opts
pass in quick on egress inet6 proto icmp6 from any to egress icmp6-type redir allow-opts
Explications
La première règle définit les types ICMPv6 autorisés nécessaires, au minimum.
La deuxième règle autorise en sortie :
ff02::2
est l’adresse multicast local de tout routeur —listenrepv2
La troisième règle autorise en entrée les annonces de routeur — type 143 —
à destination du nœud local de notre station — ff02::1
.
La quatrième règle autorise en entrée et en sortie, tous les types
mentionnés dans la première règle — la macro $icmp6_auth
.
La cinquième règle autorise en entrée toute annonce ICMPv6 de redirection vers une route plus courte.
Les règles deux et trois sont strictement nécessaires pour débuter une communication sur le protocole IPv6 ; sans elles, la station sera incapable de le faire correctement !
⇒ Gestion d’un routeur :
Pour débuter, faisons simplement :
icmp6_auth = "{ echoreq echoreq neighbradv neighbrsol }"
pass in quick on egress inet6 proto icmp6 icmp6-type { routersol, listenrepv2 }
pass out quick on egress inet6 proto icmp6 icmp6-type routeradv
pass quick on egress inet6 proto icmp6 icmp6-type $icmp6_auth
Pour limiter le trafic ICMPv6, PF peut utiliser les STO .
Pour reprendre l’exemple ci-dessus, en utilisant l’option
max-src-conn-rate
:
icmp6_auth = "{ unreach toobig timex paramprob echoreq neighbradv neighbrsol }"
icmp6_sto = "( max-src-conn-rate 100/10 )"
pass out quick on egress inet6 proto icmp6 from any to ff02::2 icmp6-type { routersol, listenrepv2 }
pass in quick on egress inet6 proto icmp6 from fe80::/64 to ff02::1 icmp6-type { routeradv }
pass quick on egress inet6 proto icmp6 icmp6-type $icmp6_auth allow-opts $icmp6_sto
pass in quick on egress inet6 proto icmp6 from any to egress icmp6-type redir allow-opts $icmp6_sto
icmp6_auth = "{ unreach, toobig, timex code 0, timex code 1, paramprob code 1, paramprob code 2, echorep, echoreq, neighbradv, neighbrsol }"
icmp6_out = "{ echorep, echoreq, neighbradv, neighbrsol }"
icmp6_sto = "( max-src-conn-rate 100/10 )"
pass out quick on egress inet6 proto icmp6 from any to ff02::2 icmp6-type { routersol, listenrepv2 }
pass in quick on egress inet6 proto icmp6 from fe80::/64 to ff02::1 icmp6-type { routeradv, redir }
pass quick on egress inet6 proto icmp6 icmp6-type $icmp6_auth allow-opts $icmp6_sto
pass out quick on egress inet6 proto from egress to any icmp6 icmp6-type $icmp6_out allow-opts $icmp6_sto
Explications
La règle icmp6_auth
ne gére que ce qui est absolument nécessaire…
attention à bien utiliser les virgules séparant les codes,
autrement elle ne serait pas fonctionnelle !
La règle icmp6_out
n’autorise seulement que les messages d’echo et
les messages de découvertes des voisins.
on a ajouté dans la première règle in
la gestion des messages de
redirection vers une route plus courte, seulement depuis un routeur
vers notre machine. ATTENTION : autoriser le message de redirection
de toute autre manière posera des problèmes de sécurité, à tel point
qu’il semble recommander de les supprimer dans le contexte de parefeu !
⇒ Cas d’un routeur :
icmp6_auth = "{ unreach toobig timex paramprob echoreq echoreq neighbradv neighbrsol }"
icmp6_sto = "( max-src-conn-rate 100/10 )"
pass in quick on egress inet6 proto icmp6 icmp6-type { routersol, listenrepv2 }
pass out quick on egress inet6 proto icmp6 icmp6-type { routeradv, redir }
pass quick on egress inet6 proto icmp6 icmp6-type $icmp6_auth allow-opts $icmp6_sto
La commande traceroute
a un comportement particulier, car il est possible
d’utiliser l’option -I
afin de simuler le comportement d’ICMP, voire d’ICMPv6.
Voici la règle utile afin de sortir sur le protocol udp
:
pass out on egress inet proto udp to port 33433:33626
La commande équivalente nommée traceroute6
pour la pile IPv6 fonctionne
avec les mêmes options, donc de la même manière !
Allez lire un peu le manpage traceroute(8), cela fait toujours du bien de se rafraîchir la mémoire !
Normalement le port donné pour le service sane
est le 6566
sur le protocole tcp
.
Il suffit donc d’écrire une règle équivalente :
pass out on egress proto tcp from egress to egress:network port 6566 flag S/SA modulate state
Si vous avez une MFP de marque Epson, le port 1865
sur udp
est celui qu’il faut contacter…
par défaut. (d’autres sont possibles, dépendant de votre modèle)
Mais une analyse de l’activité sur l’interface pflog0
, par le biais de
la fameuse commande tcpdump -n -e -ttt -i pflog0
nous restitue qu’il
envoie des paquets sur udp
à l’attention du réseau local, puis interroge
en envoyant des paquets broadcasts, avant d’obtenir une réponse de l’imprimante…
bref, tout se passe en udp
.
Code : sh
Oct 10 13:15:25.146815 rule 53/(match) block in on axe0: 192.168.1.2.8612 > 192.168.1.255.8612: udp 16
Oct 10 13:15:25.146890 rule 53/(match) block in on axe0: 192.168.1.2.8612 > 192.168.1.255.8610: udp 16
Oct 10 13:15:25.158437 rule 53/(match) block in on axe0: 192.168.1.2.8612 > 192.168.1.255.8612: udp 16
Oct 10 13:15:25.158493 rule 53/(match) block in on axe0: 192.168.1.2.8612 > 192.168.1.255.8610: udp 16
Oct 10 13:15:30.007313 rule 53/(match) block in on axe0: 192.168.1.2.4891 > 255.255.255.255.3289: udp 15 [ttl 1]
Oct 10 13:15:30.020862 rule 53/(match) block in on axe0: 192.168.1.3.3289 > 192.168.1.2.4891: udp 76
Oct 10 13:15:31.171140 rule 53/(match) block in on axe0: 192.168.1.2.17068 > 255.255.255.255.1124: udp 37 [ttl 1]
Le plus simple est d’autoriser le flux du protocole udp
entrant et
venant du réseau local vers ou depuis l’interface locale :
pass in quick on egress proto udp from egress to egress:network allow-opts
pass in quick on egress proto udp from egress:network to egress allow-opts
Voici les règles pare-feu au besoin :
Code : sh
# avahi
pass on egress inet proto udp from any to 224.0.0.251 port mdns allow-opts
pass on egress inet6 proto udp from any to ff02::fb port mdns allow-opts
# ssdp
pass on egress inet proto udp from any to 239.255.255.250 port 1900 allow-opts
pass on egress inet6 proto udp from any to { ff02::c, ff05::c, ff08::c } port 1900 allow-opts
Concernant le trafic SSDP :
ff02::c
est l’adresse multicast de lien localff05::c
est l’adresse multicast de site localff08::c
est l’adresse multicast d’organisation localff0e::c
pour l’adresse multicast global - que nous
n’utiliserons pas dans le contexte local !Voici les règles PF nécessaires :
⇒ macros
smb_ports_tcp = "{ 135 137 139 445 }"
smb_ports_udp = "{ 135 137 138 445 }"
⇒ samba in
pass in quick on egress proto tcp from egress:network to egress port $smb_ports_tcp flags S/SA modulate state
pass in quick on egress proto udp from egress:network to egress port $smb_ports_udp allow-opts
⇒ samba out
pass out on egress proto tcp from egress to egress:network port $smb_ports_tcp flags S/SA modulate state
pass out on egress proto udp from egress to egress:network port $smb_ports_udp allow-opts
Voici les règles PF nécessaires :
⇒ in :
pass in quick on egress inet proto tcp from egress:network to egress port 22000 flags S/SA modulate state
pass in quick on egress inet proto udp from egress:network to egress port 21027 allow-opts
⇒ out :
pass out quick on egress inet proto tcp from egress to egress:network port 22000 flags S/SA modulate state
pass out quick on egress inet proto udp from egress to egress:network port 21027 allow-opts
Bien-sûr, ces règles pour Syncthing sont à modifier, surtout si vous modifiez les ports dans la configuration de Syncthing !
Ce sont des règles de bases, pour exemple !
Très simplement :
⇒ IPv4 :
pass on egress inet proto icmp all icmp-type echoreq
⇒ IPv6 :
pass on egress inet6 proto icmp all icmp6-type echoreq
N’hésitez pas à (re?)lire le manpage concernant la commande ping
,
et son équivalent ping6
qui fonctionne de la même manière avec presque
toutes les mêmes options…
La virtualisation de machine virtuelle sous OpenBSD est officiellement disponible nativement dans le système de base depuis OpenBSD 5.9.
ATTENTION : Ce tutoriel ne documente pas dans les moindres détails les phases d’installation, voire de configuration.
Il est VRAIMENT nécessaire de faire preuve de réflexion, discernement et d’avoir un minimum de compétences, pour comprendre les liens entre les différentes briques !
Merci de votre compréhension…
Il est nécessaire que votre machine sur laquelle vous souhaitez virtualiser ait un CPU compatible avec les fonctions adéquates. Pour le vérifier, tapez dans votre terminal/console la commande suivante :
$ dmesg | egrep '(VMX/EPT|SVM/RVI)'
La réponse du système doit être :
⇒ pour CPU Intel :
vmm0 at mainbus0: VMX/EPT
⇒ pour CPU Amd :
vmm0 at mainbus0: SVM/RVI
Si aucune ligne n’apparaît, aucune virtualisation ne sera possible. Par acquis de conscience, vérifiez votre BIOS|UEFI que celle-ci ne soit pas désactivée.
De même, en rapport avec les failles CPU relatives à Meltdown, Spectre, certains CPU Intel sont patchés pour remédier à L1TF. Sous OpenBSD, ces CPU reçoivent un correctif approprié. Malheureusement, cela impacte la virtualisation et rend celle-ci impossible. Vous pouvez vous retrouver dans la situation où vous auriez un CPU compatible, mais dans les faits, la virtualisation ne pourrait être pleinement fonctionnelle.
Préférez AMD, en attendant ARM…
Il est nécessaire d’installer le firmware vmm
pour que le kernel gère.
# fw_update vmm
Par convention, créons un répertoire ‘‘vm’’ dans notre répertoire personnel,
et nous travaillerons à partir de celui-ci :
$ mkdir vm && cd vm
vether0
de l’hôte aura pour adresse IPv4 : 192.168.0.1
,
cette adresse IP sera l’adresse de la passerelle pour l’interface réseau de la VM.enp0s3
de la VM Debian aura pour adresse IPv4 : 192.168.0.2
/etc/resolv.conf
de la VM de
Debian est, par convention 1.1.1.1
. C’est celui de Cloudfare.
Mais il peut être très bien tout autre, pourvu qu’il soit respectueux
de la confidentialité… tel que ceux de Quad9, par exemple !Dans les deux cas présentés, nous commencerons par créer la VM, très simplement
avec l’outil natif à OpenBSD, nommé vmctl
:
$ vmctl create ~/vm/buster.qcow2 -s 10G
$ vmctl create -s 10G ~/vm/buster.qcow2
ATTENTION, vérifiez à l’URL suivante le nom de l’image iso de debian : https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/
Et, modifiez en conséquence le code ci-dessous !
Téléchargeons l’iso Debian :
Code : shell
$ ftp https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/{debian-10.1.0-amd64-netinst.iso,SHA512SUMS}
Trying 2001:6b0:19::173...
Trying 2001:6b0:19::165...
Trying 194.71.11.165...
Requesting https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-10.1.0-amd64-netinst.iso
Redirected to https://gemmei.ftp.acc.umu.se/debian-cd/current/amd64/iso-cd/debian-10.1.0-amd64-netinst.iso
Trying 2001:6b0:19::137...
Trying 194.71.11.137...
Requesting https://gemmei.ftp.acc.umu.se/debian-cd/current/amd64/iso-cd/debian-10.1.0-amd64-netinst.iso
100% |*************************************************************************************************************************************************************| 335 MB 00:54
351272960 bytes received in 54.52 seconds (6.14 MB/s)
Trying 2001:6b0:19::165...
Trying 2001:6b0:19::173...
Trying 194.71.11.173...
Requesting https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/SHA512SUMS
100% |*************************************************************************************************************************************************************| 658 00:00
658 bytes received in 0.00 seconds (639.20 KB/s)
Une fois téléchargée, vérifions sa somme de contrôle :
sha512 -C SHA512SUMS debian-10.1.0-amd64-netinst.iso
(SHA512) debian-10.1.0-amd64-netinst.iso: OK
Si OK, alors c’est bon… sinon, re-téléchargez !
Le fichier de configuration se trouve être /etc/vm.conf
. Il faut écrire
votre compte identifiant dans la variable USER
, cela permettra à votre
utilisateur d’utiliser l’outil vmctl
…
Code : shell
USER=""
VM="/home/$USER/vm"
switch "sw" {
interface bridge0
}
vm "buster" {
disable
memory 1G
cdrom $VM/debian-10.1.0-amd64-netinst.iso
disk $VM/debian.qcow2
interface { switch "sw" }
owner $USER
}
Vérifiez la configuration à l’aide de l’option -n
de vmd :
$ vmd -n
Après avoir configuré les interfaces réseaux
,
il faut maintenant démarrer le service de gestion des VMs :
# rcctl enable vmd
# rcctl start vmd
Il est assurément utile de s’occuper de la traduction d'adresses réseaux , et aussi des règles du parefeu …
Créons les interfaces réseaux nécessaires que sont vether0
et bridge0
qui permettront un contrôle fin de l’adressage IP et des règles PF.
Pour l’interface vether0
, il est possible d’utiliser n’importe quelle
classe privée IPv4 (A: 10.0/8 ; B: 172.0.0/16 ; C: 192.168.0.0/24) -
nous utiliserons un type de classe C privée, telle que 192.168.0.x
.
Après tout, nous n’avons pas plus de 256 VM à administrer… ;)
Le fichier relatif est /etc/hostname.bridge0
:
Fichier : /etc/hostname.bridge0
|
|
Le fichier relatif est /etc/hostname.vether0
:
Fichier : /etc/hostname.vether0
|
|
Une fois les fichiers d’interfaces créés, donnez des droits 0600 dessus,
puis démarrez les deux interfaces :
# chmod 0600 /etc/hostname.{bridge,vether}0
# sh /etc/netstart {bridge,vether}0
Pour nous faciliter la vie avec notre futur VM, nous allons autoriser la redirection des paquets IP, pour qu’elle puisse communiquer sur Internet - ne serait-ce que pour faire les mises à jour…
Dans un terminal/console, écrivez :
# sysctl net.inet.ip.forwarding=1
# sysctl net.inet6.ip6.forwarding=1
La première ligne est pour IPv4, la seconde pour IPv6.
Puis, pour garder les paramètres au redémarrage, modifiez le fichier
/etc/sysctl.conf
pour ajouter :
net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1
Il sera ensuite nécessaire de modifier le fichier /etc/pf.conf
ajouter
au moins les règles suivantes :
Code : shell
(…)
domain = "1.1.1.1"
match out on egress from (vether0:network) to any nat-to (egress)
(…)
pass in quick proto { udp tcp } from (vether0:network) to any port domain rdr-to $domain port domain
pass on vether0 from 127.0.0.1 to any
pass on vether0 from (vether0:network) to any
(…)
vether0
doit être traduit (NATé) vers les adresses IP faisant partie
du groupe egress
.domain
(port 53
) sur les protocoles udp
et tcp
depuis
le réseau lié à l’interface vether0
soit redirigée vers le service
en question.
L’adresse IPv4 1.1.1.1
est celle du serveur DNS de Cloudflare ;
elle peut être très bien celle de tout autre serveur DNS.vether0
depuis l’interface locale
vers ailleurs…vether0
vers partout !$ vmctl start buster -c
$ vmctl start -c buster
> /install.amd/vmlinuz vga=788 initrd=/install.amd/initrd.gz --- quiet
en
> /install.amd/vmlinuz vga=off initrd=/install.amd/initrd.gz --- quiet console=ttyS0,115200n8
;
une fois, transformée, appuyez sur la touche ENTRÉE !Le reste de l’installation de Debian se fait comme tout autre installation… à vous de paramétrer selon vos besoins.
Une fois l’installation terminée, ne redémarrez pas par le biais de l’installateur,
choisissez d’exécuter le shell, puis écrivez la commande :
# halt
afin d’arrêter la VM proprement !
Une fois que vous avez fini l’installation de Debian dans votre VM, que
vous avez fait les derniers réglages nécessaires pour son bon fonctionnement,
pensez à éditer à nouveau le fichier /etc/vm.conf
:
cdrom
…disable
par enable
pour la VM debian
-
si vous désirez que la VM correspondante démarre, soit lors du démarrage
de votre machine, si et seulement si le service vmd
est bien actif
et démarré lors du processus de démarrage machine, soit lorsque vous
redémarrez le service vmd
lui-même par vos soins.Vous n’avez tout simplement pas installé le firmware vmm !
Un tout petit laïus sur la commande vmctl
:
$ man vmctl
pour découvrir les différentes options bien utiles,
dont show
, status
, start
, et stop
qu’il semble nécessaire de maîtriser !
Enjoy-IT! Enjoy-ID!
Depuis OpenBSD 6.0, l’option de montage wxallowed
est configuré par
défaut sur /usr/local
. Pour ceux qui ne le savent pas, c’est une protection
système. Si la partition a cette option, les logiciels sont autorisés à
fonctionner depuis cette partition, sinon ils ne pourront fonctionner et
émettront un message de violation W^X
, tel que :
$ dmesg | grep wxallowed
/home/hs/.local/share/virtualenvs/mybeautifullproject-q1koN8ay/bin/python3(26392): W^X binary outside wxallowed mountpoint
De fait, puisque seul /usr/local
a cette option activée, si vous tentez
d’exécuter un programme depuis, par exemple, votre $HOME
, cela ne fonctionnera
pas. Et, c’est tout le problème avec les environnements Python qui doivent
fonctionner dans votre répertoire personnel.
Dans les faits, voici ce qui se passe pour virtualenv
:
Code : shell
$ virtualenv mybeautifullproject
Using base prefix '/usr/local'
New python executable in $HOME/python/mybeautifullproject.py/mybeautifullproject/bin/python3
Also creating executable in $HOME/python/mybeautifullproject.py/mybeautifullproject/bin/python
ERROR: The executable $HOME/python/mybeautifullproject.py/mybeautifullproject/bin/python3 could not be run: [Errno 13] Permission denied: '$HOME/python/mybeautifullproject.py/mybeautifullproject/bin/python
C’est pareil pour pipenv
:
Code : shell
$ pipenv install requests
Warning: the environment variable LANG is not set!
We recommend setting this in ~/.profile (or equivalent) for proper expected behavior.
Creating a virtualenv for this project…
Pipfile: $HOME/python/mybeautifullproject.py/Pipfile
Using /usr/local/bin/python3 (3.6.8) to create virtualenv…
⠇ Creating virtual environment...Already using interpreter /usr/local/bin/python3
Using base prefix '/usr/local'
New python executable in $HOME/.local/share/virtualenvs/mybeautifullproject.py-oFlnu9vD/bin/python3
Also creating executable in $HOME/.local/share/virtualenvs/mybeautifullproject.py-oFlnu9vD/bin/python
ERROR: The executable $HOME/.local/share/virtualenvs/mybeautifullproject.py-oFlnu9vD/bin/python3 could not be run: [Errno 13] Permission denied: '$HOME/.local/share/virtualenvs/mybeautifullproject.py-oFlnu9vD/bin/python3'
✘ Failed creating virtual environment
[pipenv.exceptions.VirtualenvCreationException]: File "$HOME/.local/lib/python3.6/site-packages/pipenv/cli/command.py", line 254, in install
[pipenv.exceptions.VirtualenvCreationException]: editable_packages=state.installstate.editables,
[pipenv.exceptions.VirtualenvCreationException]: File "$HOME/.local/lib/python3.6/site-packages/pipenv/core.py", line 1741, in do_install
[pipenv.exceptions.VirtualenvCreationException]: pypi_mirror=pypi_mirror,
[pipenv.exceptions.VirtualenvCreationException]: File "$HOME/.local/lib/python3.6/site-packages/pipenv/core.py", line 574, in ensure_project
[pipenv.exceptions.VirtualenvCreationException]: pypi_mirror=pypi_mirror,
[pipenv.exceptions.VirtualenvCreationException]: File "$HOME/.local/lib/python3.6/site-packages/pipenv/core.py", line 506, in ensure_virtualenv
[pipenv.exceptions.VirtualenvCreationException]: python=python, site_packages=site_packages, pypi_mirror=pypi_mirror
[pipenv.exceptions.VirtualenvCreationException]: File "$HOME/.local/lib/python3.6/site-packages/pipenv/core.py", line 935, in do_create_virtualenv
[pipenv.exceptions.VirtualenvCreationException]: extra=[crayons.blue("{0}".format(c.err)),]
[pipenv.exceptions.VirtualenvCreationException]:
Failed to create virtual environment.
D’autant que ce n’est vraiment pas un problème de droits utilisateurs :
Code : shell
$ ls -al mybeautifullproject/
total 40
drwxr-xr-x 5 hs hs 512 Jun 3 01:43 ./
drwxr-xr-x 3 hs hs 512 Jun 3 01:44 ../
drwxr-xr-x 2 hs hs 512 Jun 3 01:43 bin/
drwxr-xr-x 2 hs hs 512 Jun 3 01:43 include/
drwxr-xr-x 3 hs hs 512 Jun 3 01:43 lib/
$ ls -al mybeautifullproject/bin/
total 40
drwxr-xr-x 2 hs hs 512 Jun 3 01:43 ./
drwxr-xr-x 5 hs hs 512 Jun 3 01:43 ../
lrwxr-xr-x 1 hs hs 7 Jun 3 01:43 python@ -> python3
-rwxr-xr-x 1 hs hs 10680 Jun 3 01:43 python3*
lrwxr-xr-x 1 hs hs 7 Jun 3 01:43 python3.6@ -> python3
Une petite modification système va faciliter notre vie - puisque /usr/local
est la seule partition autorisée à l’exécution des programmes qui nécessitent
la violation W^X
:
# mkdir -p /usr/local/${my_user}/python
# chown -R ${my_user}:wheel /usr/local/${my_user}
# ln -s /usr/local/${my_user}/python $home/python
Remplacez ${my_user}
par votre identifiant de session ;)
Si vous avez la bonne idée d’utiliser l’outil pipenv
, il faudra créer
un nouveau répertoire et le lier symboliquement ; lisez la section TL;DR
ci-dessous…
Remplacez ‘’${my_user}’’ par votre identifiant de session !
=> Pour virtualenv :
# mkdir -p /usr/local/${my_user}/python
# chown -R ${my_user}:wheel /usr/local/${my_user}
# ln -s /usr/local/${my_user}/python $home/python
=> Pour pipenv, il faut rajouter à ce qui suit au-dessus :
$ mkdir /usr/local/$USER/python/virtualenvs
$ ln -s /usr/local/$USER/python/virtualenvs $HOME/.local/share/virtualenvs
Depuis OpenBSD 6.0, l’option de montage wxallowed
est configuré par
défaut sur /usr/local
. Pour ceux qui ne le savent pas, c’est une protection
système. Si la partition a cette option, les logiciels sont autorisés à
fonctionner depuis cette partition, sinon ils ne pourront fonctionner et
émettront un message de violation W^X
, tel que :
$ dmesg | grep wxallowed
/home/hs/.local/share/virtualenvs/mybeautifullproject-q1koN8ay/bin/python3(26392): W^X binary outside wxallowed mountpoint
De fait, puisque seul /usr/local
a cette option activée, si vous tentez
d’exécuter un programme depuis, par exemple, votre $HOME
, cela ne fonctionnera
pas. Et, c’est tout le problème avec les environnements Python qui doivent
fonctionner dans votre répertoire personnel.
Dans les faits, voici ce qui se passe pour virtualenv
:
Code : shell
$ virtualenv mybeautifullproject
Using base prefix '/usr/local'
New python executable in $HOME/python/mybeautifullproject.py/mybeautifullproject/bin/python3
Also creating executable in $HOME/python/mybeautifullproject.py/mybeautifullproject/bin/python
ERROR: The executable $HOME/python/mybeautifullproject.py/mybeautifullproject/bin/python3 could not be run: [Errno 13] Permission denied: '$HOME/python/mybeautifullproject.py/mybeautifullproject/bin/python
C’est pareil pour pipenv
:
Code : shell
$ pipenv install requests
Warning: the environment variable LANG is not set!
We recommend setting this in ~/.profile (or equivalent) for proper expected behavior.
Creating a virtualenv for this project…
Pipfile: $HOME/python/mybeautifullproject.py/Pipfile
Using /usr/local/bin/python3 (3.6.8) to create virtualenv…
⠇ Creating virtual environment...Already using interpreter /usr/local/bin/python3
Using base prefix '/usr/local'
New python executable in $HOME/.local/share/virtualenvs/mybeautifullproject.py-oFlnu9vD/bin/python3
Also creating executable in $HOME/.local/share/virtualenvs/mybeautifullproject.py-oFlnu9vD/bin/python
ERROR: The executable $HOME/.local/share/virtualenvs/mybeautifullproject.py-oFlnu9vD/bin/python3 could not be run: [Errno 13] Permission denied: '$HOME/.local/share/virtualenvs/mybeautifullproject.py-oFlnu9vD/bin/python3'
✘ Failed creating virtual environment
[pipenv.exceptions.VirtualenvCreationException]: File "$HOME/.local/lib/python3.6/site-packages/pipenv/cli/command.py", line 254, in install
[pipenv.exceptions.VirtualenvCreationException]: editable_packages=state.installstate.editables,
[pipenv.exceptions.VirtualenvCreationException]: File "$HOME/.local/lib/python3.6/site-packages/pipenv/core.py", line 1741, in do_install
[pipenv.exceptions.VirtualenvCreationException]: pypi_mirror=pypi_mirror,
[pipenv.exceptions.VirtualenvCreationException]: File "$HOME/.local/lib/python3.6/site-packages/pipenv/core.py", line 574, in ensure_project
[pipenv.exceptions.VirtualenvCreationException]: pypi_mirror=pypi_mirror,
[pipenv.exceptions.VirtualenvCreationException]: File "$HOME/.local/lib/python3.6/site-packages/pipenv/core.py", line 506, in ensure_virtualenv
[pipenv.exceptions.VirtualenvCreationException]: python=python, site_packages=site_packages, pypi_mirror=pypi_mirror
[pipenv.exceptions.VirtualenvCreationException]: File "$HOME/.local/lib/python3.6/site-packages/pipenv/core.py", line 935, in do_create_virtualenv
[pipenv.exceptions.VirtualenvCreationException]: extra=[crayons.blue("{0}".format(c.err)),]
[pipenv.exceptions.VirtualenvCreationException]:
Failed to create virtual environment.
D’autant que ce n’est vraiment pas un problème de droits utilisateurs :
Code : shell
$ ls -al mybeautifullproject/
total 40
drwxr-xr-x 5 hs hs 512 Jun 3 01:43 ./
drwxr-xr-x 3 hs hs 512 Jun 3 01:44 ../
drwxr-xr-x 2 hs hs 512 Jun 3 01:43 bin/
drwxr-xr-x 2 hs hs 512 Jun 3 01:43 include/
drwxr-xr-x 3 hs hs 512 Jun 3 01:43 lib/
$ ls -al mybeautifullproject/bin/
total 40
drwxr-xr-x 2 hs hs 512 Jun 3 01:43 ./
drwxr-xr-x 5 hs hs 512 Jun 3 01:43 ../
lrwxr-xr-x 1 hs hs 7 Jun 3 01:43 python@ -> python3
-rwxr-xr-x 1 hs hs 10680 Jun 3 01:43 python3*
lrwxr-xr-x 1 hs hs 7 Jun 3 01:43 python3.6@ -> python3
Une petite modification système va faciliter notre vie - puisque /usr/local
est la seule partition autorisée à l’exécution des programmes qui nécessitent
la violation W^X
:
# mkdir -p /usr/local/${my_user}/python
# chown -R ${my_user}:wheel /usr/local/${my_user}
# ln -s /usr/local/${my_user}/python $home/python
Remplacez ${my_user}
par votre identifiant de session ;)
Si vous avez la bonne idée d’utiliser l’outil pipenv
, il faudra créer
un nouveau répertoire et le lier symboliquement ; lisez la section TL;DR
ci-dessous…
Remplacez ‘’${my_user}’’ par votre identifiant de session !
=> Pour virtualenv :
# mkdir -p /usr/local/${my_user}/python
# chown -R ${my_user}:wheel /usr/local/${my_user}
# ln -s /usr/local/${my_user}/python $home/python
=> Pour pipenv, il faut rajouter à ce qui suit au-dessus :
$ mkdir /usr/local/$USER/python/virtualenvs
$ ln -s /usr/local/$USER/python/virtualenvs $HOME/.local/share/virtualenvs
Le choix de l’outil de synchronisation des données calendriers et de contacts est délicat. Oubliez DavDroid/Davx5, la solution qui fonctionne est l’usage de l’app “OpenSync” — qui est un “fork” de la précédente application, disponible sur n’importe quel store -
Celle-ci demande l’installation de l’app “Open Tasks”, complémentaire pour gérer les tâches.
Avant de chercher à paramétrer votre connexion vers votre nuage informatique, tel Nextcloud, il faut configurer votre système MIUI.
Le mode opératoire est le suivant :
Menu “Paramètres” > “Applis et notifications” : recherchez “OpenSync”
1 v10: il semble qu’il faille appuyer sur les noms “Agenda”, puis “Contacts” pour avoir accès au choix d’autoriser ou de refuser l’autorisation
Faites quasiment de même avec “OpenTasks” en validant les autorisations sur “Contacts”, et en “Autorisations supplémentaires”, activez “Tâches”.
Pour finir, vérifiez dans les “Options avancées”2 , puis “Batterie” que “Optimisation de la batterie” soit bien positionnée sur “Non optimisée” - ce qui devrait être le cas, puisque paramétré précédemment ; sinon, faites-le !
2 v10 : ce menu s’appelle “Préférences avancées”
Menu “Paramètres” > “applications installées”3 , cherchez “OpenSync” et appuyez sur le nom de l’application.
3 v11 : ce menu s’appelle tout simplement “Applis”
Toujours dans le menu “Paramètres”, à “Autorisations”, puis “Gestion du démarrage automatique”, vérifiez que vous ayez bien “OpenSync” et “OpenTasks”, toutes les deux activées.
Ensuite, dans l’application “Sécurité” :
Maintenant, ouvrez l’app “OpenSync”, et ajoutez votre paramétrage de connexion vers votre serveur Nextcloud.
Puis redémarrez votre smartphone !
Ensuite, ouvrez à nouveau “OpenSync” et exécutez une synchronisation des différentes données que vous avez paramétré.
Je ne présenterais ni PHP, ni composer…
Versions logicielles :
Les deux “outils” sont disponibles en tant que paquets, pour l’exemple :
pkg_add -v php-7.2 composer
Après l’installation de Composer, faites une mise à jour de lui-même :
composer self-update
De même, je ne détaillerais pas la configuration ni de PHP, ni de Composer, d’autant que par défaut pour ce dernier, il n’y a rien à faire en soit - il est bien sûr possible de configurer certaines options…
Pour information, par défaut, Composer est configuré pour être exécuté avec php-7.0 sous la 6.4, et php-7.1 sous 6.5 - qu’il installe en dépendances (avec femail*)
Le problème qui se pose est que si vous utilisez php-7.2, voire php-7.3, Composer s’exécutera avec l’environnement PHP pour lequel il est paramétré par défaut - logique, vous me direz !
Alors, comment le contraindre ?
Très facilement :
# sed -i -e "s/php-7.x/php-7.y/" "$(which composer)"
où :
7.x
est votre installation PHP par défaut,7.y
la version de PHP que vous préférez utiliser, telle que 7.2, par exemple…Pour finir, on exécute ensuite un petit diagnostic :
Code : shell
$ composer diagnose
Checking platform settings: OK
Checking git settings: OK
Checking http connectivity to packagist: OK
Checking https connectivity to packagist: OK
Checking github.com rate limit: OK
Checking disk free space: OK
Checking pubkeys:
Tags Public Key Fingerprint: 57815BA2 7E54DC31 7ECC7CC5 573090D0 87719BA6 8F3BB723 4E5D42D0 84A14642
Dev Public Key Fingerprint: 4AC45767 E5EC2265 2F0C1167 CBBB8A2B 0C708369 153E328C AD90147D AFE50952
OK
Checking composer version: OK
Composer version: 1.8.5
PHP version: 7.2.17
PHP binary path: /usr/local/bin/php-7.2
Tous les voyants sont OK, Composer a la dernière version en cours, et il s’exécute bien avec la version de PHP désirée - (ici, dans cet exemple, la 7.2 !)
Et, oui, il n’est pas recommandé d'exécuter Composer avec des droits d'administrateurs - alors ne le faites pas !
Plus d’informations, sur : https://getcomposer.org/root
Il est possible que lors du diagnostique, vous vous retrouvez avec ce message d’erreur sur fond rouge :
Checking pubkeys: FAIL
Missing pubkey for tags verification
Missing pubkey for dev verification
Run composer self-update --update-keys to set them up
Il vous dit quoi faire !!!
Donc :
Code : shell
$ composer self-update --update-keys
Open https://composer.github.io/pubkeys.html to find the latest keys
Enter Dev / Snapshot Public Key (including lines with -----):
Là, le shell reste en attente jusqu’à ce que vous lui copiez la clé demandée, que vous trouverez sur https://composer.github.io/pubkeys.html, puisqu’il a même la gentillesse de vous le dire !
Si l’entrée saisie n’est pas correcte, vous aurez un message d’erreur : Invalid input
,
il vous sera redemandé de faire la saisie !
“My spelling is Wobbly. It’s good spelling but it Wobbles, and the letters get in the wrong places.” — Winnie-the-Pooh
Ayant grandit en fils de bibliothécaire et de spécialiste en langue anglaise, j’ai toujours été fasciné par les langages. Pas les langages de programmation. Enfin si, les langages de programmation, mais aussi les langages naturels. Prenez l’anglais. L’anglais est un langage schizophrénique qui emprunte des mots de l’allemand, du français, de l’espagnol et du latin (pour en citer quelque uns). En fait, “emprunte” n’est pas le bon mot ; “pille” est plus approprié. Ou peut être, “assimile” — comme les Borgs. Ouais, j’aime ça.
Nous sommes les Borgs. Vos caractèristiques linguistiques et étymologiques seront ajoutées aux nôtres. La résistance est futile.
Dans ce chapitre, vous allez apprendre les noms pluriels. Mais aussi, les fonctions qui retournent d’autres fonctions, les expressions régulières avancées, et les générateurs. Mais d’abord, discutons de comment former les noms pluriels. (Si vous n’avez pas encore lu le chapitre sur les expressions régulières, maintenant serait le bon moment. Ce chapitre assume que vous comprenez les bases des expressions régulières, et il en vient rapidement à des usages plus avancés.)
Si vous avez grandit dans un pays anglophone ou apprit l’anglais dans un contexte scolaire, vous êtes probablement familier avec les règles de base :
(Je sais, il y a plein d’exceptions. Man devient men et woman devient women, mais human devient humans. Mouse devient mice and louse devient lice, mais house devient houses. Knife devient knives et wife devient wives, mais lowlife devient lowlifes. Et ne parlons même pas des mots qui sont leur propre pluriel comme sheep, deer et haiku.)
Bien évidemment, les autres langues sont complètement différentes.
Développons une librairie Python qui forme automatiquement le pluriel des mots anglais. Nous commencerons seulement avec ces quatre règles, mais gardez à l’esprit que vous allez inévitablement en ajouter d’autres.
Dons vous recherchez des mots qui, au moins en anglais, signifie que vous recherchez des chaînes de caractères. Vous avez des règles qui disent que vous devez trouver différentes combinaisons de caractères, et leur faire différentes choses. Cela semble être un boulot pour les expressions régulières !
import re
def plural(noun):
if re.search('[sxz]$', noun): ### (1)
return re.sub('$', 'es', noun) ### (2)
elif re.search('[^aeioudgkprt]h$', noun):
return re.sub('$', 'es', noun)
elif re.search('[^aeiou]y$', noun):
return re.sub('y$', 'ies', noun)
else:
return noun + 's'
(1) C’est une expression régulière, mais elle utilise une syntaxe que vous n’avez pas vu dans le chapitre Expressions Régulières. Les crochets signifient “correspond exactement à un de ces caractères”. Donc [sxz]
signifie " s
, ou x
, ou z
“, mais seulement à un d’entre eux. Le $
devrait être familier ; il correspond à la fin de chaîne. Combinés, cette expression régulière vérifie si noun
se termine avec s
, x
ou z
.
(2) Cette fonction re.sub()
exécute une substitution de chaînes par expression régulière.
Regardons les substitutions par expression régulière plus en détail.
>>> import re
>>> re.search('[abc]', 'Mark') ### (1)
<_sre.SRE_Match object at 0x001C1FA8>
>>> re.sub('[abc]', 'o', 'Mark') ### (2)
'Mork'
>>> re.sub('[abc]', 'o', 'rock') ### (3)
'rook'
>>> re.sub('[abc]', 'o', 'caps') ### (4)
'oops'
(1) Est-ce que la chaîne Mark
contient a
, b
, ou c
? Oui, elle contient a
.
(2) OK, maintenant trouvons a
, b
, ou c
, et replaçons-le par o
. Mark
devient Mork
.
(3) La même fonction transforme rock
en rook
.
(4) Vous devez penser que cela devrait transformer caps
en oaps
, mais en fait non. re.sub
remplace toutes les correspondances, pas seulement la première. Donc cette expression régulière transforme caps
en oops
, parce que le c
et le a
sont tous les deux transformés en o
.
Et maintenant, revenons à la fonction plural()
…
def plural(noun):
if re.search('[sxz]$', noun):
return re.sub('$', 'es', noun) ### (1)
elif re.search('[^aeioudgkprt]h$', noun): ### (2)
return re.sub('$', 'es', noun)
elif re.search('[^aeiou]y$', noun): ### (3)
return re.sub('y$', 'ies', noun)
else:
return noun + 's'
(1) Ici, vous remplacez la fin de chaîne (correspondant à $
) par la chaîne es
. En d’autres mots, cela ajoute es
à la chaîne. Vous pouvez obtenir la même chose avec la concaténation de chaîne, par exemple noun + 'es'
, mais j’ai choisi d’utiliser les expressions régulières pour chaque règle, pour des raisons qui deviendront plus claires plus loin dans ce chapitre.
(2) Regardez attentivement, c’est une autre nouvelle variation. Le ^
, en premier caractère entre crochets, signifie quelque chose de spécial : la négation. [^abc]
signifie “n’importe quel caractère sauf a
, b
, ou c
”. Donc [^aeioudgkprt]
signifie n’importe quel caractère sauf a
, e
, i
, o
, u
, d
, g
, k
, p
, r
, ou t
. Puis ce caractère doit être suivi par h
, suivi par la fin de chaîne. Vous cherchez les mots qui finissent avec un H où le H est sonore.
(3) Même motif ici : trouver les mots qui se terminent par Y, où le caractère avant le Y n’est pas a
, e
, i
, o
, ou u
. Vous cherchez les mots qui finissent avec un Y qui sonne comme un I.
Regardons la négation d’expression régulière plus en détail.
>>> import re
>>> re.search('[^aeiou]y$', 'vacancy') ### (1)
<_sre.SRE_Match object at 0x001C1FA8>
>>> re.search('[^aeiou]y$', 'boy') ### (2)
>>>
>>> re.search('[^aeiou]y$', 'day')
>>>
>>> re.search('[^aeiou]y$', 'pita') ### (3)
>>>
(1) vacancy
correspond à cette expression régulière, parce qu’il se termine en cy
, et c
n’est pas a
, e
, i
, o
, ou u
.
(2) boy
ne correspond pas, parce qu’il se termine en oy
, et vous avez spécifiquement dit que le caractère avant le y
ne peut pas être o
. day
ne correspond pas, parce qu’il se termine en ay
.
(3) pita
ne correspond pas, parce qu’il ne se termine pas en y
.
>>> re.sub('y$', 'ies', 'vacancy') ### (1)
'vacancies'
>>> re.sub('y$', 'ies', 'agency')
'agencies'
>>> re.sub('([^aeiou])y$', r'\1ies', 'vacancy') ### (2)
'vacancies'
(1) Cette expression régulière transforme vacancy
en vacancies
et agency
en agencies
, ce qui est ce que vous voulez. Notez que cela transforme aussi boy
en boies
, mais cela n’arrivera jamais dans la fonction parce que vous avez fait cette recherche d’abord avec re.search
pour savoir si vous devez la faire avec re.sub
.
(2) Juste en passant, je voudrais pointer le fait qu’il est possible de combiner ces deux expressions régulières (une pour trouver si la règle s’applique, et une autre pour effectivement l’appliquer) en une unique expression régulière. Cela ressemblerait à ça. Cela doit sembler en grande partie familier : vous utilisez un groupe de capture, que vous avez appris dans l’Étude de Cas : Analyser les Numéros de Téléphone. Le groupe est utilisé pour capturer le caractère avant la lettre y
. Puis dans la chaîne de substitution, vous utilisez une nouvelle syntaxe, \1
, qui signifie « hé, tu te souviens de ce premier groupe ? met le ici. » Dans ce cas, vous capturez le c
avant le y
; quand vous faite la substitution, vous substituez c
à la place de c
, et ies
à la place de y
. (Si vous avez plus d’un groupe de capture, vous pouvez utiliser \2
et \3
et ainsi de suite.)
Les substitutions par expression régulière sont extrêmement puissantes, et la syntaxe \1
les rend encore plus puissante. Mais combiner toute l’opération en une seule expression régulière est aussi plus difficile à lire, et cela ne correspond pas directement à la façon dont vous décrivez les règles du pluriel. Vous avez initialement posé les règles comme “si le mot se termine en S, X, ou Z, alors ajouter ES”. Si vous regardez cette fonction, vous avez deux lignes de code qui disent “si le mot se termine en S, X, ou Z, alors ajouter ES”. Il n’est pas possible d’être plus direct.
Maintenant, vous allez ajouter un niveau d’abstraction. Vous avez commencé par définir une liste de règles : si ceci, faire cela, autrement aller à la prochaine règle. Compliquons temporairement une partie du programme, ainsi vous pourrez en simplifier une autre partie.
import re
def match_sxz(noun):
return re.search('[sxz]$', noun)
def apply_sxz(noun):
return re.sub('$', 'es', noun)
def match_h(noun):
return re.search('[^aeioudgkprt]h$', noun)
def apply_h(noun):
return re.sub('$', 'es', noun)
def match_y(noun): ### (1)
return re.search('[^aeiou]y$', noun)
def apply_y(noun): ### (2)
return re.sub('y$', 'ies', noun)
def match_default(noun):
return True
def apply_default(noun):
return noun + 's'
rules = ((match_sxz, apply_sxz), ### (3)
(match_h, apply_h),
(match_y, apply_y),
(match_default, apply_default)
)
def plural(noun):
for matches_rule, apply_rule in rules: ### (4)
if matches_rule(noun):
return apply_rule(noun)
(1) Maintenant, chaque règle de correspondance est sa propre fonction qui retourne les résultats de l’appel de la fonction re.search()
.
(2) Chaque règle d’application est aussi sa propre fonction qui appelle la fonction re.sub()
pour appliquer la règle de pluriel appropriée.
(3) Au lieu d’avoir une fonction (plural()
) avec de multiple règles, vous avez la structure de données rules
qui est une séquence de paires de fonctions.
(4) Puisque les règles ont été placées dans une structure de données séparée, la nouvelle fonction plural()
peut être réduite à quelques lignes de code. En utilisant une boucle for
, vous pouvez extraire les règles de correspondance et les règles d’application deux à la fois (une de correspondance et une d’application) de la structure rules
. À la première itération de la boucle for
, matches_rule
recevra match_sxz
, et apply_rule
recevra apply_sxz
. À la seconde itération (en présumant que vous arrivez jusque là), matches_rules
sera assignée à match_h
, et apply_rule
sera assignée à apply_h
. La fonction est garantie de retourner quelque chose éventuellement, parce que la dernière règle (match_default
) retourne simplement True
, cela signifie que la règle d’application correspondante (apply_default
) sera toujours appliquée.
La raison pour laquelle cette technique fonctionne est que tout en Python est un objet, y compris les fonctions. La structure de données rules
contient des fonctions — pas des noms de fonctions, mais de vrais objets fonction. Quand ils sont assignés dans la boucle for
, alors matches_rule
et apply_rule
sont de vraies fonctions que vous pouvez appeler. À la première itération de la boucle for
, c’est équivalent à appeler matches_sxz(noun)
, et si elle retourne une correspondance, à appeler apply_sxz(noun)
.
Si cet additionnel niveau d’abstraction prête à confusion, essayez de dérouler la fonction pour voir l’équivalence. La boucle for
complète est équivalente à :
def plural(noun):
if match_sxz(noun):
return apply_sxz(noun)
if match_h(noun):
return apply_h(noun)
if match_y(noun):
return apply_y(noun)
if match_default(noun):
return apply_default(noun)
Le bénéfice ici est que la fonction plural()
est maintenant simplifiée. Elle prend une séquence de règles, définies quelque part, et les itére d’une manière générique.
Les règles peuvent être définies n’importe où, de n’importe quelle façon. La fonction plural()
ne s’en préoccupe pas.
Maintenant, est-ce qu’ajouter ce niveau d’abstraction en valait la peine ? Et bien, pas encore. Considérez ce qu’il faudrait pour ajouter une nouvelle règle à la fonction. Dans le premier exemple, cela nécessiterait d’ajouter une instruction if
à la fonction plural()
. Dans le second exemple, cela nécessiterait d’ajouter deux fonctions, match_foo()
et apply_foo()
, et puis mettre à jour la séquence rules
pour spécifier où dans la séquence les nouvelles fonctions de correspondance et d’application doivent être appelées par rapport aux autres règles.
Mais ce n’est qu’une étape dans la prochaine section. Allons-y…
Définir des fonctions nommées séparées pour chaque règle de correspondance et d’application n’est pas vraiment nécessaire. Vous ne les appelez jamais directement ; vous les ajoutez à la séquence rules
et les appelez depuis-là. De plus, chaque fonction suit l’un des deux motifs. Toutes les fonctions de correspondances appelent re.search()
et toutes les fonctions d’applications appelent re.sub()
. Examinons les motifs afin de définir de nouvelles règles plus faciles :
import re
def build_match_and_apply_functions(pattern, search, replace):
def matches_rule(word): ### (1)
return re.search(pattern, word)
def apply_rule(word): ### (2)
return re.sub(search, replace, word)
return (matches_rule, apply_rule) ### (3)
(1) build_match_and_apply_functions()
est une fonction qui construit d’autres fonction de manière dynamique. Elle prend pattern
, search
et replace
, puis définit une fonction matches_rule()
qui appelle re.search()
avec le pattern
(motif) qui a été passé à la fonction build_match_and_apply_functions()
, et (le mot) word
qui a été passé à la fonction matches_rule()
que vous construisez. Waouh.
(2) Construire la fonction d’application fonctionne de la même manière. La fonction d’application est une fonction qui prend un paramètre, et qui appelle re.sub()
avec les paramètres search
et replace
qui ont été passés à la fonction build_match_and_apply_functions()
, et (le mot) word
qui a été passé à la fonction apply_rule()
que vous construisez. Cette technique utilisant les valeurs de paramètres externes au sein d’une fonction dynamique est appelée closures. Vous définissez essentiellement des constantes au sein de la fonction d’application que vous construisez : elle prend un paramètre (word
), mais elle le traite alors avec deux autres valeurs (search
et replace
) qui ont été paramétrées quand vous avez défini la fonction application.
(3) Finalement, la fonction build_match_and_apply_functions()
retourne un tuple de deux valeurs : les deux fonctions que vous venez de créer. Les constantes que vous avez définies dans ces fonctions (pattern
dans la fonction matches_rule()
, et search
dans la fonction apply_rule()
) restent avec ces fonctions, même après que votre retour de build_match_and_apply_functions()
. C’est incroyablement cool.
Si cela prête vraiment à confusion (et cela devrait l’être, c’est bizarre), cela peut devenir plus clair en analysant comment l’utiliser.
patterns = \ ### (1)
(
('[sxz]$', '$', 'es'),
('[^aeioudgkprt]h$', '$', 'es'),
('(qu|[^aeiou])y$', 'y$', 'ies'),
('$', '$', 's') ### (2)
)
rules = [build_match_and_apply_functions(pattern, search, replace) ### (3)
for (pattern, search, replace) in patterns]
(1) Nos “règles” du pluriel sont maintenant définies comme tuple de tuples de chaînes (non pas de fonctions). La première chaîne dans chaque groupe est le motif d’expression régulière que vous utiliseriez avec re.search()
pour voir si la règle correspond. La deuxième et la troisième chaîne dans chaque groupe sont les expressions de recherche et de remplacement que vous utiliseriez avec re.sub()
pour effectivement appliquer la règle afin de transformer un nom en son pluriel.
(2) Il y a un léger changement ici, dans la règle par défaut. Dans l’exemple précédent, la fonction match_default()
retournait simplement True
, signifiant que si aucune des règles spécifiques ne correspond, le code ajouterait simplement un s
à la fin du mot donné. Cette exemple fait quelque chose de fonctionnellement équivalent. La dernière expression régulière demande si le mot a une fin ($
correspond à la fin d’une chaîne). Bien sur, chaque chaîne a une fin, même une chaîne vide, donc cette expression correspond toujours. Ainsi, elle sert le même objectif que la fonction matches_default()
qui retournait toujours True
: elle assure que si aucune règle spécifique ne correspond, le code ajoute un s
à la fin du mot donné.
(3) Cette ligne est magique. Elle prend la séquence de chaînes dans patterns
et les transforme en une séquence de fonctions. Comment ? En faisant correspondre les chaînes à la fonction build_match_and_apply_functions()
. C’est-à-dire, elle prend chaque triplet de chaînes et appelle la fonction build_match_and_apply_functions()
avec ces trois chaînes comme arguments. La fonction build_match_and_apply_functions()
retourne un tuple de deux fonctions. Cela signifie que rules
est donc fonctionnellement équivalente à l’exemple précédent : une liste de tuples où chaque tuple est une paire de fonctions. La première fonction est la fonction de correspondance qui appelle re.search()
, et la seconde fonction est la fonction d’application qui appelle re.sub()
.
Cette version du script est complétée par le point d’entrée principal, la fonction plural()
.
def plural(noun):
for matches_rule, apply_rule in rules: ### (1)
if matches_rule(noun):
return apply_rule(noun)
(1) Puisque la liste rules
est la même que dans l’exemple précédent (c’est vraiment le cas), cela ne devrait pas être surprenant que la fonction plural()
n’a pas changé du tout. Elle est complètement générique ; elle prend une liste de fonctions de règle et les appelle dans l’ordre. Elle ne se soucie pas de comment les règles sont définies. Dans l’exemple précédent, elles étaient définies comme des fonctions nommées séparées. Maintenant, elles sont construites dynamiquement en faisant correspondre la sortie de la fonction build_match_and_apply_functions()
avec une liste brute de chaînes. Cela n’a aucune d’importance ; la fonction plural()
fonctionne toujours de la même façon.
Vous avez extrait tout le code dupliqué et ajoutez assez d’abstraction pour les que les règles du pluriel soient définies dans une liste de chaînes. La prochaine étape logique est de prendre ces chaînes et de les mettre dans un fichier séparé, où elles peuvent être maintenues séparément du code qui les utilise.
En premier, créons un fichier texte qui contient les règles que vous voulez. Pas de structure de données sophistiquée, juste des chaînes délimitées par des espaces dans trois colonnes. Appelons-le plural4-rules.txt
.
[sxz]$ $ es
[^aeioudgkprt]h$ $ es
[^aeiou]y$ y$ ies
$ $ s
Maintenant regardons comment nous pouvons utiliser ce fichier de règles.
import re
def build_match_and_apply_functions(pattern, search, replace): ### (1)
def matches_rule(word):
return re.search(pattern, word)
def apply_rule(word):
return re.sub(search, replace, word)
return (matches_rule, apply_rule)
rules = []
with open('plural4-rules.txt', encoding='utf-8') as pattern_file: ### (2)
for line in pattern_file: ### (3)
pattern, search, replace = line.split(None, 3) ### (4)
rules.append(build_match_and_apply_functions( ### (5)
pattern, search, replace))
(1) La fonction build_match_and_apply_functions()
n’a pas changé. Vous utilisez toujours des closures pour construire deux fonctions dynamiquement qui utilisent les variables définies dans la fonction externe.
(2) La fonction globale open()
ouvre un fichier et retourne un objet fichier. Dans ce cas, le fichier que nous ouvrons contient les motifs de chaînes pour mettre au pluriel des noms. L’instruction with
crée ce qui est appelé un contexte : quand le bloc with
se termine, Python va automatiquement fermer le fichier, même si une exception se produit à l’intérieur du bloc with
. Vous en apprendrez plus à-propos des blocs with
et des objets fichier dans le chapitre Fichiers.
(3) L’idiome for line in <fileobject>
lit les données depuis le fichier ouvert, une ligne à la fois, et assigne le texte à la variable line
. Vous en apprendrez plus à-propos de la lecture de fichier dans le chapitre Fichiers.
(4) Chaque ligne du fichier a en fait trois valeurs, mais elles sont séparées par des espaces blancs (tabulation ou espace, cela n’a pas d’importance). Pour les séparer, utilisez la méthode de chaîne split()
. Le premier argument de la méthode split()
est None
, ce qui signifie “découpe à chaque espace blanc (tabulation ou espace, cela n’a pas d’importance).” Le second argument est 3
, ce qui signifie “découpe sur les espaces blancs 3 fois, puis laisse en l’état le reste de la ligne.” Une ligne comme [sxz]$ $ es
sera découpée en liste ['[sxz]$', '$', 'es']
, ce qui signifie que pattern
aura ‘[sxz]$
’, search
aura ‘$
’, et replace
aura ‘es
’. C’est beaucoup de puissance dans une seule petite ligne de code.
(5) Finalement, vous passez pattern
, search
, et replace
à la fonction build_match_and_apply_functions()
, qui retourne un tuple de fonctions. Vous ajouter ce tuple à la liste rules
, et rules
finit par stocker la liste des fonctions de correspondance et d’application que la fonction plural()
attend.
L’amélioration ici est que vous avez complètement séparé les règles du pluriel dans une fichier externe, ainsi il peut être maintenu séparément du code qui l’utilise. Le code avec le code, les données avec les données, et tout va bien.
Est-ce que ce ne serait pas grandiose d’avoir une fonction générique plural()
qui analyse le fichier de règles ? Récupère les règles, cherche une correspondance, applique la transformation appropriée, va à la règle suivante. C’est tout ce que la fonction plural()
a à faire, et c’est tout ce que la fonction plural()
devrait faire.
def rules(rules_filename):
with open(rules_filename, encoding='utf-8') as pattern_file:
for line in pattern_file:
pattern, search, replace = line.split(None, 3)
yield build_match_and_apply_functions(pattern, search, replace)
def plural(noun, rules_filename='plural5-rules.txt'):
for matches_rule, apply_rule in rules(rules_filename):
if matches_rule(noun):
return apply_rule(noun)
raise ValueError('no matching rule for {0}'.format(noun))
Mais comment est-ce que ça fonctionne ? Regardons d’abord un premier exemple interactif.
>>> def make_counter(x):
… print('entering make_counter')
… while True:
… yield x ### (1)
… print('incrementing x')
… x = x + 1
…
>>> counter = make_counter(2) ### (2)
>>> counter ### (3)
<generator object at 0x001C9C10>
>>> next(counter) ### (4)
entering make_counter
2
>>> next(counter) ### (5)
incrementing x
3
>>> next(counter) ### (6)
incrementing x
4
(1) La présence du mot-clef yield
dans make_counter
signifie que ce n’est pas une fonction normale. C’est un type spécial de fonction qui génère des valeurs l’une après l’autre. Vous pouvez l’imaginez comme une fonction pouvant être interrompue et reprise. L’appeler retournera un générateur qui peut être utiliser pour générer des valeurs successives de x
.
(2) Pour créer une instance du générateur make_counter
, appelez-le juste comme une autre fonction. Notez qu’en fait cela n’exécute pas le code de la fonction. Vous pouvez le voir parce que la première ligne de la fonction make_counter
appelle print()
, mais rien n’est encore affiché.
(3) La fonction make_counter
retourne un objet générateur.
(4) La fonction next()
prend un objet générateur et retourne sa prochaine valeur. La première fois que vous appelez next()
avec le générateur counter
, elle exécute le code dans make_counter
jusqu’à la première instruction yield
, puis retourne la valeur qui a été générée. Dans ce cas, ce sera 2
, car vous avez initialement créé le générateur en appelant make_counter(2)
.
(5) Appeler de façon répétitive next()
avec le mème objet générateur reprend exactement là où il s’était arrêté et continue jusqu’à ce qu’il rencontre la prochaine instruction yield
. Toutes les variables, état local, etc, sont sauvegardées à yield
et rétablies à next()
. La prochaine ligne de code attendant d’être exécutée appelle print()
, qui affiche incrementing x
. Après cela, l’instruction x = x + 1
. Puis elle boucle à nouveau au travers de la boucle while
, et la première chose recontrée est l’instruction yield x
, qui sauvegarde l’état de toute chose et retourne la valeur courante de x
(maintenant 3
).
(6) La deuxième fois que vous appelez next()
, vous faites à nouveau les même choses, mais cette fois x
vaut 4
.
Puisque make_counter
définit une boucle infinie, vous pouvez théoriquement faire cela pour toujours, et ça continuerait juste d’incrémenter x
et de cracher des valeurs. Mais regardons plutôt des utilisations plus productives des générateurs.
“yield” met en pause une fonction. “next()” la reprend où elle s’était interrompue.
def fib(max):
a, b = 0, 1 ### (1)
while a < max:
yield a ### (2)
a, b = b, a + b ### (3)
(1) La séquence de Fibonacci est une séquence de nombres où chaque nombre est la somme des deux nombres qui le précèdent. Elle commence avec 0
et 1
, progresse doucement d’abord, puis de plus en plus rapidement. Pour commencer la séquence, vous avez besoin de deux variables : a
commence à 0
, et b
commence à 1
.
(2) Générons a
qui est le nombre courant dans la séquence.
(3) Assignons b
, qui est le prochain nombre dans la séquence, à a
, mais calculons aussi la prochaine valeur (a + b)
et assignons-la à b
pour l’utiliser plus tard. Notez que cela se produit en parallèle ; si a
vaut 3
et b
vaut 5
, alors a, b = b, a + b
paramètrera 5
à a
(la précédente valeur de b
) et 8
à b
(la somme des précédentes valeurs de a
et b
).
Donc vous avez une fonction qui restitue les nombres Fibonacci successifs. Bien sur, vous pouvez faire cela avec la récursion, mais cette manière est plus facile à lire. De même, cela fonctionne bien avec les boucles for
.
>>> from fibonacci import fib
>>> for n in fib(1000): ### (1)
… print(n, end=' ') ### (2)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> list(fib(1000)) ### (3)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
(1) Vous pouvez utiliser un générateur tel que fib()
directement dans la boucle for
. La boucle for
appellera automatiquement la fonction next()
, récupèrera les valeurs du générateur fib()
et les assignera à la variable d’index (n
) de la boucle for
.
(2) A chaque passage dans la boucle for
, n
reçoit une nouvelle valeur de l’instruction yield
dans fib()
, tout ce que vous avez à faire est de l’afficher. Une fois que fib()
est à court de nombres (a
devient plus grand que max
, qui dans ce cas vaut 1000
), alors la boucle for
se termine normalement.
(3) C’est un idiome utile : passez un générateur à la fonction list()
, et il itérera le générateur tout entier (exactement comme la boucle for
de l’exemple précédent) et retournera une liste de toutes les valeurs.
Retournons à plural5.py
et voyons comment cette version de plural()
fonctionne.
def rules(rules_filename):
with open(rules_filename, encoding='utf-8') as pattern_file:
for line in pattern_file:
pattern, search, replace = line.split(None, 3) ### (1)
yield build_match_and_apply_functions(pattern, search, replace) ### (2)
def plural(noun, rules_filename='plural5-rules.txt'):
for matches_rule, apply_rule in rules(rules_filename): ### (3)
if matches_rule(noun):
return apply_rule(noun)
raise ValueError('no matching rule for {0}'.format(noun))
(1) Ici, pas de magie. Souvenez-vous que les lignes du fichier de règles ont trois valeurs séparées par des espaces, donc vous utilisez line.split(None, 3)
pour récupérer les trois “colonnes” et les assigner à trois variables locales.
(2) Et puis vous générez. Qu’est-ce que vous générez ? Deux fonctions, construites dynamiquement avec notre vieille amie, build_match_and_apply_functions()
, qui est identique à celle des exemples précédents. En d’autres mots, rules()
est un générateur qui crache des fonctions de correspondance et d’application à la demande.
(3) Puisque rules()
est un générateur, vous pouvez l’utiliser directement dans une boucle for
. Au premier passage dans la boucle for
, vous appellerez la fonction rules()
, qui ouvrira le fichier de motifs, lira la première ligne, construira dynamiquement une fonction de correspondance et une fonction d’application à partir des motifs de cette ligne, et générera les fonctions construites dynamiquement. Au second passage dans la boucle for
, vous reprendrez exactement là où vous avez laissé rules()
(qui était au milieu de la boucle for line in pattern_file
). La première chose qu’elle fera sera de lire la ligne suivante du fichier (qui est toujours ouvert), de construire dynamiquement une autre fonction de correspondance et une autre fonction d’application sur la base des motifs de cette ligne, et générera les deux fonctions.
Qu’avez-vous gagné par rapport à l’étape 4 ? Le temps de démarrage. À l’étape 4, quand vous importez le module plural4
, il lit tout le fichier de motifs et construit une liste de toutes les règles possibles, avant mème que ne vous pensiez à appeler la fonction plural()
. Avec les générateurs, vous pouvez tout faire de façon paresseuse : vous lisez la première règle et créez les fonctions puis les testez, et si ça fonctionne vous ne lisez même pas le reste du fichier ou créez d’autres fonctions.
Qu’avez-vous perdu ? De la performance ! Chaque fois que vous appelez la fonction plural()
, le générateur rules
recommence depuis le début — ce qui signifie ouvrir à nouveau le fichier de motifs et le lire depuis le début, une ligne à la fois.
Et si vous pouviez avoir le meilleur des deux mondes : temps de démarrage minimal (ne pas exécuter de code à import
), et performance maximale (ne pas construire les même fonctions encore et encore). Oh, et vous voulez toujours garder les règles dans un fichier séparé (parce que le code avec le code et les données avec les données), tant que vous n’avez jamais besoin de lire deux fois la même ligne.
Pour faire cela, vous allez devoir construire votre propre itérateur. Mais avant que vous fassiez cela, vous devez apprendre les classes Python.
Python inclut de nombreuses normes de programmation des structures de données, telles que list
, tuple
, dict
, et set
, dans le cadre de ses types natifs. Beaucoup d’application ne requièrent pas d’autres structures, mais quand elles le font, la bibliothèque standard fournit des versions puissantes et bien testées, prêtes à être utilisées.
Le module enum
fournit une implémentation du type enumeration qui a des capacités d’itération et de comparaison. Il peut être utilisé pour créer des symboles bien définis pour les valeurs, à la place des chaînes ou entiers littéraux.
Le module collections
inclus les implémentations de nombreuses structures de données qui étendent celles trouvées dans d’autres modules. Par exemple, Deque
est une file d’attente double, qui permet l’addition ou la suppression d’éléments à chaque extrémité. defaultdict
est un dictionnaire qui répond avec une valeur par défaut si une clé est manquante, alors que OrderedDict
se souvient de la séquence dans laquelle les éléments sont ajoutés. namedtuple
étend le tuple normal pour donner à chaque item membre un nom d’attribut en supplément de l’index numérique.
Pour de grandes quantités de données, un array
peut utiliser plus efficacement la mémoire qu’une liste. Puisqu’un array
est limité à un simple type de donnée, il peut utiliser une représentation de mémoire plus compacte qu’une list
à usage général. En même temps, les instances array
peuvent être manipulées en utilisant beaucoup des mêmes méthodes qu’une list
, ainsi il peut être possible de remplacer une list
avec un array
sans faire beaucoup de changements.
Le tri d’items dans une séquence est un aspect fondamental de la manipulation de données. La list
de Python inclus une méthode sort()
, mais parfois il est plus efficient de maintenir une liste dans un ordre trié, sans la trier à nouveau, à chaque fois que son contenu a changé.
Les fonctions dans heapq
modifient le contenu d’une liste tout en préservant l’ordre trié de la liste avec une faible surcharge.
Une autre option pour construire des listes triés ou des tableaux est bisect
. Il utilise une recherche binaire pour trouver le point d’insertion des nouveaux items, et est une alternative au tri répété d’une liste qui change fréquemment.
Bien que la list
native peut simuler une queue, en utilisant les méthodes insert()
et pop()
, ceci n’est pas sûr. Pour avoir de vraies communications ordonnées entre les threads, utilisez le module queue
. multiprocessing
inclus une version de Queue
qui fonctionne entre processus, rendant plus facile la conversion d’un programme multithread pour utiliser des processus à la place.
struct
est utile pour décoder les données d’une autre application, qui viennent peut être d’un fichier binaire ou d’un flux de données, dans les types natifs de Python pour une manipulation plus facile.
Ce chapitre couvre deux modules relatifs à la gestion de la mémoire. Pour des structures de données hautement interconnectées, telles que des graphiques et des arbres, utilisez weakref
pour maintenir des références tout en permettant que le récupérateur de mémoire nettoie les objets après qu’ils ne soient plus nécessaires. Utilisez les fonctions dans copy
pour dupliquer des structures de données et leurs contenus, incluant les copies récursives avec deepcopy()
.
Déboguer des structures de données peut consommer du temps, spécialement lorsque vous parcourez les sorties imprimées de grandes séquences ou de dictionnaires. Utilisez pprint
pour créer des représentations faciles à lire qui peuvent être imprimées dans la console ou écrites dans un fichier journal pour déboguer facilement.
Enfin, si les types disponibles ne répondent pas aux exigences, sous-classez l’un des types natifs et personnalisez-le, ou créez un nouveau type de conteneur en utilisant l’une des classes de base abstraites définies dans les collections
en tant que base de départ.
Le module enum
définit un type d’énumération avec des capacités d’itération et de comparaison. Il peut être utilisé pour créer des symboles bien définis pour des valeurs, à la place des chaînes ou entiers littéraux.
Une nouvelle énumération est définie par l’utilisation de la syntaxe class
en sous-classant Enum
et en ajoutant des attributs de classe décrivant les valeurs.
# enum_create.py
import enum
class BugStatus(enum.Enum):
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
print('\nMember name: {}'.format(BugStatus.wont_fix.name))
print('Member value: {}'.format(BugStatus.wont_fix.value))
Les membres de Enum
sont convertis en instances à mesure que la classe est analysée. Chaque instance a une propriété name
correspondant au nom de membre et une propriété value
correspondante à la valeur assignée au nom dans la définition de classe.
$ python3 enum_create.py
Member name: wont_fix
Member value: 4
Itérer sur l’énumération class
produit des membres individuels d’énumération.
# enum_iterate.py
import enum
class BugStatus(enum.Enum):
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
for status in BugStatus:
print('{:15} = {}'.format(status.name, status.value))
Les membres sont produits dans l’ordre dans lequel ils sont déclarés dans la définition de classe.
$ python3 enum_iterate.py
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
Parce que les membres d’énumération ne sont pas ordonnés, ils supportent la comparaison seulement par identité et égalité.
# enum_comparison.py
import enum
class BugStatus(enum.Enum):
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
actual_state = BugStatus.wont_fix
desired_state = BugStatus.fix_released
print('Equality:',
actual_state == desired_state,
actual_state == BugStatus.wont_fix)
print('Identity:',
actual_state is desired_state,
actual_state is BugStatus.wont_fix)
print('Ordered by value:')
try:
print('\n'.join(' ' + s.name for s in sorted(BugStatus)))
except TypeError as err:
print(' Cannot sort: {}'.format(err))
Les opérateurs de comparaison plus-grand-que et plus-petit-que soulèvent des erreurs d’exceptions TypeErrors
.
$ python3 enum_comparison.py
Equality: False True
Identity: False True
Ordered by value:
Cannot sort: '<' not supported between instances of 'BugStatus
' and 'BugStatus'
Utilisez la classe IntEnum
pour les énumérations dans laquelle les membres doivent se comporter comme des nombres - par exemple, pour supporter les comparaisons.
# enum_intenum.py
import enum
class BugStatus(enum.IntEnum):
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
print('Ordered by value:')
print('\n'.join(' ' + s.name for s in sorted(BugStatus)))
$ python3 enum_intenum.py
Ordered by value:
fix_released
fix_committed
in_progress
wont_fix
invalid
incomplete
new
Les membres d’énumération avec les mêmes valeurs sont suivis comme des références d’alias du même objet membre. Les alias n’entraînent pas la présence de valeurs répétées dans l’itérateur pour Enum
.
# enum_aliases.py
import enum
class BugStatus(enum.Enum):
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
by_design = 4
closed = 1
for status in BugStatus:
print('{:15} = {}'.format(status.name, status.value))
print('\nSame: by_design is wont_fix: ',
BugStatus.by_design is BugStatus.wont_fix)
print('Same: closed is fix_released: ',
BugStatus.closed is BugStatus.fix_released)
Parce que by_design
et closed
sont des alias pour d’autres membres, ils n’apparaissent pas séparément dans la sortie lors de l’itération de Enum
. Le nom canonique pour un membre est le premier nom attaché à la valeur.
$ python3 enum_aliases.py
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
Same: by_design is wont_fix: True
Same: closed is fix_released: True
Pour que tous les membres aient des valeurs uniques, ajoutez le décorateur @unique
à Enum
.
# enum_unique_enforce.py
import enum
@enum.unique
class BugStatus(enum.Enum):
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
# This will trigger an error with unique applied.
by_design = 4
closed = 1
Les membres qui ont des valeurs répétées déclenchent une erreur d’exception ValueError
quand la classe Enum
est interprétée.
$ python3 enum_unique_enforce.py
Traceback (most recent call last):
File "enum_unique_enforce.py", line 11, in <module>
class BugStatus(enum.Enum):
File ".../lib/python3.7/enum.py", line 848, in unique
(enumeration, alias_details))
ValueError: duplicate values found in <enum 'BugStatus'>:
by_design -> wont_fix, closed -> fix_released
Dans certains cas, il est plus pratique de créer des énumérations par programme, plutôt que les coder en dur dans une définition de classe. Pour ces situations, Enum
prend aussi en charge le fait de passer les noms des membres et les valeurs au constructeur de classe.
# enum_programmatic_create.py
import enum
BugStatus = enum.Enum(
value='BugStatus',
names=('fix_released fix_committed in_progress '
'wont_fix invalid incomplete new'),
)
print('Member: {}'.format(BugStatus.new))
print('\nAll members:')
for status in BugStatus:
print('{:15} = {}'.format(status.name, status.value))
L’argument value
est le nom de l’énumération, qui est utilisée pour construire la représentation des membres. L’argument names
liste les membres de l’énumération. Quand une chaîne unique est passée, elle est divisée en espaces et en virgules, et les jetons résultants sont utilisés comme noms pour les membres, auxquels sont automatiquement attribuées des valeurs commençant par 1
.
$ python3 enum_programmatic_create.py
Member: BugStatus.new
All members:
fix_released = 1
fix_committed = 2
in_progress = 3
wont_fix = 4
invalid = 5
incomplete = 6
new = 7
Pour plus de contrôles sur les valeurs associées aux membres, la chaîne names
peut être remplacée par une séquence de deux tuples ou un dictionnaire faisant correspondre des noms aux valeurs.
# enum_programmatic_mapping.py
import enum
BugStatus = enum.Enum(
value='BugStatus',
names=[
('new', 7),
('incomplete', 6),
('invalid', 5),
('wont_fix', 4),
('in_progress', 3),
('fix_committed', 2),
('fix_released', 1),
],
)
print('All members:')
for status in BugStatus:
print('{:15} = {}'.format(status.name, status.value))
Dans cet exemple, une liste de deux tuples est donnée au lieu d’une chaîne unique contenant seulement les noms des membres. Cela permet de reconstruire l’énumération BugStatus
avec les membres dans le même ordre que la version définie dans enum_create.py
.
$ python3 enum_programmatic_mapping.py
All members:
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
Les valeurs des membres d’énumération ne sont pas restreints aux entiers. En fait, tout type d’objet peut être associé avec un membre. Si la valeur est un tuple, les membres sont passés en tant qu’argument individuel à __init__()
.
# enum_tuple_values.py
import enum
class BugStatus(enum.Enum):
new = (7, ['incomplete',
'invalid',
'wont_fix',
'in_progress'])
incomplete = (6, ['new', 'wont_fix'])
invalid = (5, ['new'])
wont_fix = (4, ['new'])
in_progress = (3, ['new', 'fix_committed'])
fix_committed = (2, ['in_progress', 'fix_released'])
fix_released = (1, ['new'])
def __init__(self, num, transitions):
self.num = num
self.transitions = transitions
def can_transition(self, new_state):
return new_state.name in self.transitions
print('Name:', BugStatus.in_progress)
print('Value:', BugStatus.in_progress.value)
print('Custom attribute:', BugStatus.in_progress.transitions)
print('Using attribute:',
BugStatus.in_progress.can_transition(BugStatus.new))
Dans cet exemple, chaque valeur de membre est un tuple contenant l’ID numérique (qui peut être enregistré dans une base de données) et une liste de transitions valide, sortant de l’état actuel.
$ python3 enum_tuple_values.py
Name: BugStatus.in_progress
Value: (3, ['new', 'fix_committed'])
Custom attribute: ['new', 'fix_committed']
Using attribute: True
Pour les cas les plus complexes, les tuples peuvent devenir difficiles à manier. Puisque les valeurs des membres peuvent être n’importe quel type d’objet, les dictionnaires peuvent être utilisés pour les cas où il y a beaucoup d’attributs distincts à suivre pour chaque valeur d’énumération. Les valeurs complexes sont directement transmises à __init __ ()
en tant que seul argument autre que self
.
# enum_complex_values.py
import enum
class BugStatus(enum.Enum):
new = {
'num': 7,
'transitions': [
'incomplete',
'invalid',
'wont_fix',
'in_progress',
],
}
incomplete = {
'num': 6,
'transitions': ['new', 'wont_fix'],
}
invalid = {
'num': 5,
'transitions': ['new'],
}
wont_fix = {
'num': 4,
'transitions': ['new'],
}
in_progress = {
'num': 3,
'transitions': ['new', 'fix_committed'],
}
fix_committed = {
'num': 2,
'transitions': ['in_progress', 'fix_released'],
}
fix_released = {
'num': 1,
'transitions': ['new'],
}
def __init__(self, vals):
self.num = vals['num']
self.transitions = vals['transitions']
def can_transition(self, new_state):
return new_state.name in self.transitions
print('Name:', BugStatus.in_progress)
print('Value:', BugStatus.in_progress.value)
print('Custom attribute:', BugStatus.in_progress.transitions)
print('Using attribute:',
BugStatus.in_progress.can_transition(BugStatus.new))
Cet exemple exprime les mêmes données que l’exemple précédent, utilisant des dictionnaires plutôt que des tuples.
$ python3 enum_complex_values.py
Name: BugStatus.in_progress
Value: {'num': 3, 'transitions': ['new', 'fix_committed']}
Custom attribute: ['new', 'fix_committed']
Using attribute: True
But : Types de données de conteneur.
Le module collections
inclus les types de données de conteneur au-delà des types natifs list
, dict
et tuple
.
async
et await
La classe ChainMap
gère une séquence de dictionnaires, et recherche au-travers, dans l’ordre où ils sont donnés, pour trouver les valeurs associées aux clés. Une ChainMap
constitue un bon conteneur “contextuel”, car il peut être traité comme une pile pour laquelle des modifications sont apportées à mesure que la pile grandit, ces modifications étant à nouveau ignorées à mesure que la pile se réduit.
La ChainMap
supporte la même API qu’une dictionnaire classique pour accéder aux valeurs existantes.
# collections_chainmap_read.py
import collections
a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
m = collections.ChainMap(a, b)
print('Individual Values')
print('a = {}'.format(m['a']))
print('b = {}'.format(m['b']))
print('c = {}'.format(m['c']))
print()
print('Keys = {}'.format(list(m.keys())))
print('Values = {}'.format(list(m.values())))
print()
print('Items:')
for k, v in m.items():
print('{} = {}'.format(k, v))
print()
print('"d" in m: {}'.format(('d' in m)))
Les correspondances sous-jacentes font l’objet d’une recherche dans l’ordre dans lequel elles ont été transmises au constructeur, ainsi la valeur indiquée pour la clé c
provient du dictionnaire a
.
$ python3 collections_chainmap_read.py
Individual Values
a = A
b = B
c = C
Keys = ['b', 'c', 'a']
Values = ['B', 'C', 'A']
Items:
b = B
c = C
a = A
"d" in m: False
La ChainMap
enregistre dans son attribut maps
une liste de correspondances, sur laquelle elle fait sa recherche. Cette liste est mutable, ainsi il est possible d’ajouter de nouvelles correspondances directement ou de changer l’ordre des éléments pour contrôler la recherche et le comportement de mise à jour.
# collections_chainmap_reorder.py
import collections
a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
m = collections.ChainMap(a, b)
print(m.maps)
print('c = {}\n'.format(m['c']))
# reverse the list
m.maps = list(reversed(m.maps))
print(m.maps)
print('c = {}'.format(m['c']))
Quand la liste de correspondances est renversée, la valeur associée à c
change.
$ python3 collections_chainmap_reorder.py
[{'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'}]
c = C
[{'b': 'B', 'c': 'D'}, {'a': 'A', 'c': 'C'}]
c = D
Une ChainMap
ne met pas en cache les valeurs dans les correspondances sous-jacentes. Ainsi, si leur contenu est modifié, les résultats sont reflétés lors de l’accès à ChainMap
.
# collections_chainmap_update_behind.py
import collections
a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
m = collections.ChainMap(a, b)
print('Before: {}'.format(m['c']))
a['c'] = 'E'
print('After : {}'.format(m['c']))
Changer les valeurs associées avec les clés existantes et ajouter de nouveaux éléments fonctionne de la même manière.
$ python3 collections_chainmap_update_behind.py
Before: C
After : E
Il est également possible de définir directement des valeurs via ChainMap
, bien que seule la première correspondance de la chaîne soit réellement modifiée.
# collections_chainmap_update_directly.py
import collections
a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
m = collections.ChainMap(a, b)
print('Before:', m)
m['c'] = 'E'
print('After :', m)
print('a:', a)
Quand la nouvelle valeur est enregistrée en utilisant m
, la correspondance a
est mise à jour.
$ python3 collections_chainmap_update_directly.py
Before: ChainMap({'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})
After : ChainMap({'a': 'A', 'c': 'E'}, {'b': 'B', 'c': 'D'})
a: {'a': 'A', 'c': 'E'}
ChainMap
fournit une méthode pratique pour créer une nouvelle instance avec une correspondance supplémentaire au début de la liste des correspondances pour éviter de modifier les structures de données sous-jacentes existantes.
# collections_chainmap_new_child.py
import collections
a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
m1 = collections.ChainMap(a, b)
m2 = m1.new_child()
print('m1 before:', m1)
print('m2 before:', m2)
m2['c'] = 'E'
print('m1 after:', m1)
print('m2 after:', m2)
Ce comportement d’empilement est pratique pour utiliser les instances de ChainMap
comme contextes de modèles ou d’applications. Il est spécifiquement facile d’ajouter ou de mettre à jour des valeurs en une itération, puis d’annuler les changements pour la prochaine itération.
$ python3 collections_chainmap_new_child.py
m1 before: ChainMap({'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})
m2 before: ChainMap({}, {'a': 'A', 'c': 'C'}, {'b': 'B', 'c':
'D'})
m1 after: ChainMap({'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'})
m2 after: ChainMap({'c': 'E'}, {'a': 'A', 'c': 'C'}, {'b': 'B',
'c': 'D'})
Pour les situations où le nouveau contexte est connu ou natif à l’avance, il est aussi possible de passer une correspondance à new_child()
.
# collections_chainmap_new_child_explicit.py
import collections
a = {'a': 'A', 'c': 'C'}
b = {'b': 'B', 'c': 'D'}
c = {'c': 'E'}
m1 = collections.ChainMap(a, b)
m2 = m1.new_child(c)
print('m1["c"] = {}'.format(m1['c']))
print('m2["c"] = {}'.format(m2['c']))
Ce qui est l’équivalent de :
m2 = collections.ChainMap(c, *m1.maps)
et produit :
$ python3 collections_chainmap_new_child_explicit.py
m1["c"] = C
m2["c"] = E
Un Counter
est un conteneur qui garde une trace du nombre de fois où des valeurs équivalentes sont ajoutées. Il peut être utilisé pour implémenter les mêmes algorithmes pour lesquels d’autres langages utilisent couramment des structures de données en sacs ou en multi-ensembles.
Counter
prend en charge trois formes d’initialisation. Son constructeur peut être appelé avec une séquence d’items, un dictionnaire contenant des clés et des compteurs, ou en utilisant des arguments de mots-clés qui associent les noms de chaîne aux compteurs.
# collections_counter_init.py
import collections
print(collections.Counter(['a', 'b', 'c', 'a', 'b', 'b']))
print(collections.Counter({'a': 2, 'b': 3, 'c': 1}))
print(collections.Counter(a=2, b=3, c=1))
Les résultats des trois formes d’initialisation sont les mêmes.
$ python3 collections_counter_init.py
Counter({'b': 3, 'a': 2, 'c': 1})
Counter({'b': 3, 'a': 2, 'c': 1})
Counter({'b': 3, 'a': 2, 'c': 1})
Un Counter
vide peut être construit sans arguments et rempli via la méthode update()
.
# collections_counter_update.py
import collections
c = collections.Counter()
print('Initial :', c)
c.update('abcdaab')
print('Sequence:', c)
c.update({'a': 1, 'd': 5})
print('Dict :', c)
Les valeurs comptées sont augmentées en se basant sur les nouvelles données, plutôt que remplacées. Dans l’exemple précédent, le compteur pour a
va de 3
à 4
.
$ python3 collections_counter_update.py
Initial : Counter()
Sequence: Counter({'a': 3, 'b': 2, 'c': 1, 'd': 1})
Dict : Counter({'d': 6, 'a': 4, 'b': 2, 'c': 1})
Une fois qu’un Counter
est rempli, ses valeurs peuvent être récupérées en utilisant l’API de dictionnaire.
# collections_counter_get_values.py
import collections
c = collections.Counter('abcdaab')
for letter in 'abcde':
print('{} : {}'.format(letter, c[letter]))
Le Counter
ne soulève pas d’erreur KeyError
pour les items inconnus. Si une valeur n’est pas vue dans l’entrée (comme c’est le cas dans l’exemple avec e
), son compteur est à 0
.
$ python3 collections_counter_get_values.py
a : 3
b : 2
c : 1
d : 1
e : 0
La méthode elements()
retourne un itérateur qui produit tous les items connus de Counter
.
# collections_counter_elements.py
import collections
c = collections.Counter('extremely')
c['z'] = 0
print(c)
print(list(c.elements()))
L’ordre des éléments n’est pas garanti, et les items avec des compteurs inférieurs ou égales à zéro ne sont pas inclus.
$ python3 collections_counter_elements.py
Counter({'e': 3, 'x': 1, 't': 1, 'r': 1, 'm': 1, 'l': 1, 'y': 1,
'z': 0})
['e', 'e', 'e', 'x', 't', 'r', 'm', 'l', 'y']
Utilisez most_common()
pour produire une séquence de n
valeurs d’entrées les plus fréquemment rencontrées et de leurs compteurs respectifs.
# collections_counter_most_common.py
import collections
c = collections.Counter()
with open('/usr/share/dict/words', 'rt') as f:
for line in f:
c.update(line.rstrip().lower())
print('Most common:')
for letter, count in c.most_common(3):
print('{}: {:>7}'.format(letter, count))
Cet exemple compte les lettres apparaissant dans tous les mots du dictionnaire système pour produire une distribution de fréquence, puis imprime les trois lettres les plus courantes. Si vous omettez l’argument à most_common ()
, vous obtenez une liste de tous les éléments, par ordre de fréquence.
$ python3 collections_counter_most_common.py
Most common:
e: 235331
i: 201032
a: 199554
Les instances de Counter
supportent l’arithmétique et paramètrent des opérations pour l’agrégation des résultats. Cet exemple montre les opérateurs standards pour créer de nouvelles instances de Counter
, mais les opérateurs sur place +=
, -=
, &=
, et |=
sont aussi supportés.
# collections_counter_arithmetic.py
import collections
c1 = collections.Counter(['a', 'b', 'c', 'a', 'b', 'b'])
c2 = collections.Counter('alphabet')
print('C1:', c1)
print('C2:', c2)
print('\nCombined counts:')
print(c1 + c2)
print('\nSubtraction:')
print(c1 - c2)
print('\nIntersection (taking positive minimums):')
print(c1 & c2)
print('\nUnion (taking maximums):')
print(c1 | c2)
Chaque fois qu’un nouveau Counter
est produit par opération, chaque item avec un compteur zéro ou négatif est supprimé. Le compteur pour a
est le même dans c1
et c2
, la soustraction le laisse à zéro.
$ python3 collections_counter_arithmetic.py
C1: Counter({'b': 3, 'a': 2, 'c': 1})
C2: Counter({'a': 2, 'l': 1, 'p': 1, 'h': 1, 'b': 1, 'e': 1, 't': 1})
Combined counts:
Counter({'a': 4, 'b': 4, 'c': 1, 'l': 1, 'p': 1, 'h': 1, 'e': 1, 't': 1})
Subtraction:
Counter({'b': 2, 'c': 1})
Intersection (taking positive minimums):
Counter({'a': 2, 'b': 1})
Union (taking maximums):
Counter({'b': 3, 'a': 2, 'c': 1, 'l': 1, 'p': 1, 'h': 1, 'e': 1, 't': 1})
Le dictionnaire standard inclut la méthode setdefault()
pour récupérer une valeur et en établir une par défaut si la valeur n’existe pas. Par contraste, defaultdict
permet à l’appelant de spécifier la valeur par défaut dès l’initialisation du conteneur.
# collections_defaultdict.py
import collections
def default_factory():
return 'default value'
d = collections.defaultdict(default_factory, foo='bar')
print('d:', d)
print('foo =>', d['foo'])
print('bar =>', d['bar'])
Cette méthode fonctionne aussi dans la mesure où il est approprié que toutes les clés aient la même valeur par défaut. Elle peut être spécialement utile si la valeur par défaut est un type utilisé pour l’agrégation ou l’accumulation de valeurs, tels que list
, set
, ou même int
. La documentation standard de la bibliothèque inclus de nombreux exemples dans lesquels defaultdict
est utilisé de cette manière.
$ python3 collections_defaultdict.py
d: defaultdict(<function default_factory at 0x101341950>,
{'foo': 'bar'})
foo => bar
bar => default value
defaultdict
dans la documentation standard de la bibliothèquedefaultdict
et d’autres moyens d’initialisation des dictionnaires.Une file d’attente double, ou deque
prend en charge l’ajout ou la suppression d’éléments depuis chaque extrémité de la queue. Les piles et les files d’attente les plus couramment utilisées sont des formes dégénérées de deques où les entrées et les sorties sont restreintes à une seule extrémité.
# collections_deque.py
import collections
d = collections.deque('abcdefg')
print('Deque:', d)
print('Length:', len(d))
print('Left end:', d[0])
print('Right end:', d[-1])
d.remove('c')
print('remove(c):', d)
Puisque les deques sont un type de conteneur de séquences, ils prennent en charge certaines des opérations similaires à list
, tel que l’examen des contenus avec __getitem__()
, déterminer la longueur, et la suppression des éléments depuis le milieu de la queue par correspondance d’identité.
$ python3 collections_deque.py
Deque: deque(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
Length: 7
Left end: a
Right end: g
remove(c): deque(['a', 'b', 'd', 'e', 'f', 'g'])
Une deque peut être remplis depuis chaque extrémité, décrite à «gauche» ou à «droite» dans l’implémentation Python.
# collections_deque_populating.py
import collections
# Add to the right
d1 = collections.deque()
d1.extend('abcdefg')
print('extend :', d1)
d1.append('h')
print('append :', d1)
# Add to the left
d2 = collections.deque()
d2.extendleft(range(6))
print('extendleft:', d2)
d2.appendleft(6)
print('appendleft:', d2)
La fonction extendleft()
effectue une itération sur son entrée et effectue l’équivalent d’un appendleft()
pour chaque item. Le résultat final est que deque
contient la séquence d’entrée dans l’ordre inverse.
$ python3 collections_deque_populating.py
extend : deque(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
append : deque(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
extendleft: deque([5, 4, 3, 2, 1, 0])
appendleft: deque([6, 5, 4, 3, 2, 1, 0])
De la même manière, les éléments de deque
peuvent être consommés depuis les deux extrémités, ou de l’une, selon l’algorithme qui est appliqué.
# collections_deque_consuming.py
import collections
print('From the right:')
d = collections.deque('abcdefg')
while True:
try:
print(d.pop(), end='')
except IndexError:
break
print()
print('\nFrom the left:')
d = collections.deque(range(6))
while True:
try:
print(d.popleft(), end='')
except IndexError:
break
print()
Utilisez pop()
pour supprimer un item depuis l’extrémité «droite» de deque
et popleft()
pour prendre un item depuis l’extrémité «gauche».
$ python3 collections_deque_consuming.py
From the right:
gfedcba
From the left:
012345
Puisque les deques sont des processus sûrs (dits «thead-safe»), les contenus peuvent être consommés depuis chaque extrémité en même temps, depuis des processus séparés.
# collections_deque_both_ends.py
import collections
import threading
import time
candle = collections.deque(range(5))
def burn(direction, nextSource):
while True:
try:
next = nextSource()
except IndexError:
break
else:
print('{:>8}: {}'.format(direction, next))
time.sleep(0.1)
print('{:>8} done'.format(direction))
return
left = threading.Thread(target=burn,
args=('Left', candle.popleft))
right = threading.Thread(target=burn,
args=('Right', candle.pop))
left.start()
right.start()
left.join()
right.join()
Les processus dans cet exemple alternent entre chaque extrémité, supprimant les éléments jusqu’à ce que deque
soit vide.
$ python3 collections_deque_both_ends.py
Left: 0
Right: 4
Right: 3
Left: 1
Right: 2
Left done
Right done
Un autre aspect utile de deque
est la capacité à se retourner dans chaque direction, et ainsi à sauter par dessus certains items.
# collections_deque_rotate.py
import collections
d = collections.deque(range(10))
print('Normal :', d)
d = collections.deque(range(10))
d.rotate(2)
print('Right rotation:', d)
d = collections.deque(range(10))
d.rotate(-2)
print('Left rotation :', d)
La rotation de deque
par la droite (utilisant la rotation positive) prend les éléments depuis l’extrémité droite et les déplacer à l’extrémité gauche. Les retourner par la gauche (avec une valeur négative) prend les items depuis l’extrémité gauche et les déplacent vers l’extrémité droite. Il peut être utile de visualiser les éléments dans la deque comme étant gravés le long du bord d’un cadran.
$ python3 collections_deque_rotate.py
Normal : deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Right rotation: deque([8, 9, 0, 1, 2, 3, 4, 5, 6, 7])
Left rotation : deque([2, 3, 4, 5, 6, 7, 8, 9, 0, 1])
Une instance deque
peut être configuré avec une longueur maximale, ainsi elle ne pourra jamais grandir plus que sa taille. Quand la file d’attente atteint la taille spécifiée, les éléments existants sont abandonnés au profit des nouveaux items ajoutés. Ce comportement est pratique pour chercher les n
derniers éléments d’un flux d’une longueur indéterminé.
# collections_deque_maxlen.py
import collections
import random
# Set the random seed so we see the same output each time
# the script is run.
random.seed(1)
d1 = collections.deque(maxlen=3)
d2 = collections.deque(maxlen=3)
for i in range(5):
n = random.randint(0, 100)
print('n =', n)
d1.append(n)
d2.appendleft(n)
print('D1:', d1)
print('D2:', d2)
La longueur de la file d’attente est maintenue quelque soit l’extrémité à laquelle sont ajoutés les éléments.
$ python3 collections_deque_maxlen.py
n = 17
D1: deque([17], maxlen=3)
D2: deque([17], maxlen=3)
n = 72
D1: deque([17, 72], maxlen=3)
D2: deque([72, 17], maxlen=3)
n = 97
D1: deque([17, 72, 97], maxlen=3)
D2: deque([97, 72, 17], maxlen=3)
n = 8
D1: deque([72, 97, 8], maxlen=3)
D2: deque([8, 97, 72], maxlen=3)
n = 32
D1: deque([97, 8, 32], maxlen=3)
D2: deque([32, 8, 97], maxlen=3)
Le tuple
standard utilise les index numériques pour accéder à ses membres.
# collections_tuple.py
bob = ('Bob', 30, 'male')
print('Representation:', bob)
jane = ('Jane', 29, 'female')
print('\nField by index:', jane[0])
print('\nFields by index:')
for p in [bob, jane]:
print('{} is a {} year old {}'.format(*p))
Ce qui fait des tuples des conteneurs pratiques pour des utilisations simples.
$ python3 collections_tuple.py
Representation: ('Bob', 30, 'male')
Field by index: Jane
Fields by index:
Bob is a 30 year old male
Jane is a 29 year old female
Par contraste, se souvenir quel index utiliser pour chaque valeur peut entraîner des erreurs, spécialement si le tuple a beaucoup de champs et est construit loin de l’endroit où il est utilisé. Un namedtuple
assigne des noms, aussi bien que des index numériques, pour chaque membre.
Les instances namedtuple
sont juste plus efficient en mémoire que les tuples ordinaires car ils n’ont pas de dictionnaires par instance. Chaque type de namedtuple
est représenté par sa propre classe, qui est créée en utilisant la fonction de fabrication namedtuple()
. Les arguments sont des noms de la nouvelle classe et une chaîne contenant les noms des éléments.
# collections_namedtuple_person.py
import collections
Person = collections.namedtuple('Person', 'name age')
bob = Person(name='Bob', age=30)
print('\nRepresentation:', bob)
jane = Person(name='Jane', age=29)
print('\nField by name:', jane.name)
print('\nFields by index:')
for p in [bob, jane]:
print('{} is {} years old'.format(*p))
Comme l’exemple l’illustre, il est possible d’accéder aux champs du namedtuple
par nom en utilisant la notation (obj.attr
) aussi bien que par l’utilisation des index positionnés des tuples standards.
$ python3 collections_namedtuple_person.py
Representation: Person(name='Bob', age=30)
Field by name: Jane
Fields by index:
Bob is 30 years old
Jane is 29 years old
Tout comme un tuple
ordinaire, un namedtuple
est immuable. Cette restriction permet aux instances tuples
d’avoir une valeur de hachage cohérente, ce qui rend possible leur utilisation comme clés de dictionnaires et d’être incluses dans des ensembles.
# collections_namedtuple_immutable.py
import collections
Person = collections.namedtuple('Person', 'name age')
pat = Person(name='Pat', age=12)
print('\nRepresentation:', pat)
pat.age = 21
Essayer de changer sa valeur par son nom d’attribut résulte en une erreur AttributError
.
$ python3 collections_namedtuple_immutable.py
Representation: Person(name='Pat', age=12)
Traceback (most recent call last):
File "collections_namedtuple_immutable.py", line 17, in
<module>
pat.age = 21
AttributeError: can't set attribute
Les noms de champs sont invalides s’ils sont répétés ou en conflit avec des mots clés Python.
# collections_namedtuple_bad_fields.py
import collections
try:
collections.namedtuple('Person', 'name class age')
except ValueError as err:
print(err)
try:
collections.namedtuple('Person', 'name age age')
except ValueError as err:
print(err)
Comme les noms des champs sont analysés, les valeurs invalides causent des erreurs d’exceptions ValueError
.
$ python3 collections_namedtuple_bad_fields.py
Type names and field names cannot be a keyword: 'class'
Encountered duplicate field name: 'age'
Dans les situations où un namedtuple
est créé sur la base des valeurs en-dehors du contrôle du programme (telle que représenter les lignes renvoyées par une requête de base de données, lorsque le schéma n’est pas connu à l’avance), l’option rename
doit être paramétrée à True
pour que les champs invalides soient renommés.
# collections_namedtuple_rename.py
import collections
with_class = collections.namedtuple(
'Person', 'name class age',
rename=True)
print(with_class._fields)
two_ages = collections.namedtuple(
'Person', 'name age age',
rename=True)
print(two_ages._fields)
Les nouveaux noms des champs renommés dépendent de leur index dans le tuple, ainsi le champ avec le nom class
devient _1
et le champ dupliqué age
est changé en _2
.
$ python3 collections_namedtuple_rename.py
('name', '_1', 'age')
('name', 'age', '_2')
namedtuple
fournit de nombreux attributs et méthodes pratiques pour travailler avec les sous-classes et les instances. Toutes ces propriétés natives ont des noms préfixés avec un tiret bas (_
), qui par convention dans la plupart des programmes Python indique un attribut privé. Pour namedtuple
, cependant, le préfixe est intentionnel pour protéger le nom d’une collision avec les noms d’attributs fournis par utilisateur.
Les noms de ces champs passés à namedtuple
pour définir de nouvelle classe sont sauvegardés sont l’attribut _fields
.
# collections_namedtuple_fields.py
import collections
Person = collections.namedtuple('Person', 'name age')
bob = Person(name='Bob', age=30)
print('Representation:', bob)
print('Fields:', bob._fields)
Bien que l’argument soit une seule chaîne séparée par des espaces, la valeur enregistrée est la séquence de noms individuels.
$ python3 collections_namedtuple_fields.py
Representation: Person(name='Bob', age=30)
Fields: ('name', 'age')
Les instances namedtuple
peuvent être converties en instances OrderedDict
par l’usage de _asdict()
.
# collections_namedtuple_asdict.py
import collections
Person = collections.namedtuple('Person', 'name age')
bob = Person(name='Bob', age=30)
print('Representation:', bob)
print('As Dictionary:', bob._asdict())
Les clés de OrderedDict
sont dans le même ordre que les champs du namedtuple
.
$ python3 collections_namedtuple_asdict.py
Representation: Person(name='Bob', age=30)
As Dictionary: OrderedDict([('name', 'Bob'), ('age', 30)])
La méthode _replace()
construit une nouvelle instance, en remplaçant les valeur de certains champs dans le processus.
# collections_namedtuple_replace.py
import collections
Person = collections.namedtuple('Person', 'name age')
bob = Person(name='Bob', age=30)
print('\nBefore:', bob)
bob2 = bob._replace(name='Robert')
print('After:', bob2)
print('Same?:', bob is bob2)
Bien que le nom implique que l’objet existant ait été modifié, parce que les instances namedtuple
sont immuables, la méthode retourne actuellement un nouvel objet.
$ python3 collections_namedtuple_replace.py
Before: Person(name='Bob', age=30)
After: Person(name='Robert', age=30)
Same?: False
Un OrderedDict
est une sous-classe de dictionnaire qui se souvient de l’ordre dans lequel son contenu est ajouté.
# collections_ordereddict_iter.py
import collections
print('Regular dictionary:')
d = {}
d['a'] = 'A'
d['b'] = 'B'
d['c'] = 'C'
for k, v in d.items():
print(k, v)
print('\nOrderedDict:')
d = collections.OrderedDict()
d['a'] = 'A'
d['b'] = 'B'
d['c'] = 'C'
for k, v in d.items():
print(k, v)
Avant Python 3.6 un dict
ordinaire ne piste pas l’ordre d’insertion, et itère dessus les valeurs produites dans l’ordre en fonction de la manière dont les clés étaient stockées dans la table de hachage, qui à son tour, est influencé par une valeur aléatoire pour réduire les collisions. Dans un OrderedDict
, par contraste, l’ordre dans lequel les éléments sont insérés est retenu et utilisé lors de la création de l’itérateur.
$ python3.5 collections_ordereddict_iter.py
Regular dictionary:
c C
b B
a A
OrderedDict:
a A
b B
c C
Sous Python 3.6, le natif dict
piste l’ordre d’insertion, bien que ce comportement soit l’un des effets secondaires d’un changement d’implémentation, il ne faut pas s’y fier.
$ python3.6 collections_ordereddict_iter.py
Regular dictionary:
a A
b B
c C
OrderedDict:
a A
b B
c C
Un dict
ordinaire cherche son contenu lorsqu’il teste l’égalité. Un OrderedDict
considère lui aussi l’ordre dans lequel les items sont ajoutés.
# collections_ordereddict_equality.py
import collections
print('dict :', end=' ')
d1 = {}
d1['a'] = 'A'
d1['b'] = 'B'
d1['c'] = 'C'
d2 = {}
d2['c'] = 'C'
d2['b'] = 'B'
d2['a'] = 'A'
print(d1 == d2)
print('OrderedDict:', end=' ')
d1 = collections.OrderedDict()
d1['a'] = 'A'
d1['b'] = 'B'
d1['c'] = 'C'
d2 = collections.OrderedDict()
d2['c'] = 'C'
d2['b'] = 'B'
d2['a'] = 'A'
print(d1 == d2)
Dans ce cas, puisque deux dictionnaires ordonnés sont créés depuis des valeurs dans un ordre différent, ils sont considérés différents.
$ python3 collections_ordereddict_equality.py
dict : True
OrderedDict: False
Il est possible de changer l’ordre des clés dans un OrderedDict
en les bougeant selon le début ou la fin de la séquence en utilisant move_to_end()
.
# collections_ordereddict_move_to_end.py
import collections
d = collections.OrderedDict(
[('a', 'A'), ('b', 'B'), ('c', 'C')]
)
print('Before:')
for k, v in d.items():
print(k, v)
d.move_to_end('b')
print('\nmove_to_end():')
for k, v in d.items():
print(k, v)
d.move_to_end('b', last=False)
print('\nmove_to_end(last=False):')
for k, v in d.items():
print(k, v)
Le dernier argument demande à move_to_end()
de bouger l’élément afin de devenir le dernier dans la séquence de clé (quand True
) ou le premier (quand False
).
$ python3 collections_ordereddict_move_to_end.py
Before:
a A
b B
c C
move_to_end():
a A
c C
b B
move_to_end(last=False):
b B
a A
c C
But : Classes de bases abstraites pour types de données de conteneur.
Le module collections.abc
contient des classes de base abstraites qui définissent les API pour les structures de conteneur de données natives dans Python et fournies dans le module collections
. Référez-vous à la table ci-dessous pour la liste des classes et leur but.
+——————–+——————————+——————————————————————————————————————-+
| Classe | Classe(s) de Base | But de l’API |
+——————–+——————————+——————————————————————————————————————-+
| Container | | Fonctionnalités de base de conteneur, tel que l’opérateur inc
. |
| Hashable | | Ajoute le support de fourniture d’une valeur de hachage pour l’instance du conteneur. |
| Iterable | | Peut créer un itérateur sur le contenu du conteneur. |
| Iterator | Iterable | Est un itérateur sur le contenu du conteneur. |
| Generator | Iterator | Étend les itérateurs avec le protocole générateur du PEP 342. |
| Sized | | Ajoute les méthodes de conteneurs pour connaître la grosseur de leur taille. |
| Callable | | Pour les conteneurs invoqués en tant que fonction. |
| Sequence | Sized, Iterable, Container | Prend en charge la récupération d’éléments individuels, l’itération et la modification de l’ordre des éléments. |
| MutableSequence | Sequence | Prend en charge l’ajout et la suppression des éléments d’une instance après qu’ils soient créés. |
| ByteString | Sequence | API combinées de bytes
et de bytearray
. |
| Set | Sized, Iterable, Container | Prend en charges les opérations d’ensemble telles que l’intersection et l’union. |
| MutableSet | Set | Ajoute les méthodes de manipulation pour le contenu d’ensemble après qu’il soit créé. |
| Mapping | Sized, Iterable, Container | Définit l’API en lecture seule utilisé par dict
. |
| MutableMapping | Mapping | Définit les méthodes de manipulation des contenus pour la correspondance après qu’ils soient créés. |
| MappingView | Sized | Définit la vue de l’API pour l’accès à la correspondance depuis un itérateur. |
| ItemsView | MappingView, Set | Partie de la vue de l’API. |
| KeysView | MappingView, Set | Partie de la vue de l’API. |
| ValuesView | MappingView | Partie de la vue de l’API. |
| Awaitable | | API pour les objets qui peuvent être utilisés dans des expressions await
, telles que des coroutines. |
| Coroutine | Awaitable | API pour les classes qui implémentent le protocole coroutine. |
| AsyncIterable | | API pour les itérables compatibles avec async for
, telle que définit dans la PEP 492. |
| AsyncIterator | AsyncIterable | API pour les itérateurs asynchrones. |
+——————–+——————————+——————————————————————————————————————-+
En plus de définir clairement les API pour les conteneurs avec des sémantiques différentes, ces classes de base abstraites peuvent être utilisées pour tester n’importe quel objet qui prend en charge une API avant de l’invoquer par l’usage d’ isinstance()
. Certaines de ces classes fournissent aussi des implémentations de méthodes, et elles peuvent être utilisées comme mixages(?) pour créer des types de conteneurs personnalisés sans implémenter chaque méthode à partir de rien.
But : Gérer efficacement des séquences de données numériques de type fixé.
Le module array
définit une structure de données de séquence qui ressemble beaucoup à une list
, excepté que tous les membres doivent être du même type primitif. Les types supportés sont tous les types numériques ou les autres primitifs de taille fixée, tels que les bytes
.
Référez-vous à la table ci-dessous pour connaître certains des types supportés. La documentation de la bibliothèque standard pour array
inclus une liste complète des codes de types.
+———-+———————-+—————————–+ | Code | Type | Taille minimal (octets) | +———-+———————-+—————————–+ | b | int | 1 | | B | int | 1 | | h | signed short | 2 | | H | unsigned short | 2 | | i | signed int | 2 | | I | unsigned int | 2 | | l | signed long | 4 | | L | unsigned long | 4 | | q | signed long long | 8 | | Q | unsigned long long | 8 | | f | float | 4 | | d | double float | 8 | +———-+———————-+—————————–+
Un array
est instancié avec un argument décrivant le type de donnée à allouer, et si possible une séquence initiale de données à enregistrer dans le tableau.
# array_string.py
import array
import binascii
s = b'This is the array.'
a = array.array('b', s)
print('As byte string:', s)
print('As array :', a)
print('As hex :', binascii.hexlify(a))
Dans cet exemple, le tableau est configuré pour capturer une séquence d’octets et est initialisé avec une simple chaîne d’octets.
$ python3 array_string.py
As byte string: b'This is the array.'
As array : array('b', [84, 104, 105, 115, 32, 105, 115, 32,
116, 104, 101, 32, 97, 114, 114, 97, 121, 46])
As hex : b'54686973206973207468652061727261792e'
Un array
peut être étendu ou autrement manipulé de la même manière que les autres séquences Python.
# array_sequence.py
import array
import pprint
a = array.array('i', range(3))
print('Initial :', a)
a.extend(range(3))
print('Extended:', a)
print('Slice :', a[2:5])
print('Iterator:')
print(list(enumerate(a)))
Les opérations supportées incluent le découpage, l’itération, et l’ajout d’éléments à la fin.
$ python3 array_sequence.py
Initial : array('i', [0, 1, 2])
Extended: array('i', [0, 1, 2, 0, 1, 2])
Slice : array('i', [2, 0, 1])
Iterator:
[(0, 0), (1, 1), (2, 2), (3, 0), (4, 1), (5, 2)]
Le contenu d’un tableau peut être écrit et lit depuis et vers des fichiers en utilisant des méthodes natives codées efficacement dans ce but.
# array_file.py
import array
import binascii
import tempfile
a = array.array('i', range(5))
print('A1:', a)
# Write the array of numbers to a temporary file
output = tempfile.NamedTemporaryFile()
a.tofile(output.file) # must pass an *actual* file
output.flush()
# Read the raw data
with open(output.name, 'rb') as input:
raw_data = input.read()
print('Raw Contents:', binascii.hexlify(raw_data))
# Read the data into an array
input.seek(0)
a2 = array.array('i')
a2.fromfile(input, len(a))
print('A2:', a2)
Cet exemple illustre la lecture de donnée «brute», venant directement depuis le fichier binaire, versus la lecture dans un autre tableau et convertissant les octets dans les types appropriés.
$ python3 array_file.py
A1: array('i', [0, 1, 2, 3, 4])
Raw Contents: b'0000000001000000020000000300000004000000'
A2: array('i', [0, 1, 2, 3, 4])
tofile()
utilise tobytes()
pour formater les données, et fromfile()
utilise frombytes()
pour les convertir à nouveau en une instance de tableau.
# array_tobytes.py
import array
import binascii
a = array.array('i', range(5))
print('A1:', a)
as_bytes = a.tobytes()
print('Bytes:', binascii.hexlify(as_bytes))
a2 = array.array('i')
a2.frombytes(as_bytes)
print('A2:', a2)
Les deux fonctions tobytes()
et frombytes()
fonctionnent sur des chaînes d’octets, et non pas des chaînes Unicode.
$ python3 array_tobytes.py
A1: array('i', [0, 1, 2, 3, 4])
Bytes: b'0000000001000000020000000300000004000000'
A2: array('i', [0, 1, 2, 3, 4])
Si la donnée dans le tableau n’est pas de l’ordre natif d’octet, ou si la donnée nécessite d’être échangée avant d’être envoyée au système avec un ordre d’octet différent (ou sur le réseau), il est possible de convertir un tableau entier sans itérer les éléments dans Python.
# array_byteswap.py
import array
import binascii
def to_hex(a):
chars_per_item = a.itemsize * 2 # 2 hex digits
hex_version = binascii.hexlify(a)
num_chunks = len(hex_version) // chars_per_item
for i in range(num_chunks):
start = i * chars_per_item
end = start + chars_per_item
yield hex_version[start:end]
start = int('0x12345678', 16)
end = start + 5
a1 = array.array('i', range(start, end))
a2 = array.array('i', range(start, end))
a2.byteswap()
fmt = '{:>12} {:>12} {:>12} {:>12}'
print(fmt.format('A1 hex', 'A1', 'A2 hex', 'A2'))
print(fmt.format('-' * 12, '-' * 12, '-' * 12, '-' * 12))
fmt = '{!r:>12} {:12} {!r:>12} {:12}'
for values in zip(to_hex(a1), a1, to_hex(a2), a2):
print(fmt.format(*values))
La méthode byteswap()
échange l’ordre d’octet des éléments dans le tableau depuis le langage C, qui est plus efficace pour boucler sur les données en Python.
$ python3 array_byteswap.py
A1 hex A1 A2 hex A2
------------ ------------ ------------ ------------
b'78563412' 305419896 b'12345678' 2018915346
b'79563412' 305419897 b'12345679' 2035692562
b'7a563412' 305419898 b'1234567a' 2052469778
b'7b563412' 305419899 b'1234567b' 2069246994
b'7c563412' 305419900 b'1234567c' 2086024210
array
struct
.But : Heapq implémente un algorithme de tri minitas(?) approprié pour utiliser les listes Python.
Un heap
est tel une arborescence de structure de données dans laquelle les nœuds enfants ont une relation d’ordre trié avec les nœuds parents. Le binary heaps
peut être représenté en utilisant une liste ou un tableau organisé afin que les nœuds enfants d’élément N
soient à la position 2 * N + 1 et 2 * N + 2 (pour les index basés sur zéro). Ce calque rend cela possible en réarrangeant le tas en place, ainsi il est n’est pas nécessaire de ré-allouer beaucoup de mémoire lors de l’ajout ou de la suppression d’items.
Un max-heap s’assure que le nœud parent est plus large que ou égal à deux de ces enfants. Un min-heap requiert que le nœud parent soit plus petit ou égal à ces nœuds enfants. Le module Python heapq
implémente un min-heap.
Cet exemple dans ce chapitre utilise la donnée dans le script heapq_heapdata.py
.
# heapq_heapdata.py
# This data was generated with the random module.
data = [19, 9, 4, 10, 11]
La sortie du tas est imprimé en utilisant le script heapq_showtree.py
.
# heapq_showtree.py
import math
from io import StringIO
def show_tree(tree, total_width=36, fill=' '):
"""Pretty-print a tree."""
output = StringIO()
last_row = -1
for i, n in enumerate(tree):
if i:
row = int(math.floor(math.log(i + 1, 2)))
else:
row = 0
if row != last_row:
output.write('\n')
columns = 2 ** row
col_width = int(math.floor(total_width / columns))
output.write(str(n).center(col_width, fill))
last_row = row
print(output.getvalue())
print('-' * total_width)
print()
Il y a deux manières de base de créer un heap : heappush()
et heapify()
.
# heapq_heappush.py
import heapq
from heapq_showtree import show_tree
from heapq_heapdata import data
heap = []
print('random :', data)
print()
for n in data:
print('add {:>3}:'.format(n))
heapq.heappush(heap, n)
show_tree(heap)
Quand heappush()
est utilisé, l’ordre de tri du tas des éléments est maintenu lorsque de nouveaux éléments sont ajoutés à partir d’une source de données.
$ python3 heapq_heappush.py
random : [19, 9, 4, 10, 11]
add 19:
19
------------------------------------
add 9:
9
19
------------------------------------
add 4:
4
19 9
------------------------------------
add 10:
4
10 9
19
------------------------------------
add 11:
4
10 9
19 11
------------------------------------
Si la donnée est toujours en mémoire, il est plus efficient d’utiliser heapify()
pour réarranger les items dans la liste.
# heapq_heapify.py
import heapq
from heapq_showtree import show_tree
from heapq_heapdata import data
print('random :', data)
heapq.heapify(data)
print('heapified :')
show_tree(data)
Le résultat d’une construction d’une liste dans un ordre heap, un item à la fois, est le même que le fait de construire une liste non ordonnée en appelant heapify()
.
$ python3 heapq_heapify.py
random : [19, 9, 4, 10, 11]
heapified :
4
9 19
10 11
------------------------------------
Une fois que le heap est organisé correctement, utilisez heappop()
pour supprimer l’élément ayant la valeur la plus petite.
# heapq_heappop.py
import heapq
from heapq_showtree import show_tree
from heapq_heapdata import data
print('random :', data)
heapq.heapify(data)
print('heapified :')
show_tree(data)
print()
for i in range(2):
smallest = heapq.heappop(data)
print('pop {:>3}:'.format(smallest))
show_tree(data)
Dans cet exemple, adapté de la documentation de la bibliothèque standard, heapify()
et heappop()
sont utilisées pour trier une liste de nombres.
$ python3 heapq_heappop.py
random : [19, 9, 4, 10, 11]
heapified :
4
9 19
10 11
------------------------------------
pop 4:
9
10 19
11
------------------------------------
pop 9:
10
11 19
------------------------------------
Pour supprimer des éléments existants et les remplacer par de nouvelles valeurs en une unique opération, utilisez heapreplace()
.
# heapq_heapreplace.py
import heapq
from heapq_showtree import show_tree
from heapq_heapdata import data
heapq.heapify(data)
print('start:')
show_tree(data)
for n in [0, 13]:
smallest = heapq.heapreplace(data, n)
print('replace {:>2} with {:>2}:'.format(smallest, n))
show_tree(data)
Remplacer des éléments rend possible de maintenir un heap de taille fixée, tel qu’une file de travaux ordonnés par priorité.
$ python3 heapq_heapreplace.py
start:
4
9 19
10 11
------------------------------------
replace 4 with 0:
0
9 19
10 11
------------------------------------
replace 0 with 13:
9
10 19
13 11
------------------------------------
heapq
inclus aussi deux fonctions qui examine un itérable et trouve une rangée des valeurs les plus grandes ou les plus petites qu’il contient.
# heapq_extremes.py
import heapq
from heapq_heapdata import data
print('all :', data)
print('3 largest :', heapq.nlargest(3, data))
print('from sort :', list(reversed(sorted(data)[-3:])))
print('3 smallest:', heapq.nsmallest(3, data))
print('from sort :', sorted(data)[:3])
Utiliser nlargest()
et nsmallest()
est efficace seulement pour les valeurs relativement petites de n > 1, mais peut toujours devenir plus pratique dans quelques cas.
$ python3 heapq_extremes.py
all : [19, 9, 4, 10, 11]
3 largest : [19, 11, 10]
from sort : [19, 11, 10]
3 smallest: [4, 9, 10]
from sort : [4, 9, 10]
Combiner de nombreuses séquences triées en une nouvelle séquence est facile pour de petits ensembles de données.
python list(sorted(itertools.chain(*data)))
Pour de plus grand ensembles de données, cette technique peut utiliser une somme considérable de mémoire. Au lieu de trier la séquence triée en entier, merge()
utilise un tas pour générer un nouvelle séquence une à la fois, déterminant le nouvel item en utilisant une somme de mémoire fixée.
# heapq_merge.py
import heapq
import random
random.seed(2016)
data = []
for i in range(4):
new_data = list(random.sample(range(1, 101), 5))
new_data.sort()
data.append(new_data)
for i, d in enumerate(data):
print('{}: {}'.format(i, d))
print('\nMerged:')
for i in heapq.merge(*data):
print(i, end=' ')
print()
Puisque l’implémentation de merge()
utilise un tas, il consomme la mémoire basée sur le nombre de séquences à fusionner, plutôt que le nombre des éléments dans ces séquences.
$ python3 heapq_merge.py
0: [33, 58, 71, 88, 95]
1: [10, 11, 17, 38, 91]
2: [13, 18, 39, 61, 63]
3: [20, 27, 31, 42, 45]
Merged:
10 11 13 17 18 20 27 31 33 38 39 42 45 58 61 63 71 88 91 95
Queue
dans la bibliothèque standard.But : Maintenir une liste dans un ordre trié sans avoir à appeler le tri chaque fois qu’un item est ajouté à la liste.
Le module bisect
implémente un algorithme pour insérer des éléments dans une liste tout en maintenant la liste dans un ordre trié.
Voici un exemple dans lequel insort()
est utilisé pour insérer des items dans la liste en ordre trié.
# bisect_example.py
import bisect
# A series of random numbers
values = [14, 85, 77, 26, 50, 45, 66, 79, 10, 3, 84, 77, 1]
print('New Pos Contents')
print('--- --- --------')
l = []
for i in values:
position = bisect.bisect(l, i)
bisect.insort(l, i)
print('{:3} {:3}'.format(i, position), l)
La première colonne de sortie montre un nouveau nombre aléatoire. La seconde colonne montre la position où le nombre sera inséré dans la liste. Le reste de chaque ligne est la liste triée actuelle.
$ python3 bisect_example.py
New Pos Contents
--- --- --------
14 0 [14]
85 1 [14, 85]
77 1 [14, 77, 85]
26 1 [14, 26, 77, 85]
50 2 [14, 26, 50, 77, 85]
45 2 [14, 26, 45, 50, 77, 85]
66 4 [14, 26, 45, 50, 66, 77, 85]
79 6 [14, 26, 45, 50, 66, 77, 79, 85]
10 0 [10, 14, 26, 45, 50, 66, 77, 79, 85]
3 0 [3, 10, 14, 26, 45, 50, 66, 77, 79, 85]
84 9 [3, 10, 14, 26, 45, 50, 66, 77, 79, 84, 85]
77 8 [3, 10, 14, 26, 45, 50, 66, 77, 77, 79, 84, 85]
1 0 [1, 3, 10, 14, 26, 45, 50, 66, 77, 77, 79, 84, 85]
Ceci est un simple exemple. En fait, compte tenu de la quantité de données manipulées, il est plus rapide de simplifier la construction de la liste et la trier en une fois. Par contraste, pour des listes longues, des économies de temps et de mémoire considérables peuvent être obtenues à l’aide d’un algorithme de tri par insertion tel que celui-ci, spécialement quand l’opération comparant deux membres d’une liste requiert de coûteux calculs.
Le résultat de l’ensemble montré précédemment inclus une valeur répétée, 77
. Le module bisect
fournit deux manière de traiter les répétitions : les nouvelles valeurs peuvent être insérées soit à la gauche des valeurs existantes, soit à la droite. La fonction insort()
est actuellement un alias de insort_right()
, qui insère un item après une valeur existante. La fonction correspondante insort_left()
insère un item avant la valeur existante.
# bisect_example2.py
import bisect
# A series of random numbers
values = [14, 85, 77, 26, 50, 45, 66, 79, 10, 3, 84, 77, 1]
print('New Pos Contents')
print('--- --- --------')
# Use bisect_left and insort_left.
l = []
for i in values:
position = bisect.bisect_left(l, i)
bisect.insort_left(l, i)
print('{:3} {:3}'.format(i, position), l)
Quand la même donnée est manipulée par l’utilisation des fonctions bisect_left()
et insort_left()
, il en résulte la même liste triée mais l’insertion des positions est différente pour les valeurs dupliquées.
$ python3 bisect_example2.py
New Pos Contents
--- --- --------
14 0 [14]
85 1 [14, 85]
77 1 [14, 77, 85]
26 1 [14, 26, 77, 85]
50 2 [14, 26, 50, 77, 85]
45 2 [14, 26, 45, 50, 77, 85]
66 4 [14, 26, 45, 50, 66, 77, 85]
79 6 [14, 26, 45, 50, 66, 77, 79, 85]
10 0 [10, 14, 26, 45, 50, 66, 77, 79, 85]
3 0 [3, 10, 14, 26, 45, 50, 66, 77, 79, 85]
84 9 [3, 10, 14, 26, 45, 50, 66, 77, 79, 84, 85]
77 7 [3, 10, 14, 26, 45, 50, 66, 77, 77, 79, 84, 85]
1 0 [1, 3, 10, 14, 26, 45, 50, 66, 77, 77, 79, 84, 85]
But : Fournir une implémentation FIFO de processus sûrs.
Le module queue
fournit une structure de données premier entré, premier sorti (FIFO) adaptée à la programmation multithread. Elle peut être utilisée pour passer des messages ou d’autres choses en toute sécurité entre les threads producteur et consommateur. Le verrouillage est géré pour l’appelant. Ainsi, de nombreux threads peuvent fonctionner avec la même instance de Queue
facilement et en toute sécurité. La taille de la Queue
(le nombre des éléments qu’elle contient) peut être restreinte à l’utilisation ou au traitement de la mémoire.
Note Cette discussion présume que vous comprenez la nature générale d’une file d’attente. Si ce n’est pas le cas, vous devriez lire certaines références avant de continuer.
La classe Queue
implémente un conteneur premier entré, premier sorti de base. Les éléments sont ajoutés à la «fin» de la séquence en utilisant la fonction put()
, et supprimé à la fin d’une autre par l’utilisation de get()
.
# queue_fifo.py
import queue
q = queue.Queue()
for i in range(5):
q.put(i)
while not q.empty():
print(q.get(), end=' ')
print()
Cet exemple utilise un unique thread pour illustrer comment les éléments sont supprimés de la file d’attente, dans le même ordre dans lequel ils ont été insérés.
$ python3 queue_fifo.py
0 1 2 3 4
Par contraste à l’implémentation standard FIFO de Queue
, la LifoQueue
utilise l’ordre dernier entré, premier sorti (normalement associé à la pile de la structure de données).
# queue_lifo.py
import queue
q = queue.LifoQueue()
for i in range(5):
q.put(i)
while not q.empty():
print(q.get(), end=' ')
print()
L’élément le plus récemment entré dans la file d’attente est supprimé par get
.
$ python3 queue_lifo.py
4 3 2 1 0
Parfois, l’ordre de traitement des éléments d’une file d’attente doit être basé sur les caractéristiques de ces éléments, plutôt que sur l’ordre dans lequel ils ont été créés ou ajoutés à la file d’attente. Par exemple, les travaux d’impression du service de la comptabilité peuvent avoir priorité sur une liste de codes qu’un développeur souhaite imprimer. PriorityQueues
utilise l’ordre de tri de la file d’attente pour décider quel élément est à récupérer.
# queue_priority.py
import functools
import queue
import threading
@functools.total_ordering
class Job:
def __init__(self, priority, description):
self.priority = priority
self.description = description
print('New job:', description)
return
def __eq__(self, other):
try:
return self.priority == other.priority
except AttributeError:
return NotImplemented
def __lt__(self, other):
try:
return self.priority < other.priority
except AttributeError:
return NotImplemented
q = queue.PriorityQueue()
q.put(Job(3, 'Mid-level job'))
q.put(Job(10, 'Low-level job'))
q.put(Job(1, 'Important job'))
def process_job(q):
while True:
next_job = q.get()
print('Processing job:', next_job.description)
q.task_done()
workers = [
threading.Thread(target=process_job, args=(q,)),
threading.Thread(target=process_job, args=(q,)),
]
for w in workers:
w.setDaemon(True)
w.start()
q.join()
Cet exemple comporte de multiples threads consommant les travaux, qui sont traités en fonction de la priorité des éléments dans la file d’attente au moment où get()
est appelé. L’ordre de traitement des éléments ajoutés à la file d’attente, pendant l’exécution des threads consommateurs, dépend du basculement du contexte du thread.
$ python3 queue_priority.py
New job: Mid-level job
New job: Low-level job
New job: Important job
Processing job: Important job
Processing job: Mid-level job
Processing job: Low-level job
Le code source pour un client de podcast dans ce chapitre démontre comment utiliser la classe Queue
avec de multiples threads. Le programme lit un ou plusieurs flux RSS, met en file d’attente les pièces jointes des cinq derniers épisodes de chaque flux à télécharger et traite plusieurs téléchargements en parallèle à l’aide de threads. La gestion des erreurs n’est pas suffisante pour une utilisation en production, mais l’implémentation du squelette illustre l’utilisation du module queue
.
En premier, certains paramètres de fonctionnement sont établis. Habituellement, ce sont des entrées d’utilisateur (p.ex. : des préférences ou d’une base de données). L’exemple utilise des valeurs codées en dur pour le nombre des threads et la liste des URL à récupérer.
# fetch_podcasts.py
from queue import Queue
import threading
import time
import urllib
from urllib.parse import urlparse
import feedparser
# Set up some global variables
num_fetch_threads = 2
enclosure_queue = Queue()
# A real app wouldn't use hard-coded data...
feed_urls = [
'http://talkpython.fm/episodes/rss',
]
def message(s):
print('{}: {}'.format(threading.current_thread().name, s))
La fonction download_enclosures()
s’exécute dans le thread de travail et traite les téléchargements en utilisant urllib
.
def download_enclosures(q):
"""This is the worker thread function.
It processes items in the queue one after
another. These daemon threads go into an
infinite loop, and exit only when
the main thread ends.
"""
while True:
message('looking for the next enclosure')
url = q.get()
filename = url.rpartition('/')[-1]
message('downloading {}'.format(filename))
response = urllib.request.urlopen(url)
data = response.read()
# Save the downloaded file to the current directory
message('writing to {}'.format(filename))
with open(filename, 'wb') as outfile:
outfile.write(data)
q.task_done()
Une fois que la fonction cible pour les threads est définie, le thread de travail peut être démarré. Quand download_enclosures()
s’occupe de l’instruction url = q.get()
, elle la bloque et attend jusqu’à ce que la file d’attente ait quelque chose à retourner. Cela signifie qu’il est prudent de démarrer les threads avant qu’il n’y ait quoi que ce soit dans la file d’attente.
# Set up some threads to fetch the enclosures
for i in range(num_fetch_threads):
worker = threading.Thread(
target=download_enclosures,
args=(enclosure_queue,),
name='worker-{}'.format(i),
)
worker.setDaemon(True)
worker.start()
L’étape suivante est de récupérer le contenu de flux en utilisant le module feedparser
et de mettre en file d’attente les URL. Dès que possible, la première URL est ajoutée à la file d’attente, un des threads de travail la prend et démarre le téléchargement. La boucle continue d’ajouter les éléments jusqu’à ce que le flux soit complet, et les threads de travail retirent à tour de rôle de la file d’attente les URL pour les télécharger.
# Download the feed(s) and put the enclosure URLs into
# the queue.
for url in feed_urls:
response = feedparser.parse(url, agent='fetch_podcasts.py')
for entry in response['entries'][:5]:
for enclosure in entry.get('enclosures', []):
parsed_url = urlparse(enclosure['url'])
message('queuing {}'.format(
parsed_url.path.rpartition('/')[-1]))
enclosure_queue.put(enclosure['url'])
Il ne reste plus qu’à attendre que la file se vide à nouveau, par l’utilisation de join()
.
# Now wait for the queue to be empty, indicating that we have
# processed all of the downloads.
message('*** main thread waiting')
enclosure_queue.join()
message('*** done')
L’exécution de cet exemple de script produit une sortie similaire à celle qui suit.
python3 fetch_podcasts.py
worker-0: looking for the next enclosure
worker-1: looking for the next enclosure
MainThread: queuing turbogears-and-the-future-of-python-web-frameworks.mp3
MainThread: queuing continuum-scientific-python-and-the-business-of-open-source.mp3
MainThread: queuing openstack-cloud-computing-built-on-python.mp3
MainThread: queuing pypy.js-pypy-python-in-your-browser.mp3
MainThread: queuing machine-learning-with-python-and-scikit-learn.mp3
MainThread: *** main thread waiting
worker-0: downloading turbogears-and-the-future-of-python-web-frameworks.mp3
worker-1: downloading continuum-scientific-python-and-the-business-of-open-source.mp3
worker-0: looking for the next enclosure
worker-0: downloading openstack-cloud-computing-built-on-python.mp3
worker-1: looking for the next enclosure
worker-1: downloading pypy.js-pypy-python-in-your-browser.mp3
worker-0: looking for the next enclosure
worker-0: downloading machine-learning-with-python-and-scikit-learn.mp3
worker-1: looking for the next enclosure
worker-0: looking for the next enclosure
MainThread: *** done
La sortie actuelle dépendra du contenu des flux RSS utilisés.
But : Conversion entre chaînes et données binaires.
Le module struct
inclut des fonctions pour la conversion entre les octets de chaînes et les types de données Python natifs tels que les nombres et les chaînes.
Un ensemble de fonctions au niveau du module est disponible pour travailler avec des valeurs structurées, tout comme la classe Struct
. Les spécificateurs de format sont convertis depuis leur format de chaînes vers une représentation compilée, similaire à la façon dont sont pratiques les expressions régulières. La conversion nécessite certaines ressources, ainsi il est plus efficient de la faire en une fois lors de la création de l’instance Struct
et de l’appel des méthodes sur l’instance plutôt que d’utiliser les fonctions au niveau du module. Tous les exemples suivants utilisent la classe Struct
.
Les structures prennent en charge l’emballage de données dans les chaînes, et le déballage de données depuis les chaînes par l’usage des spécificateurs de format composés de caractères représentant le type des données et d’indicateurs facultatifs de comptage et de finalité. Se référer à la documentation standard de la bibliothèque pour avoir la liste complète des spécificateurs de format supportés.
Dans cet exemple, le spécificateur appelle comme valeurs, un entier, un entier long, et un nombre à virgule flottante. Les espaces dans le spécificateur de format sont inclus pour séparer le type d’indicateurs, et sont ignorés lorsque le format est compilé.
# struct_pack.py
import struct
import binascii
values = (1, 'ab'.encode('utf-8'), 2.7)
s = struct.Struct('I 2s f')
packed_data = s.pack(*values)
print('Original values:', values)
print('Format string :', s.format)
print('Uses :', s.size, 'bytes')
print('Packed Value :', binascii.hexlify(packed_data))
L’exemple convertit la valeur encodée en une séquence d’octets hexadécimaux pour l’imprimer avec la fonction binascii.hexlify()
, puisque certains des caractères sont nuls.
$ python3 struct_pack.py
Original values: (1, b'ab', 2.7)
Format string : I 2s f
Uses : 12 bytes
Packed Value : b'0100000061620000cdcc2c40'
Utilisez unpack()
pour extraire la donnée de sa représentation encodée.
# struct_unpack.py
import struct
import binascii
packed_data = binascii.unhexlify(b'0100000061620000cdcc2c40')
s = struct.Struct('I 2s f')
unpacked_data = s.unpack(packed_data)
print('Unpacked Values:', unpacked_data)
Passer la valeur condensée à unpack()
renvoie les mêmes valeurs (notez l’écart dans la valeur à virgule flottante).
$ python3 struct_unpack.py
Unpacked Values: (1, b'ab', 2.700000047683716)
Par défaut, les valeurs sont codées à l’aide de la notion d’endianness de la bibliothèque C native. Il est facile de surcharger ce choix en fournissant une directive endianness explicite dans le format de chaînes.
# struct_endianness.py
import struct
import binascii
values = (1, 'ab'.encode('utf-8'), 2.7)
print('Original values:', values)
endianness = [
('@', 'native, native'),
('=', 'native, standard'),
('<', 'little-endian'),
('>', 'big-endian'),
('!', 'network'),
]
for code, name in endianness:
s = struct.Struct(code + ' I 2s f')
packed_data = s.pack(*values)
print()
print('Format string :', s.format, 'for', name)
print('Uses :', s.size, 'bytes')
print('Packed Value :', binascii.hexlify(packed_data))
print('Unpacked Value :', s.unpack(packed_data))
La table ci-dessous liste les spécificateurs d’ordre d’octets utilisés par Struct
.
+——+—————–+ | Code | Signification | +——+—————–+ | @ | Ordre natif | | = | Standard natif | | < | little-endian | | > | big-endian | | ! | Ordre réseau | +——+—————–+
$ python3 struct_endianness.py
Original values: (1, b'ab', 2.7)
Format string : @ I 2s f for native, native
Uses : 12 bytes
Packed Value : b'0100000061620000cdcc2c40'
Unpacked Value : (1, b'ab', 2.700000047683716)
Format string : = I 2s f for native, standard
Uses : 10 bytes
Packed Value : b'010000006162cdcc2c40'
Unpacked Value : (1, b'ab', 2.700000047683716)
Format string : < I 2s f for little-endian
Uses : 10 bytes
Packed Value : b'010000006162cdcc2c40'
Unpacked Value : (1, b'ab', 2.700000047683716)
Format string : > I 2s f for big-endian
Uses : 10 bytes
Packed Value : b'000000016162402ccccd'
Unpacked Value : (1, b'ab', 2.700000047683716)
Format string : ! I 2s f for network
Uses : 10 bytes
Packed Value : b'000000016162402ccccd'
Unpacked Value : (1, b'ab', 2.700000047683716)
Travailler avec une donnée encodée en binaire est typiquement réservé pour les situations nécessitant de la performance ou de passer la donnée vers ou depuis des modules d’extensions. Ces cas peuvent être optimisés en évitant la surcharge liée à l’allocation d’un nouveau tampon pour chaque structure codée. Les méthodes pack_into()
et unpack_from()
prennent en charge l’écriture directe de tampons préalloués.
# struct_buffers.py
import array
import binascii
import ctypes
import struct
s = struct.Struct('I 2s f')
values = (1, 'ab'.encode('utf-8'), 2.7)
print('Original:', values)
print()
print('ctypes string buffer')
b = ctypes.create_string_buffer(s.size)
print('Before :', binascii.hexlify(b.raw))
s.pack_into(b, 0, *values)
print('After :', binascii.hexlify(b.raw))
print('Unpacked:', s.unpack_from(b, 0))
print()
print('array')
a = array.array('b', b'\0' * s.size)
print('Before :', binascii.hexlify(a))
s.pack_into(a, 0, *values)
print('After :', binascii.hexlify(a))
print('Unpacked:', s.unpack_from(a, 0))
L’attribut size
à Struct
nous dit la taille dont a besoin le tampon.
$ python3 struct_buffers.py
Original: (1, b'ab', 2.7)
ctypes string buffer
Before : b'000000000000000000000000'
After : b'0100000061620000cdcc2c40'
Unpacked: (1, b'ab', 2.700000047683716)
array
Before : b'000000000000000000000000'
After : b'0100000061620000cdcc2c40'
Unpacked: (1, b'ab', 2.700000047683716)
array
, pour travailler avec des séquences de valeurs de type fixébinascii
- Le module binascii
, pour produire des représentations ASCII de donnée binaire.But: Référer un objet «coûteux», tout en permettant à sa mémoire d’être réclamée par le ramasse miettes s’il n’y a pas d’autres références non faibles.
Le module weakref
prend en charge les références faibles aux objets. Une référence normale incrémente le compteur de référence sur l’objet et l’empêche d’être nettoyé. Ce résultat n’est pas toujours souhaitable, spécifiquement quand une référence circulaire doit être présente ou quand un cache d’objet doit être supprimé quand de la mémoire est nécessaire. Une référence faible est une poignée pour un objet qui ne l’empêche pas d’être nettoyé automatiquement.
Les références faibles d’objets sont gérés au-travers de la classe ref
. Pour récupérer l’objet original, appelez la référence objet.
# weakref_ref.py
import weakref
class ExpensiveObject:
def __del__(self):
print('(Deleting {})'.format(self))
obj = ExpensiveObject()
r = weakref.ref(obj)
print('obj:', obj)
print('ref:', r)
print('r():', r())
print('deleting obj')
del obj
print('r():', r())
Dans ce cas, puisque obj
est supprimé avant le second appel à la référence, la ref
retourne None
.
$ python3 weakref_ref.py
obj: <__main__.ExpensiveObject object at 0x1007b1a58>
ref: <weakref at 0x1007a92c8; to 'ExpensiveObject' at
0x1007b1a58>
r(): <__main__.ExpensiveObject object at 0x1007b1a58>
deleting obj
(Deleting <__main__.ExpensiveObject object at 0x1007b1a58>)
r(): None
Le constructeur ref
accepte une fonction optionnelle de rappel qui est invoquée quand la référence de l’objet est supprimée.
# weakref_ref_callback.py
import weakref
class ExpensiveObject:
def __del__(self):
print('(Deleting {})'.format(self))
def callback(reference):
"""Invoked when referenced object is deleted"""
print('callback({!r})'.format(reference))
obj = ExpensiveObject()
r = weakref.ref(obj, callback)
print('obj:', obj)
print('ref:', r)
print('r():', r())
print('deleting obj')
del obj
print('r():', r())
Le rappel reçoit la référence de l’objet en tant qu’argument après que la référence soit «morte» et ne se réfère plus à l’objet d’origine. Une utilisation de cette fonctionnalité est de supprimer la référence faible d’un objet depuis un cache.
$ python3 weakref_ref_callback.py
obj: <__main__.ExpensiveObject object at 0x1010b1978>
ref: <weakref at 0x1010a92c8; to 'ExpensiveObject' at
0x1010b1978>
r(): <__main__.ExpensiveObject object at 0x1010b1978>
deleting obj
(Deleting <__main__.ExpensiveObject object at 0x1010b1978>)
callback(<weakref at 0x1010a92c8; dead>)
r(): None
Pour une gestion plus robuste des ressources lorsque des références faibles sont nettoyées, utilisez la méthode finalize
pour associer les rappels aux objets. Une instance finalize
est retenue jusqu’à ce que l’objet attaché soit supprimé, même si l’application ne retient pas de référence à la fin.
# weakref_finalize.py
import weakref
class ExpensiveObject:
def __del__(self):
print('(Deleting {})'.format(self))
def on_finalize(*args):
print('on_finalize({!r})'.format(args))
obj = ExpensiveObject()
weakref.finalize(obj, on_finalize, 'extra argument')
del obj
Les arguments de finalize
sont les objets à suivre, un rappel à invoquer quand les objets sont nettoyés, et que les arguments de positions ou nommés sont passés au rappel.
$ python3 weakref_finalize.py
(Deleting <__main__.ExpensiveObject object at 0x1019b10f0>)
on_finalize(('extra argument',))
L’instance finalize
a une propriété en écriture nommée atexit
pour contrôler quand le rappel est invoqué lorsqu’un programme se termine, s’il n’a pas déjà été appelé.
# weakref_finalize_atexit.py
import sys
import weakref
class ExpensiveObject:
def __del__(self):
print('(Deleting {})'.format(self))
def on_finalize(*args):
print('on_finalize({!r})'.format(args))
obj = ExpensiveObject()
f = weakref.finalize(obj, on_finalize, 'extra argument')
f.atexit = bool(int(sys.argv[1]))
Le comportement par défaut est d’invoquer le rappel. Paramétrer atexit
sur false
désactivera ce comportement.
$ python3 weakref_finalize_atexit.py 1
on_finalize(('extra argument',))
(Deleting <__main__.ExpensiveObject object at 0x1007b10f0>)
$ python3 weakref_finalize_atexit.py 0
Donner à l’instance finalize
une référence vers l’objet à suivre a pour conséquence de le retenir, ainsi l’objet n’est jamais passé au ramasse miettes.
# weakref_finalize_reference.py
import gc
import weakref
class ExpensiveObject:
def __del__(self):
print('(Deleting {})'.format(self))
def on_finalize(*args):
print('on_finalize({!r})'.format(args))
obj = ExpensiveObject()
obj_id = id(obj)
f = weakref.finalize(obj, on_finalize, obj)
f.atexit = False
del obj
for o in gc.get_objects():
if id(o) == obj_id:
print('found uncollected object in gc')
Comme cet exemple le montre, même si la référence explicite vers obj
est supprimée, l’objet est retenu et visible par le ramasse miettes au-travers de f
.
$ python3 weakref_finalize_reference.py
found uncollected object in gc
Utiliser une méthode liée à un objet suivi en tant rappel peut également empêcher la finalisation correcte de l’objet.
# weakref_finalize_reference_method.py
import gc
import weakref
class ExpensiveObject:
def __del__(self):
print('(Deleting {})'.format(self))
def do_finalize(self):
print('do_finalize')
obj = ExpensiveObject()
obj_id = id(obj)
f = weakref.finalize(obj, obj.do_finalize)
f.atexit = False
del obj
for o in gc.get_objects():
if id(o) == obj_id:
print('found uncollected object in gc')
Puisque le rappel donné à finalize
est une méthode liée à l’instance obj
, l’objet de finalisation capture une référence vers obj
, qui ne peut être supprimé ou collecté par le ramasse miettes.
$ python3 weakref_finalize_reference_method.py
found uncollected object in gc
Il est parfois plus pratique d’utiliser un mandataire, plutôt qu’une référence faible. Les mandataires peuvent être utilisés comme s’il s’agissait de l’objet d’origine et n’ont pas besoin d’être appelés avant que l’objet ne soit accessible. En conséquence, ils peuvent être passés à une bibliothèque qui ne sait pas qu’elle reçoit une référence au lieu d’un objet réel.
# weakref_proxy.py
import weakref
class ExpensiveObject:
def __init__(self, name):
self.name = name
def __del__(self):
print('(Deleting {})'.format(self))
obj = ExpensiveObject('My Object')
r = weakref.ref(obj)
p = weakref.proxy(obj)
print('via obj:', obj.name)
print('via ref:', r().name)
print('via proxy:', p.name)
del obj
print('via proxy:', p.name)
Si le mandataire est accédé après que l’objet en référence soit supprimé, une erreur d’exception ReferenceError
est levée.
$ python3 weakref_proxy.py
via obj: My Object
via ref: My Object
via proxy: My Object
(Deleting <__main__.ExpensiveObject object at 0x1007aa7b8>)
Traceback (most recent call last):
File "weakref_proxy.py", line 30, in <module>
print('via proxy:', p.name)
ReferenceError: weakly-referenced object no longer exists
Les classes ref
et obj
sont considérés de «bas niveau». Bien qu’elles soient utiles pour maintenir les références faibles d’objets individuels et de permettre des cycles pour être collectés par le ramasse miettes, les classes WeakKeyDictionary
et WeakValueDictionary
fournissent une API plus appropriée pour créer un cache de plusieurs objets.
La classe WeakValueDictionary
utilise les références faibles vers les valeurs qu’elle capture, leur permettant d’être collectées par le ramasse miettes lorsque tout autre code ne les utilise pas. L’utilisation des appels explicites au ramasse miettes illustre la différence entre la gestion de la mémoire avec un dictionnaire standard et WeakValueDictionary
:
# weakref_valuedict.py
import gc
from pprint import pprint
import weakref
gc.set_debug(gc.DEBUG_UNCOLLECTABLE)
class ExpensiveObject:
def __init__(self, name):
self.name = name
def __repr__(self):
return 'ExpensiveObject({})'.format(self.name)
def __del__(self):
print(' (Deleting {})'.format(self))
def demo(cache_factory):
# hold objects so any weak references
# are not removed immediately
all_refs = {}
# create the cache using the factory
print('CACHE TYPE:', cache_factory)
cache = cache_factory()
for name in ['one', 'two', 'three']:
o = ExpensiveObject(name)
cache[name] = o
all_refs[name] = o
del o # decref
print(' all_refs =', end=' ')
pprint(all_refs)
print('\n Before, cache contains:', list(cache.keys()))
for name, value in cache.items():
print(' {} = {}'.format(name, value))
del value # decref
# remove all references to the objects except the cache
print('\n Cleanup:')
del all_refs
gc.collect()
print('\n After, cache contains:', list(cache.keys()))
for name, value in cache.items():
print(' {} = {}'.format(name, value))
print(' demo returning')
return
demo(dict)
print()
demo(weakref.WeakValueDictionary)
Toutes variables de boucle faisant référence aux valeurs mises en cache doivent être explicitement effacées pour que le compte de références de l’objet soit décrémenté. Autrement, le ramasse miettes ne supprimera pas les objets, et ils resteront toujours dans le cache. De la même manière, la variable all_refs
est utilisée pour capturer les références afin de prévenir que le ramasse miettes les collecte prématurément.
$ python3 weakref_valuedict.py
CACHE TYPE: <class 'dict'>
all_refs = {'one': ExpensiveObject(one),
'three': ExpensiveObject(three),
'two': ExpensiveObject(two)}
Before, cache contains: ['one', 'three', 'two']
one = ExpensiveObject(one)
three = ExpensiveObject(three)
two = ExpensiveObject(two)
Cleanup:
After, cache contains: ['one', 'three', 'two']
one = ExpensiveObject(one)
three = ExpensiveObject(three)
two = ExpensiveObject(two)
demo returning
(Deleting ExpensiveObject(one))
(Deleting ExpensiveObject(three))
(Deleting ExpensiveObject(two))
CACHE TYPE: <class 'weakref.WeakValueDictionary'>
all_refs = {'one': ExpensiveObject(one),
'three': ExpensiveObject(three),
'two': ExpensiveObject(two)}
Before, cache contains: ['one', 'three', 'two']
one = ExpensiveObject(one)
three = ExpensiveObject(three)
two = ExpensiveObject(two)
Cleanup:
(Deleting ExpensiveObject(one))
(Deleting ExpensiveObject(three))
(Deleting ExpensiveObject(two))
After, cache contains: []
demo returning
La classe WeakKeyDictionary
fonctionne de manière similaire mais utilise les références faibles pour les clés au lieu des valeurs dans le dictionnaire.
Attention La documentation de la bibliothèque pour
weakref
contient cet avertissement : Mise en garde : Étant donné qu’unWeakValueDictionary
est construit sur un dictionnaire Python, sa taille ne doit pas changer lors de son itération. Cela peut être difficile à garantir pour unWeakValueDictionary
parce que les actions effectuées par le programme pendant l’itération peuvent entraîner la disparition «par magie» d’éléments du dictionnaire (c’est un effet de bord du ramasse miettes des collections).
gc
est l’interface pour l’interprétateur du ramasse miettes.But : Fournir des fonctions pour dupliquer les objets en utilisant une sémantique de copie superficielle ou profonde
Le module copy
inclut deux fonctions, copy()
et deepcopy()
, pour dupliquer des objets existants.
La copie superficielle créée par copy()
est un nouveau conteneur rempli de références vers les contenus de l’objet original. Lors de la copie superficielle d’un objet list
, une nouvelle list
est construite et les éléments de l’objet original y sont ajoutés.
# copy_shallow.py
import copy
import functools
@functools.total_ordering
class MyClass:
def __init__(self, name):
self.name = name
def __eq__(self, other):
return self.name == other.name
def __gt__(self, other):
return self.name > other.name
a = MyClass('a')
my_list = [a]
dup = copy.copy(my_list)
print(' my_list:', my_list)
print(' dup:', dup)
print(' dup is my_list:', (dup is my_list))
print(' dup == my_list:', (dup == my_list))
print('dup[0] is my_list[0]:', (dup[0] is my_list[0]))
print('dup[0] == my_list[0]:', (dup[0] == my_list[0]))
Pour une copie superficielle, l’instance MyClass
n’est pas dupliquée, ainsi la référence dans la liste dup
est le même objet que celui qui est dans my_list
.
$ python3 copy_shallow.py
my_list: [<__main__.MyClass object at 0x101f9c160>]
dup: [<__main__.MyClass object at 0x101f9c160>]
dup is my_list: False
dup == my_list: True
dup[0] is my_list[0]: True
dup[0] == my_list[0]: True
La copie profonde créée par deepcopy()
est un nouveau conteneur avec des copies des contenus de l’objet original. Pour faire une copie profonde d’une list
, une nouvelle list
est construite, les éléments de la liste originale sont copiés, et ensuite ces copies sont ajoutées à la nouvelle liste.
Remplacer l’appel de copy()
par deepcopy()
fait la différence dans la sortie apparente.
# copy_deep.py
import copy
import functools
@functools.total_ordering
class MyClass:
def __init__(self, name):
self.name = name
def __eq__(self, other):
return self.name == other.name
def __gt__(self, other):
return self.name > other.name
a = MyClass('a')
my_list = [a]
dup = copy.deepcopy(my_list)
print(' my_list:', my_list)
print(' dup:', dup)
print(' dup is my_list:', (dup is my_list))
print(' dup == my_list:', (dup == my_list))
print('dup[0] is my_list[0]:', (dup[0] is my_list[0]))
print('dup[0] == my_list[0]:', (dup[0] == my_list[0]))
Le premier élément de la liste n’a plus du tout la même référence objet, mais quand les deux objets sont comparés, ils sont toujours évalués comme égaux.
$ python3 copy_deep.py
my_list: [<__main__.MyClass object at 0x101e9c160>]
dup: [<__main__.MyClass object at 0x1044e1f98>]
dup is my_list: False
dup == my_list: True
dup[0] is my_list[0]: False
dup[0] == my_list[0]: True
Il est possible de contrôler comment les copies sont faites en utilisant les méthodes spéciales __copy__()
et __deepcopy__()
.
__copy__()
est appelée sans aucun argument et devrait retourner une copie superficielle de l’objet.__deepcopy__()
est appelée avec un dictionnaire memo et devrait retourner une copie profonde de l’objet. Tous les attributs membres qui ont besoin d’être copiés en profondeur devraient être passé vers copy.deepcopy()
, avec le dictionnaire memo, pour contrôler la récursion. (Le dictionnaire memo est expliqué plus tard en détails).L’exemple suivant illustre comment les méthodes sont appelées.
# copy_hooks.py
import copy
import functools
@functools.total_ordering
class MyClass:
def __init__(self, name):
self.name = name
def __eq__(self, other):
return self.name == other.name
def __gt__(self, other):
return self.name > other.name
def __copy__(self):
print('__copy__()')
return MyClass(self.name)
def __deepcopy__(self, memo):
print('__deepcopy__({})'.format(memo))
return MyClass(copy.deepcopy(self.name, memo))
a = MyClass('a')
sc = copy.copy(a)
dc = copy.deepcopy(a)
Le dictionnaire memo est utilisé pour garder la trace des valeurs qui ont été déjà copiées, évitant ainsi une récursion infinie.
$ python3 copy_hooks.py
__copy__()
__deepcopy__({})
Pour éviter les problèmes lors de la duplication récursive des structures de données, deepcopy()
utilise un dictionnaire pour suivre les objets qui ont déjà été copiés. Le dictionnaire est passé à la méthode __deepcopy__()
afin qu’il puisse être examiné là aussi.
Le nouvel exemple montre comment une structure de données interconnectée telle qu’un graphe dirigé peut aider à protéger contre la récursivité, en implémentant la méthode __deepcopy__()
.
# copy_recursion.py
import copy
class Graph:
def __init__(self, name, connections):
self.name = name
self.connections = connections
def add_connection(self, other):
self.connections.append(other)
def __repr__(self):
return 'Graph(name={}, id={})'.format(
self.name, id(self))
def __deepcopy__(self, memo):
print('\nCalling __deepcopy__ for {!r}'.format(self))
if self in memo:
existing = memo.get(self)
print(' Already copied to {!r}'.format(existing))
return existing
print(' Memo dictionary:')
if memo:
for k, v in memo.items():
print(' {}: {}'.format(k, v))
else:
print(' (empty)')
dup = Graph(copy.deepcopy(self.name, memo), [])
print(' Copying to new object {}'.format(dup))
memo[self] = dup
for c in self.connections:
dup.add_connection(copy.deepcopy(c, memo))
return dup
root = Graph('root', [])
a = Graph('a', [root])
b = Graph('b', [a, root])
root.add_connection(a)
root.add_connection(b)
dup = copy.deepcopy(root)
La classe Graph
inclut certaines méthodes basiques de graphe dirigé. Une instance peut être initialisée avec un nom et une liste de nœuds existants auxquels il est connecté. La méthode add_connection()
est utilisée pour paramétrer les connexions bidirectionnelles. Elle est aussi utilisée par l’opérateur de copie profonde.
La méthode __deepcopy__()
imprime les messages pour montrer comment elle est appelée, et gère le contenu du dictionnaire memo selon les besoins. Au lieu de copier en gros la liste complète de connexions, il crée une nouvelle liste et y ajoute des copies des connexions individuelles. Cela permet que le dictionnaire memo soit mise à jour à chaque fois qu’un nouveau nœud est dupliqué, et évite les problèmes de récursion ou de copies supplémentaires de nœuds. Comme précédemment, la méthode retourne la copie d’objet quand il est fait.
Le graphe vu dans la figure inclut les nombreux cycles, mais la gestion de la récursion avec le dictionnaire memo empêche la traversée de provoquer une erreur de débordement de pile. Quand le nœud root est copié, il produit la sortie suivante.
$ python3 copy_recursion.py
Calling __deepcopy__ for Graph(name=root, id=4326183824)
Memo dictionary:
(empty)
Copying to new object Graph(name=root, id=4367233208)
Calling __deepcopy__ for Graph(name=a, id=4326186344)
Memo dictionary:
Graph(name=root, id=4326183824): Graph(name=root,
id=4367233208)
Copying to new object Graph(name=a, id=4367234720)
Calling __deepcopy__ for Graph(name=root, id=4326183824)
Already copied to Graph(name=root, id=4367233208)
Calling __deepcopy__ for Graph(name=b, id=4326183880)
Memo dictionary:
Graph(name=root, id=4326183824): Graph(name=root,
id=4367233208)
Graph(name=a, id=4326186344): Graph(name=a, id=4367234720)
4326183824: Graph(name=root, id=4367233208)
4367217936: [Graph(name=root, id=4326183824), Graph(name=a,
id=4326186344)]
4326186344: Graph(name=a, id=4367234720)
Copying to new object Graph(name=b, id=4367235000)
La seconde fois où le nœud root est rencontré, pendant que le nœud a soit copié, __deepcopy__()
détecte la récursion et réutilise la valeur existante du dictionnaire memo au lieu de créer un nouvel objet.
But : Structures de données Pretty-print
Le module pprint
contient une «jolie imprimante» pour produire des vues esthétiques des structures de données. Le formateur produit des représentations de structures de données qui peuvent être analysées correctement par l’interpréteur, et qui sont aussi faciles à lire pour un humain. La sortie est conservée sur une seule ligne, si possible, et en retrait lorsqu’elle est fractionnée sur plusieurs lignes.
Les exemples dans ce chapitre dépendent tous du script pprint_data.py
, qui est montré ici.
# pprint_data.py
data = [
(1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}),
(2, {'e': 'E', 'f': 'F', 'g': 'G', 'h': 'H',
'i': 'I', 'j': 'J', 'k': 'K', 'l': 'L'}),
(3, ['m', 'n']),
(4, ['o', 'p', 'q']),
(5, ['r', 's', 't''u', 'v', 'x', 'y', 'z']),
]
La manière la plus simple d’utiliser le module est au-travers de la fonction pprint()
.
# pprint_pprint.py
from pprint import pprint
from pprint_data import data
print('PRINT:')
print(data)
print()
print('PPRINT:')
pprint(data)
pprint()
formate un objet et l’écrit dans le flux de données en le passant en argument (ou sys.stdout
par défaut).
$ python3 pprint_pprint.py
PRINT:
[(1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}), (2, {'e': 'E', 'f':
'F', 'g': 'G', 'h': 'H', 'i': 'I', 'j': 'J', 'k': 'K', 'l': 'L'}), (
3, ['m', 'n']), (4, ['o', 'p', 'q']), (5, ['r', 's', 'tu', 'v', 'x',
'y', 'z'])]
PPRINT:
[(1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}),
(2,
{'e': 'E',
'f': 'F',
'g': 'G',
'h': 'H',
'i': 'I',
'j': 'J',
'k': 'K',
'l': 'L'}),
(3, ['m', 'n']),
(4, ['o', 'p', 'q']),
(5, ['r', 's', 'tu', 'v', 'x', 'y', 'z'])]
Pour formater une structure de données sans l’écrire directement vers un flux (par exemple, pour la journalisation) utilisez pformat()
pour construire une représentation de chaînes.
# pprint_pformat.py
import logging
from pprint import pformat
from pprint_data import data
logging.basicConfig(
level=logging.DEBUG,
format='%(levelname)-8s %(message)s',
)
logging.debug('Logging pformatted data')
formatted = pformat(data)
for line in formatted.splitlines():
logging.debug(line.rstrip())
La chaîne formatée peut alors être imprimée ou journalisée indépendamment.
$ python3 pprint_pformat.py
DEBUG Logging pformatted data
DEBUG [(1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}),
DEBUG (2,
DEBUG {'e': 'E',
DEBUG 'f': 'F',
DEBUG 'g': 'G',
DEBUG 'h': 'H',
DEBUG 'i': 'I',
DEBUG 'j': 'J',
DEBUG 'k': 'K',
DEBUG 'l': 'L'}),
DEBUG (3, ['m', 'n']),
DEBUG (4, ['o', 'p', 'q']),
DEBUG (5, ['r', 's', 'tu', 'v', 'x', 'y', 'z'])]
La classe PrettyPrinter
utilisée par pprint()
peut aussi fonctionner avec des classes personnalisées, si elles définissent une méthode __repr__()
.
# pprint_arbitrary_object.py
from pprint import pprint
class node:
def __init__(self, name, contents=[]):
self.name = name
self.contents = contents[:]
def __repr__(self):
return (
'node(' + repr(self.name) + ', ' +
repr(self.contents) + ')'
)
trees = [
node('node-1'),
node('node-2', [node('node-2-1')]),
node('node-3', [node('node-3-1')]),
]
pprint(trees)
Les représentations de ces objets imbriqués sont combinées par PrettyPrinter
pour retourner une représentation complète de chaînes.
$ python3 pprint_arbitrary_object.py
[node('node-1', []),
node('node-2', [node('node-2-1', [])]),
node('node-3', [node('node-3-1', [])])]
Les structures de données récursives sont représentées avec une référence vers la source originale de données, restituées dans le format <Recursion on typename with id=number>
.
# pprint_recursion.py
from pprint import pprint
local_data = ['a', 'b', 1, 2]
local_data.append(local_data)
print('id(local_data) =>', id(local_data))
pprint(local_data)
Dans cet exemple, la liste local_data
est ajoutée à elle-même, créant une référence récursive.
$ python3 pprint_recursion.py
id(local_data) => 4358913288
['a', 'b', 1, 2, <Recursion on list with id=4358913288>]
Pour des structures de données très profondes, il peut ne pas être désirable que la sortie inclut tous les détails. La donnée peut ne pas être formatée proprement, le texte formaté est peut-être trop volumineux pour être géré, ou certaines données peuvent être superflues.
# pprint_depth.py
from pprint import pprint
from pprint_data import data
pprint(data, depth=1)
pprint(data, depth=2)
Utilisez l’argument depth
pour contrôler jusqu’où dans la structure de données imbriquée l’imprimante peut faire une récursion. Les niveaux non inclus dans la sortie sont représentés par une ellipse.
$ python3 pprint_depth.py
[(...), (...), (...), (...), (...)]
[(1, {...}), (2, {...}), (3, [...]), (4, [...]), (5, [...])]
La sortie par défaut pour le texte formaté est de 80 colonnes. Pour ajuster la largeur, utilisez l’argument width
de pprint()
.
# pprint_width.py
from pprint import pprint
from pprint_data import data
for width in [80, 5]:
print('WIDTH =', width)
pprint(data, width=width)
print()
Quand la largeur est trop petite pour accommoder la structure de données formatée, les lignes ne sont pas tronquées, ni encapsulées au cas où cela introduirait une syntaxe non valide.
$ python3 pprint_width.py
WIDTH = 80
[(1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}),
(2,
{'e': 'E',
'f': 'F',
'g': 'G',
'h': 'H',
'i': 'I',
'j': 'J',
'k': 'K',
'l': 'L'}),
(3, ['m', 'n']),
(4, ['o', 'p', 'q']),
(5, ['r', 's', 'tu', 'v', 'x', 'y', 'z'])]
WIDTH = 5
[(1,
{'a': 'A',
'b': 'B',
'c': 'C',
'd': 'D'}),
(2,
{'e': 'E',
'f': 'F',
'g': 'G',
'h': 'H',
'i': 'I',
'j': 'J',
'k': 'K',
'l': 'L'}),
(3,
['m',
'n']),
(4,
['o',
'p',
'q']),
(5,
['r',
's',
'tu',
'v',
'x',
'y',
'z'])]
Le drapeau compact
demande à pprint()
d’essayer de mettre plus de données sur chaque ligne individuelle, plutôt que d’étendre des structures de données complexes sur plusieurs lignes.
# pprint_compact.py
from pprint import pprint
from pprint_data import data
print('DEFAULT:')
pprint(data, compact=False)
print('\nCOMPACT:')
pprint(data, compact=True)
Cet exemple montre que quand une structure de données ne tient pas sur une ligne, elle est scindée (comme pour le deuxième élément de la liste de données). Quand de multiples éléments peuvent tenir sur une ligne, comme avec le troisième ou quatrième membre, ils sont placés de cette façon.
$ python3 pprint_compact.py
DEFAULT:
[(1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}),
(2,
{'e': 'E',
'f': 'F',
'g': 'G',
'h': 'H',
'i': 'I',
'j': 'J',
'k': 'K',
'l': 'L'}),
(3, ['m', 'n']),
(4, ['o', 'p', 'q']),
(5, ['r', 's', 'tu', 'v', 'x', 'y', 'z'])]
COMPACT:
[(1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}),
(2,
{'e': 'E',
'f': 'F',
'g': 'G',
'h': 'H',
'i': 'I',
'j': 'J',
'k': 'K',
'l': 'L'}),
(3, ['m', 'n']), (4, ['o', 'p', 'q']),
(5, ['r', 's', 'tu', 'v', 'x', 'y', 'z'])]
*[API]: Application Programming Interface - Interface de Programmation Applicative *[PEP]: Python Enhancement Proposals - Propositions d’Amélioration Python *[RSS]: Really Simple Syndication - Syndication de contenu réellement simple *[URL]: Uniform Resource Locator - Repère uniforme de ressource *[p.ex.]: par exemple
]]>Great fleas have little fleas upon their backs to bite ’em, And little fleas have lesser fleas, and so ad infinitum. — Augustus De Morgan
Tout comme les expressions régulières dopent les chaînes aux stéroïdes, le module itertools
dopent les itérateurs aux stéroïdes. Mais d’abord, je veux vous montrer un puzzle classique :
HAWAII + IDAHO + IOWA + OHIO == STATES
510199 + 98153 + 9301 + 3593 == 621246
H = 5
A = 1
W = 0
I = 9
D = 8
O = 3
S = 6
T = 2
E = 4
De tels puzzles sont appelés cryptarithmes ou alphamétiques. Les lettres épellent des mots réels, mais si vous remplacez chaque lettre par un chiffre de 0-9
, elles « épellent » aussi une équation arithmétique. L’astuce consiste à déterminer quelle lettre correspond à chaque chiffre. Toutes les occurrences de chaque lettre doivent correspondre au même chiffre, aucun chiffre ne doit être répété, et aucun « mot » ne peut démarrer avec le chiffre 0.
Dans ce chapitre, nous plongerons en profondeur dans un incroyable programme Python écrit à l’origine par Raymond Hettinger. Ce programme résout les puzzles alphamétiques en seulement 14 lignes de code :
import re
import itertools
def solve(puzzle):
words = re.findall('[A-Z]+', puzzle.upper())
unique_characters = set(''.join(words))
assert len(unique_characters) <= 10, 'Too many letters'
first_letters = {word[0] for word in words}
n = len(first_letters)
sorted_characters = ''.join(first_letters) + \
''.join(unique_characters - first_letters)
characters = tuple(ord(c) for c in sorted_characters)
digits = tuple(ord(c) for c in '0123456789')
zero = digits[0]
for guess in itertools.permutations(digits, len(characters)):
if zero not in guess[:n]:
equation = puzzle.translate(dict(zip(characters, guess)))
if eval(equation):
return equation
if __name__ == '__main__':
import sys
for puzzle in sys.argv[1:]:
print(puzzle)
solution = solve(puzzle)
if solution:
print(solution)
Vous pouvez exécuter ce programme depuis la ligne de commande. Sous Linux, cela ressemblerait à ceci. (Cela peut prendre un peu de temps, selon la vitesse de votre ordinateur, et comme il n’y a pas de barre de progression, soyez patient !)
you@localhost:~/diveintopython3/examples$ python3 alphametics.py "HAWAII + IDAHO + IOWA + OHIO == STATES"
HAWAII + IDAHO + IOWA + OHIO = STATES
510199 + 98153 + 9301 + 3593 == 621246
you@localhost:~/diveintopython3/examples$ python3 alphametics.py "I + LOVE + YOU == DORA"
I + LOVE + YOU == DORA
1 + 2784 + 975 == 3760
you@localhost:~/diveintopython3/examples$ python3 alphametics.py "SEND + MORE == MONEY"
SEND + MORE == MONEY
9567 + 1085 == 10652
La première chose que ce résolveur alphamétique fait est de trouver toutes les lettres (A-Z) dans le puzzle.
>>> import re
>>> re.findall('[0-9]+', '16 2-by-4s in rows of 8') ①
['16', '2', '4', '8']
>>> re.findall('[A-Z]+', 'SEND + MORE == MONEY') ②
['SEND', 'MORE', 'MONEY']
① Le module re
est une implémentation Python des expressions régulières. Il a une fonction astucieuse appelée findall()
qui prend un motif d’expression régulière et une chaîne, et trouve toutes les occurrences du motif dans la chaîne. Dans ce cas, le motif correspond aux séquences de nombres. La fonction findall()
retourne une liste de toutes les sous-chaînes qui correspondent au motif.
② Ici est le motif d’expression régulière qui correspond aux séquences de lettres. Une fois encore, la valeur de retour est une liste, et chaque item dans la liste est une chaîne qui correspond au motif d’expression régulière.
Voici un autre exemple qui stimulera un peu votre cerveau.
>>> re.findall(' s.*? s', "The sixth sick sheikh's sixth sheep's sick.")
[' sixth s', " sheikh's s", " sheep's s"]
Surpris ?
L’expression régulière recherche un espace, un s
, et ensuite la plus petite série possible de tout caractère (.*?)
, suivi d’un espace et encore d’un s
. Bien, en regardant cette chaîne en entrée, je vois cinq correspondances :
sixth s
ick sheikh’s sixth sheep’s sick. sick s
heikh’s sixth sheep’s sick. sheikh's s
ixth sheep’s sick. sixth s
heep’s sick. sheep's s
ick.Mais la fonction re.findall()
ne retourne seulement que trois correspondances. Elle retourne spécifiquement la première, la troisième et la cinquième. Pourquoi cela ?
Parce qu’ elle ne renvoie pas les correspondances qui se chevauchent. La première correspondance chevauche la seconde, ainsi la première est retournée et la seconde est sautée. Ensuite, la troisième chevauche la quatrième, ainsi la troisième est retournée et la quatrième est sautée. Finalement, la cinquième est retournée. Trois correspondances et pas cinq.
Cela n’a rien à voir avec le résolveur alphamétique ; Je pensais juste que c’était intéressant.
Sets rend trivial la recherche d’items uniques dans une séquence.
>>> a_list = ['The', 'sixth', 'sick', "sheik's", 'sixth', "sheep's", 'sick']
>>> set(a_list) ①
{'sixth', 'The', "sheep's", 'sick', "sheik's"}
>>> a_string = 'EAST IS EAST'
>>> set(a_string) ②
{'A', ' ', 'E', 'I', 'S', 'T'}
>>> words = ['SEND', 'MORE', 'MONEY']
>>> ''.join(words) ③
'SENDMOREMONEY'
>>> set(''.join(words)) ④
{'E', 'D', 'M', 'O', 'N', 'S', 'R', 'Y'}
① À une liste donnée de nombreuses chaînes, la fonction set()
retournera un ensemble de chaînes uniques depuis la liste. Cela à du sens si vous le considérez comme une boucle for
. Prendre le premier item de la liste, et le mettre dans l’ensemble. Le second. Le troisième. Le quatrième. Le cinquième - attendez, c’est déjà dans l’ensemble, donc il n’est répertorié qu’une fois, car les ensembles Python n’autorisent pas les doublons. La sixième. La septième – encore, une dupliquée, qui ne sera listée qu’une fois. Le résultat final ? Chacun des items uniques de la liste originale, sans duplication. La liste originale n’a même pas besoin d’être triée en premier.
② La même technique fonctionne avec les chaînes, puisqu’une chaîne est une séquence de caractères.
③ À une liste donnée de chaînes, ''.join(a_list)
concatène toutes les chaînes ensemble en une seule.
④ Ainsi, à une liste donnée de chaînes, la ligne de code retourne tous les caractères uniques dans toutes les chaînes, sans duplication.
Le résolveur alphamétique utilise cette technique pour construire un ensemble de tous les caractères uniques dans le puzzle.
unique_characters = set(''.join(words))
Cette liste est utilisée plus tard pour assigner des chiffres aux caractères ainsi le résolveur parcourt les solutions possibles.
Tout comme beaucoup de langages de programmation, Python a une instruction assert
. Voici comment elle fonctionne :
>>> assert 1 + 1 == 2 ①
>>> assert 1 + 1 == 3 ②
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
>>> assert 2 + 2 == 5, "Only for very large values of 2" ③
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: Only for very large values of 2
① L’instruction assert
est suivie de toute expression Python valide. Dans ce cas, l’expression 1 + 1 == 2
est évaluée à True
, l’instruction assert
ne fait rien.
② Toutefois, si l’expression Python est évaluée à False
, l’instruction assert
lèvera une AssertionError
.
③ Vous pouvez aussi inclure un message humainement compréhensible qui est affiché si AssertionError
est levée.
Donc, cette ligne de code :
assert len(unique_characters) <= 10, 'Too many letters'
… est équivalente à cela :
if len(unique_characters) > 10:
raise AssertionError('Too many letters')
Le résolveur alphamétique utilise l’instruction exacte assert
pour s’affranchir rapidement si le puzzle contient plus de dix lettres uniques. Puisque chaque lettre est assignée à un chiffre unique, et qu’il y a seulement dix chiffres, un puzzle avec plus de dix lettres uniques ne peut pas avoir de solution possible.
Un générateur d’expression est tout comme un générateur de fonction mais sans fonction.
>>> unique_characters = {'E', 'D', 'M', 'O', 'N', 'S', 'R', 'Y'}
>>> gen = (ord(c) for c in unique_characters) ①
>>> gen ②
<generator object <genexpr> at 0x00BADC10>
>>> next(gen) ③
69
>>> next(gen)
68
>>> tuple(ord(c) for c in unique_characters) ④
(69, 68, 77, 79, 78, 83, 82, 89)
① Un générateur d’expression est comme une fonction anonyme qui donne des valeurs. L’expression ressemble en elle-même à une liste de compréhension, mais elle est entourée de parenthèses au lieu de crochets.
② Le générateur d’expression retourne… un itérateur.
③ L’appel à next(gen)
retourne la valeur suivante dans l’itérateur.
④ Si vous le souhaitez, vous pouvez itérer au-travers toutes les valeurs possibles et retourner un tuple, une liste, ou un ensemble, en soumettant le générateur d’expression à tuple()
, list()
ou set()
. Dans ces cas, vous n’avez pas besoin de parenthèses supplémentaires – il suffit de passer l’expression ord(c) for c in unique_characters
telle qu’elle à la fonction tuple()
, et Python comprend que c’est un générateur d’expressions.
Utiliser un générateur d’expressions au lieu d’une liste de compréhension peut soulager à la fois le CPU et la RAM. Si vous construisez une liste pour juste la détruire ensuite (p. ex. pour la passer à tuple()
ou set()
), utilisez plutôt un générateur d’expression.
Voici une autre manière d’accomplir la même chose, en utilisant un générateur de fonction :
def ord_map(a_string):
for c in a_string:
yield ord(c)
gen = ord_map(unique_characters)
Le générateur d’expression est plus compact mais fonctionne de même manière.
Tout d’abord, que sont les permutations ? Les permutations sont un concept mathématique. (Il y a actuellement de nombreuses définitions, selon le type de maths que vous faites. Ici, je parle des combinatoires, mais si cela ne vous dit rien, ne vous inquiétez pas. Comme toujours, Wikipedia est votre ami).
L’idée est de prendre une liste de choses (qui peuvent être des nombres, des lettres, ou des ours dansants) et de trouver toutes les moyens possibles pour les scinder en petites listes. Toutes ces petites listes ont la même taille, qui peuvent aussi petites que 1 et aussi grandes que le nombre total des items.
Oh, rien ne doit être répété. Les mathématiciens disent des choses telles que « trouvons les permutations de 3 items différents pris 2 à la fois » ce qui signifie que vous avez une séquence de 3 items et que vous devez trouver toutes les paires ordonnées possibles.
>>> import itertools ①
>>> perms = itertools.permutations([1, 2, 3], 2) ②
>>> next(perms) ③
(1, 2)
>>> next(perms)
(1, 3)
>>> next(perms)
(2, 1) ④
>>> next(perms)
(2, 3)
>>> next(perms)
(3, 1)
>>> next(perms)
(3, 2)
>>> next(perms) ⑤
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
① Le module itertools
contient toutes sortes de choses amusantes, incluant la fonction permutations()
qui fait tout le travail difficile pour trouver les permutations.
② La fonction permutations()
prend une séquence (ici une liste de trois entiers) et un nombre, qui est le nombre d’items que vous voulez dans chaque petit groupe. La fonction retourne un itérateur, que vous pouvez utiliser dans une boucle for ou tout autre code qui itère. Ici, je vais parcourir l’itérateur manuellement pour afficher toutes les valeurs.
③ La première permutation de [1, 2, 3]
, qui prend 2 à la fois, est (1, 2)
.
④ Notez que les permutations sont ordonnées : (2, 1)
est différent de (1, 2)
.
⑤ C’est tout ! Ce sont toutes les permutations de [1, 2, 3]
qui prennent 2 à la fois. Les pairs telles que (1, 1)
et (2, 2)
ne seront jamais vues, parce qu’elles contiennent des répétitions qui ne sont pas des permutations valides.
La fonction permutations()
ne nécessite pas de liste. Elle peut prendre n’importe quelle séquence – même une chaîne.
>>> import itertools
>>> perms = itertools.permutations('ABC', 3) ①
>>> next(perms)
('A', 'B', 'C') ②
>>> next(perms)
('A', 'C', 'B')
>>> next(perms)
('B', 'A', 'C')
>>> next(perms)
('B', 'C', 'A')
>>> next(perms)
('C', 'A', 'B')
>>> next(perms)
('C', 'B', 'A')
>>> next(perms)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> list(itertools.permutations('ABC', 3)) ③
[('A', 'B', 'C'), ('A', 'C', 'B'),
('B', 'A', 'C'), ('B', 'C', 'A'),
('C', 'A', 'B'), ('C', 'B', 'A')]
① Une chaîne est juste une séquence de caractères. Dans le but de trouver des permutations, la chaîne ‘ABC’
est équivalente à la liste [‘A’, ‘B’, ‘C’]
.
② La première permutation de trois items [‘A’, ‘B’, ‘C’]
, qui prennent 3 à la fois, est (‘A’, ‘B’, ‘C’)
. Il y a cinq autres permutations. Les trois mêmes caractères dans chaque ordre imaginable.
③ Puisque la fonction permutations()
retourne toujours un itérateur, une manière facile de déboguer les permutations est de passer l’itérateur dans la fonction interne list()
pour voir toutes les permutations immédiatement.
itertools
>>> import itertools
>>> list(itertools.product('ABC', '123')) ①
[('A', '1'), ('A', '2'), ('A', '3'),
('B', '1'), ('B', '2'), ('B', '3'),
('C', '1'), ('C', '2'), ('C', '3')]
>>> list(itertools.combinations('ABC', 2)) ②
[('A', 'B'), ('A', 'C'), ('B', 'C')]
① La fonction itertools.product()
retourne un itérateur contenant le produit cartésien de deux séquences.
② La fonction itertools.combinations()
retourne un itérateur contenant toutes les combinaisons possibles d’une séquence donnée d’une longueur donnée. Tout comme la fonction itertools.permutations()
, excepté que les combinaisons n’incluent pas les items qui sont la copie d’autres items dans un ordre différent. Ainsi, itertools.permutations('ABC', 2)
retournera les deux ('A', 'B')
et ('B', 'A')
(entres autres), mais itertools.combinations('ABC', 2)
ne retournera pas ('B', 'A')
parce que c’est une copie de ('A', 'B')
dans un ordre différent.
>>> names = list(open('examples/favorite-people.txt', encoding='utf-8')) ①
>>> names
['Dora\n', 'Ethan\n', 'Wesley\n', 'John\n', 'Anne\n',
'Mike\n', 'Chris\n', 'Sarah\n', 'Alex\n', 'Lizzie\n']
>>> names = [name.rstrip() for name in names] ②
>>> names
['Dora', 'Ethan', 'Wesley', 'John', 'Anne',
'Mike', 'Chris', 'Sarah', 'Alex', 'Lizzie']
>>> names = sorted(names) ③
>>> names
['Alex', 'Anne', 'Chris', 'Dora', 'Ethan',
'John', 'Lizzie', 'Mike', 'Sarah', 'Wesley']
>>> names = sorted(names, key=len) ④
>>> names
['Alex', 'Anne', 'Dora', 'John', 'Mike',
'Chris', 'Ethan', 'Sarah', 'Lizzie', 'Wesley']
① Cet idiome retourne une liste à partir des lignes d’un fichier texte.
② Malheureusement (dans cet exemple), l’idiome list(open(filename))
inclus aussi le retour chariot à la fin de chaque ligne. Cette liste de compréhension utilise la méthode des chaînes rstrip()
pour effacer les espaces de fin de chaque ligne. (Les chaînes ont aussi une méthode lstrip()
pour supprimer les espaces en début, et une méthode strip()
qui supprime les deux).
③ La fonction sorted()
prend une liste et la retourne triée. Par défaut, le tri est alphabétique.
④ Mais la fonction sorted()
peut aussi prendre une fonction en tant que paramètre key
, elle est triée par la clé en question. Dans ce cas, la fonction de tri est len()
, ainsi elle est triée par len(each item)
. Les noms les plus courts sont en premier, puis de plus en plus longs.
Qu’est-ce que cela a à voir avec le module itertools
? Je suis content que vous le demandiez.
…continuing from the previous interactive shell…
>>> import itertools
>>> groups = itertools.groupby(names, len) ①
>>> groups
<itertools.groupby object at 0x00BB20C0>
>>> list(groups)
[(4, <itertools._grouper object at 0x00BA8BF0>),
(5, <itertools._grouper object at 0x00BB4050>),
(6, <itertools._grouper object at 0x00BB4030>)]
>>> groups = itertools.groupby(names, len) ②
>>> for name_length, name_iter in groups: ③
… print('Names with {0:d} letters:'.format(name_length))
… for name in name_iter:
… print(name)
…
Names with 4 letters:
Alex
Anne
Dora
John
Mike
Names with 5 letters:
Chris
Ethan
Sarah
Names with 6 letters:
Lizzie
Wesley
① La fonction itertools.groupby()
prend une séquence et une fonction clé, et retourne un itérateur qui génère des paires. Chaque paire contient le résultat de key_function(each item)
et un autre itérateur contient tous les items que partage la clé résultante.
② L’appel à la fonction list()
a « épuisé » l’itérateur, c’est-à-dire que vous avez déjà généré chaque élément de l’itérateur pour créer la liste. Il n’y a pas de bouton “reset” sur un itérateur ; vous ne pouvez pas juste le démarrer une fois qu’il est épuisé. Si vous voulez le parcourir encore par une boucle (dans une nouvelle boucle for
), vous devez appeler encore itertools.groupby()
pour créer un nouvel itérateur.
③ Dans cet exemple, à une liste donnée de noms toujours triée par longueur, itertools.groupby(names, len)
sortira tous les noms de 4 lettres dans un itérateur, tous les noms de 5 lettres dans un autre, et ainsi de suite. La fonction groupby()
est complètement générique ; elle peut regrouper les chaînes par première lettre, les nombres par nombre de facteurs ou toute autre fonction clé imaginable.
La fonction itertools.groupby()
fonctionne seulement si la séquence en entrée est déjà triée par la fonction de regroupement. Dans l’exemple ci-dessus, vous avez groupé une liste de noms par la fonction len()
. Cela a fonctionné parce que la liste entrée était déjà triée par longueur.
Regardez de plus prés !
>>> list(range(0, 3))
[0, 1, 2]
>>> list(range(10, 13))
[10, 11, 12]
>>> list(itertools.chain(range(0, 3), range(10, 13))) ①
[0, 1, 2, 10, 11, 12]
>>> list(zip(range(0, 3), range(10, 13))) ②
[(0, 10), (1, 11), (2, 12)]
>>> list(zip(range(0, 3), range(10, 14))) ③
[(0, 10), (1, 11), (2, 12)]
>>> list(itertools.zip_longest(range(0, 3), range(10, 14))) ④
[(0, 10), (1, 11), (2, 12), (None, 13)]
① La fonction itertools.chain()
prend deux itérateurs et retourne un itérateur qui contient tous les items du premier itérateur, suivis de ceux du second itérateur. (Actuellement, il peut prendre n’importe quel nombre d’itérateurs, et les enchaîner dans l’ordre où ils sont passés dans la fonction.)
② La fonction zip()
fait quelque chose de prosaïque qui s’avère extrêmement utile : elle prend n’importe quel nombre de séquences et retourne un itérateur qui retourne des tuples des premiers items de chaque séquence, ensuite les seconds items de chacune, puis les troisièmes, et ainsi de suite.
③ La fonction zip()
s’arrête à la fin de la plus petite séquence. range(10, 14)
a 4 items, mais range(10, 14)
en a seulement 3, ainsi la fonction zip()
retourne un itérateur de 3 items.
④ D’un autre côté, la fonction itertools.zip_longest()
s’arrête à la fin de la séquence la plus longue, insérant des valeurs None
pour les items passés en fin des séquences plus courtes.
Ok, tout cela est très intéressant, mais quel rapport cela a-t-il avec le résolveur d’alphamétique ? Voici comment :
>>> characters = ('S', 'M', 'E', 'D', 'O', 'N', 'R', 'Y')
>>> guess = ('1', '2', '0', '3', '4', '5', '6', '7')
>>> tuple(zip(characters, guess)) ①
(('S', '1'), ('M', '2'), ('E', '0'), ('D', '3'),
('O', '4'), ('N', '5'), ('R', '6'), ('Y', '7'))
>>> dict(zip(characters, guess)) ②
{'E': '0', 'D': '3', 'M': '2', 'O': '4',
'N': '5', 'S': '1', 'R': '6', 'Y': '7'}
① À une liste donnée de lettres et une liste de chiffres (chacune représentée ici sous forme de chaînes de 1 caractère), la fonction zip()
créera une paire de lettres et de chiffres, dans l’ordre.
② Pourquoi est-ce cool ? Parce que cette structure de données se trouve être exactement la bonne structure à transmettre à la fonction dict()
pour créer un dictionnaire qui utilise des lettres comme clés et leurs chiffres associés comme valeurs. (Ce n’est bien sûr pas la seule manière de faire cela. Vous pouvez utiliser un dictionnaire de compréhension pour créer directement le dictionnaire). Bien que la représentation imprimée du dictionnaire liste les paires dans un ordre différent (les dictionnaires n’ont pas d ‘«ordre» en soi), vous pouvez voir que chaque lettre est associée à un chiffre, en fonction de l’ordre d’origine des séquences characters
et guess
.
Le résolveur alphamétique utilise cette technique pour créer un dictionnaire qui fait correspondre chaque lettre dans le puzzle au chiffre, pour chaque solution possible.
characters = tuple(ord(c) for c in sorted_characters)
digits = tuple(ord(c) for c in '0123456789')
…
for guess in itertools.permutations(digits, len(characters)):
…
equation = puzzle.translate(dict(zip(characters, guess)))
Mais qu’est-ce la méthode translate()
?
Ahhh, vous arrivez maintenant la partie réellement amusante.
Les chaînes Python ont beaucoup de méthodes. Vous avez appris certaines de ces méthodes dans le chapitre Chaînes : lower()
, count()
, et format()
. Maintenant je veux vous présenter une technique de manipulation puissante mais peu connue : la méthode translate()
.
>>> translation_table = {ord('A'): ord('O')} ①
>>> translation_table ②
{65: 79}
>>> 'MARK'.translate(translation_table) ③
'MORK'
① La traduction des chaînes débute avec une table de traduction, qui est simplement un dictionnaire qui fait correspondre un caractère avec un autre. Actuellement “caractère” est incorrect - la table de traduction fait réellement correspondre un octet avec un autre.
② Rappelez-vous, les octets en Python 3 sont des entiers. La fonction ord()
retourne la valeur ASCII d’un caractère, qui, dans le cas de A-Z, est toujours un octet de 65 à 90.
③ La méthode translate()
sur une chaîne prend une table de traduction et la parcourt. Pour cela, elle remplace toutes les occurences des clés de la table de traduction avec les valeurs correspondantes. Dans ce cas, elle “traduit” MARK
en MORK
.
Qu’est-ce que cela a à voir avec la résolution de puzzles alphamétiques ? En fait, tout.
>>> characters = tuple(ord(c) for c in 'SMEDONRY') ①
>>> characters
(83, 77, 69, 68, 79, 78, 82, 89)
>>> guess = tuple(ord(c) for c in '91570682') ②
>>> guess
(57, 49, 53, 55, 48, 54, 56, 50)
>>> translation_table = dict(zip(characters, guess)) ③
>>> translation_table
{68: 55, 69: 53, 77: 49, 78: 54, 79: 48, 82: 56, 83: 57, 89: 50}
>>> 'SEND + MORE == MONEY'.translate(translation_table) ④
'9567 + 1085 == 10652'
① En utilisant un générateur d’expressions, nous calculons les valeurs d’octet pour chaque caractère d’une chaîne. characters
est un exemple de valeur de sorted_characters
dans la fonction alphametics.solve()
.
② En utilisant un autre générateur d’expression, nous calculons les valeurs d’octet de chaque chiffre dans la chaîne. Le résultat, guess
, est de la forme retournée par la fonction itertools.permutations()
dans la fonction alphametics.solve()
.
③ Cette table de traduction est générée par itération de characters
et de guess
ensemble et en construisant un dictionnaire depuis la séquence de pairs résultante. C’est exactement ce que fait la fonction alphametics.solve()
à l’intérieur de la boucle for
.
④ Enfin, nous passons cette table de traduction à la méthode translate()
du puzzle originale de la chaîne. Cela convertit chaque lettre dans la chaîne vers le chiffre correspondant (basé sur les lettres dans characters
et les chiffres dans guess
). Le résultat est une expression Python valide, tout comme l’est une chaîne.
C’est assez impressionnant. Mais que pouvez-vous faire avec une chaîne qui se trouve être une expression Python valide ?
Ceci est la pièce finale du puzzle (ou plutôt, la pièce finale du résolveur de puzzle). Après toutes ces manipulations sympathiques de chaînes, il nous reste une chaîne telle que '9567 + 1085 == 10652'
. Mais c’est une chaîne, et qu’est-ce qui est bon avec une chaîne ? Tapez eval()
, l’outil universel Python d’évaluation.
>>> eval('1 + 1 == 2')
True
>>> eval('1 + 1 == 3')
False
>>> eval('9567 + 1085 == 10652')
True
Mais attendez, il y a plus ! La fonction eval()
n’est pas limitée aux expressions booléennes. Elle peut capturer toute expression Python et retourner tout type de données.
>>> eval('"A" + "B"')
'AB'
>>> eval('"MARK".translate({65: 79})')
'MORK'
>>> eval('"AAAAA".count("A")')
5
>>> eval('["*"] * 5')
['*', '*', '*', '*', '*']
Mais attendez, ce n’est pas tout !
>>> x = 5
>>> eval("x * 5") ①
25
>>> eval("pow(x, 2)") ②
25
>>> import math
>>> eval("math.sqrt(x)") ③
2.2360679774997898
① L’expression que prend eval()
peut référencer des variables globales définies en-dehors d’ eval()
. Si elle est appelée dans une fonction, elle peut référencer des variables locales, aussi.
② Et des fonctions.
③ Et des modules.
Eh, attendez une minute…
>>> import subprocess
>>> eval("subprocess.getoutput('ls ~')") ①
'Desktop Library Pictures \
Documents Movies Public \
Music Sites'
>>> eval("subprocess.getoutput('rm /some/random/file')") ②
① Le module subprocess
vous permet d’exécuter arbitrairement des commandes shell et d’avoir le résultat en tant que chaîne Python.
② Arbitrairement les commandes shell peuvent avoir des conséquences permanentes.
C’est même pire que cela, parce qu’il y a la fonction globale __import__()
qui prend un nom de module en tant que chaîne, importe le module, et lui retourne une référence. Combinée à la puissance d’ eval()
, vous pouvez construire une expression simple qui supprimera tous vos fichiers :
>>> eval("__import__('subprocess').getoutput('rm /some/random/file')") ①
① Maintenant, imaginez la sortie de 'rm -rf ~'
. En fait, il n’y aurait pas de sortie, mais il ne resterait plus aucun fichier.
eval() is EVIL
Bien, la partie diabolique est d’évaluer arbitrairement des expressions depuis des sources non vérifiées. Vous ne devriez utiliser eval()
que sur une entrée de confiance. Bien sûr, le truc consiste à déterminer ce qui est «fiable». Mais voici quelque chose que je sais avec certitude : vous NE DEVRIEZ PAS prendre ce résolveur alphamétique et le mettre sur Internet en tant que petit service web sympa. Ne faites pas l’erreur de penser : “Mon Dieu, la fonction fait beaucoup de manipulation de chaîne avant d’obtenir une chaîne à évaluer ; je ne peux pas imaginer comment quelqu’un pourrait exploiter cela.” Quelqu’un comprendra comment passer furtivement du code exécutable nuisible après toute cette manipulation de chaîne (des choses étranges se sont produites), et vous pourrez alors dire adieu à votre serveur.
Mais il existe sûrement un moyen d’évaluer les expressions en toute sécurité ?
Mettre eval()
dans une sandbox où il ne peut accéder à rien ni endommager le reste du monde ?
Eh bien, oui et non.
>>> x = 5
>>> eval("x * 5", {}, {}) ①
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'x' is not defined
>>> eval("x * 5", {"x": x}, {}) ②
25
>>> import math
>>> eval("math.sqrt(x)", {"x": x}, {}) ③
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'math' is not defined
① Le second paramètre et le troisième passés à la fonction eval()
agissent dans les espaces de noms global et local pour évaluer l’expression. Dans ce cas, les deux sont vides, ce qui signifie alors que, quand la chaîne "x * 5"
est évaluée, il n’y a pas de référence à x
ni dans l’espace de nom global ou local, ainsi eval()
lève une exception.
② Vous pouvez sélectivement inclure des valeurs spécifiques dans l’espace de noms global en les listant individuellement. Alors ces variables - et seulement celles-là - seront disponibles durant l’évaluation.
③ Même si vous venez d’importer le module math
, vous ne pouvez l’inclure dans l’espace de noms à la fonction eval()
, ainsi l’évaluation échouera.
Pfff, c’était facile. Laissez-moi faire un service web alphamétique, maintenant !
>>> eval("pow(5, 2)", {}, {}) ①
25
>>> eval("__import__('math').sqrt(5)", {}, {}) ②
2.2360679774997898
① Même si vous avez passé des dictionnaires vides pour les espaces de noms global et local, toutes les fonctions internes de Python seront toujours disponibles durant l’évaluation. Ainsi pow(5, 2)
fonctionne, parce que 5
et 2
sont des littéraux, et que pow()
est une fonction interne.
② Malheureusement (et même si vous ne voyez pas pourquoi cela est malheureux, lisez la suite), la fonction __import__()
est aussi une fonction interne, ainsi cela fonctionne aussi.
Oui, cela signifie que vous pouvez toujours faire des choses méchantes, même si vous configurez explicitement les espaces de noms global et local pour vider les dictionnaires lors de l’appel à eval()
:
>>> eval("__import__('subprocess').getoutput('rm /some/random/file')", {}, {})
Oups. Je suis heureux de ne pas avoir créer de service web alphamétique.
N’y a-t-il aucun moyen d’utiliser eval()
de manière sécurisée ?
Eh bien, oui et non.
>>> eval("__import__('math').sqrt(5)",
… {"__builtins__":None}, {}) ①
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name '__import__' is not defined
>>> eval("__import__('subprocess').getoutput('rm -rf /')",
… {"__builtins__":None}, {}) ②
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name '__import__' is not defined
① Pour évaluer des expressions non vérifiées de manière sûre, vous avez besoin de définir un dictionnaire d’espace de noms global qui fait correspondre "__builtins__"
à None
, une valeur Python null
. En interne, les fonctions “built-in” sont contenues dans un pseudo-module appelé "__builtins__"
. Ce pseudo-module (càd l’ensemble des fonctions internes) est rendu disponible aux expressions évaluées à moins que vous les surchargiez explicitement.
② Soyez sûr que vous surchargiez __builtins__
. Non pas __builtin__
, __built-ins__
, ou toute autre variation qui fonctionnera parfaitement mais qui vous expose à des risques catastrophiques.
Ainsi, eval()
est sûr maintenant ?
Eh bien, oui et non.
>>> eval("2 ** 2147483647",
… {"__builtins__":None}, {}) ①
① Même sans accéder à __builtins__
, vous pouvez toujours lancer une attaque par déni de service. Par exemple, essayer de lever 2
à la puissance 2147483647
augmentera l’utilisation du CPU de votre serveur à 100% pendant un certain temps. (Si vous essayez cela dans un terminal interactif, appuyez plusieurs fois sur Ctrl-C
pour en sortir.) Techniquement cette expression retournera éventuellement une valeur, mais en attendant, votre serveur fera plus rien d’autres.
Enfin, il est possible d’évaluer en toute sécurité des expressions Python non vérifiées, pour une définition du terme «sûr» qui ne s’avère pas très utile dans la vie réelle. C’est bien si vous vous contentez de jouer, et c’est bien si vous ne transmettez que des données fiables. Mais tout autre ne fait que provoquer des ennuis.
Pour récapituler : ce programme résoud des puzzles alphamétiques par force brute, càd, par une recherche exhaustive de toutes les solutions possibles Pour faire cela, il faut…
re.findall()
set()
assert
itertools.permutations()
translate()
eval()
True
… en seulement 14 lignes de code.
itertools
itertools
- Fonctions d’Itérateur pour boucles efficientesTout plein de remerciements à Raymond Hettinger pour son accord à modifier la licence de son code, ainsi j’ai pu le porter vers Python 3 et l’utiliser comme base de ce chapitre.
© 2001–11 Mark Pilgrim
*[ASCII]: American Standard Code for Information Interchange - Code américain normalisé pour l’échange d’information *[CPU]: Central Processing Unit - Processeur *[RAM]: Random Access Memory - Mémoire Vive *[càd]: c’est-à-dire
]]>Il est en effet possible de créer des clés GPG en utilisant l’algorithme à courbe elliptique ED25519.
Ce tutoriel fait suite à ce guide de bonnes pratiques de création ; d’ailleurs une fois la création terminée, referez-vous y à nouveau.
Avant, assurez-vous d’avoir correctement sécurisé votre configuration GPG !
Bien veiller à choisir à la création de clé, l’option (9) ECC et ECC
- et ensuite, le
type de courbe elliptique désiré - option (1) Curve 25519
.
Pour l’instant, c’est la seule possibilité de faire.
Pour cela, il faut utiliser l’option --full-gen-key
suivie de l’option --expert
.
Code : sh
$ gpg --full-gen-key --expert
gpg (GnuPG) 2.2.10; Copyright (C) 2018 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Sélectionnez le type de clef désiré :
(1) RSA et RSA (par défaut)
(2) DSA et Elgamal
(3) DSA (signature seule)
(4) RSA (signature seule)
(7) DSA (indiquez vous-même les capacités)
(8) RSA (indiquez vous-même les capacités)
(9) ECC et ECC
(10) ECC (signature seule)
(11) ECC (indiquez vous-même les capacités)
(13) Clef existante
Quel est votre choix ? 9
Sélectionnez le type de courbe elliptique désiré :
(1) Curve 25519
(3) NIST P-256
(4) NIST P-384
(5) NIST P-521
(6) Brainpool P-256
(7) Brainpool P-384
(8) Brainpool P-512
(9) secp256k1
Quel est votre choix ? 1
Veuillez indiquer le temps pendant lequel cette clef devrait être valable.
0 = la clef n'expire pas
<n> = la clef expire dans n jours
<n>w = la clef expire dans n semaines
<n>m = la clef expire dans n mois
<n>y = la clef expire dans n ans
Pendant combien de temps la clef est-elle valable ? (0) 2y
La clef expire le Thu Jan 7 14:58:16 2021 CET
Est-ce correct ? (o/N) o
GnuPG doit construire une identité pour identifier la clef.
Nom réel : Stéphane HUC
Adresse électronique : ***@stephane-huc.net
Commentaire :
Vous utilisez le jeu de caractères « utf-8 ».
Vous avez sélectionné cette identité :
« Stéphane HUC <***@stephane-huc.net> »
Changer le (N)om, le (C)ommentaire, l'(A)dresse électronique
ou (O)ui/(Q)uitter ? o
De nombreux octets aléatoires doivent être générés. Vous devriez faire
autre chose (taper au clavier, déplacer la souris, utiliser les disques)
pendant la génération de nombres premiers ; cela donne au générateur de
nombres aléatoires une meilleure chance d'obtenir suffisamment d'entropie.
De nombreux octets aléatoires doivent être générés. Vous devriez faire
autre chose (taper au clavier, déplacer la souris, utiliser les disques)
pendant la génération de nombres premiers ; cela donne au générateur de
nombres aléatoires une meilleure chance d'obtenir suffisamment d'entropie.
gpg: clef 0x*********** marquée de confiance ultime.
gpg: revocation certificate stored as '/home/***/.gnupg/openpgp-revocs.d/***.rev'
les clefs publique et secrète ont été créées et signées.
pub ed25519/0x*********** 2019-01-08 [SC] [expire : 2021-01-07]
Empreinte de la clef = **** **** **** **** **** ****
uid Stéphane HUC <***@stephane-huc.net>
sub cv25519/0x********** 2019-01-08 [E] [expire : 2021-01-07]
Pour modifier une clé GPG, on utilise l’option --edit-key
toujours suivie de l’option --expert
.
L’action à utiliser est : addkey
Veillez à bien choisir l’option (10) ECC (signature seule)
puis l’option (1) Curve 25519
.
Code : sh
$ gpg2 --edit-key --expert "fingerprint"
gpg (GnuPG) 2.2.12; Copyright (C) 2018 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
La clef secrète est disponible.
sec ed25519/0x****************
créé : 2020-01-30 expire : 2022-01-29 utilisation : SC
confiance : ultime validité : ultime
ssb cv25519/0x****************
créé : 2020-01-30 expire : 2022-01-29 utilisation : E
[ ultime ] (1). Nom Prenom <email@domain.tld>
gpg> addkey
Sélectionnez le type de clef désiré :
(3) DSA (signature seule)
(4) RSA (signature seule)
(5) Elgamal (chiffrement seul)
(6) RSA (chiffrement seul)
(7) DSA (indiquez vous-même les capacités)
(8) RSA (indiquez vous-même les capacités)
(10) ECC (signature seule)
(11) ECC (indiquez vous-même les capacités)
(12) ECC (chiffrement seul)
(13) Clef existante
Quel est votre choix ? 10
Sélectionnez le type de courbe elliptique désiré :
(1) Curve 25519
(3) NIST P-256
(4) NIST P-384
(5) NIST P-521
(6) Brainpool P-256
(7) Brainpool P-384
(8) Brainpool P-512
(9) secp256k1
Quel est votre choix ? 1
Veuillez indiquer le temps pendant lequel cette clef devrait être valable.
0 = la clef n'expire pas
<n> = la clef expire dans n jours
<n>w = la clef expire dans n semaines
<n>m = la clef expire dans n mois
<n>y = la clef expire dans n ans
Pendant combien de temps la clef est-elle valable ? (0)
La clef n'expire pas du tout
Est-ce correct ? (o/N) o
Faut-il vraiment la créer ? (o/N) o
De nombreux octets aléatoires doivent être générés. Vous devriez faire
autre chose (taper au clavier, déplacer la souris, utiliser les disques)
pendant la génération de nombres premiers ; cela donne au générateur de
nombres aléatoires une meilleure chance d'obtenir suffisamment d'entropie.
sec ed25519/0x****************
créé : 2020-01-30 expire : 2022-01-29 utilisation : SC
confiance : ultime validité : ultime
ssb cv25519/0x****************
créé : 2020-01-30 expire : 2022-01-29 utilisation : E
ssb ed25519/0x****************
créé : 2020-01-30 expire : jamais utilisation : S
[ ultime ] (1). Nom Prenom <email@domain.tld>
gpg> save
L’action à utiliser est : setpref SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed
Code : sh
$ gpg2 --edit-key --expert "fingerprint"
gpg (GnuPG) 2.2.12; Copyright (C) 2018 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
La clef secrète est disponible.
sec ed25519/0x****************
créé : 2020-01-30 expire : 2022-01-29 utilisation : SC
confiance : ultime validité : ultime
ssb cv25519/0x****************
créé : 2020-01-30 expire : 2022-01-29 utilisation : E
ssb ed25519/0x****************
créé : 2020-01-30 expire : jamais utilisation : S
[ ultime ] (1). Nom Prenom <email@domain.tld>
gpg> setpref SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed
Définir la liste de préférences en :
Chiffrement : AES256, AES192, AES, 3DES
Hachage : SHA512, SHA384, SHA256, SHA1
Compression : ZLIB, BZIP2, ZIP, Non compressé
Fonctionnalités : MDC, Serveur de clefs sans modification
Faut-il vraiment mettre à jour les préférences ? (o/N) o
sec ed25519/0x****************
créé : 2020-01-30 expire : 2022-01-29 utilisation : SC
confiance : ultime validité : ultime
ssb cv25519/0x****************
créé : 2020-01-30 expire : 2022-01-29 utilisation : E
ssb ed25519/0x****************
créé : 2020-01-30 expire : jamais utilisation : S
[ ultime ] (1). Nom Prenom <email@domain.tld>
gpg> save
Et, maintenant, pensez à :
Du fait de fonctionner sous OpenBSD, la commande occ
ne peut pas s’exécuter. En effet, autant le service web que PHP sont tous les deux sous chroot.
Quand vous exécutez occ
, vous obtenez le message d’erreur suivant :
Code : sh
Your data directory is invalid
Ensure there is a file called ".ocdata" in the root of the data directory.
Cannot create "data" directory
This can usually be fixed by giving the webserver write access to the root directory. See https://docs.nextcloud.com/server/16/go.php?to=admin-dir_permissions
Résoudre ce problème est simple !
Éditez le fichier de configuration nextcloud/config/config.php
et modifiez la valeur de la variable datadirectory
, tel que :
'datadirectory' => ((php_sapi_name() == 'cli') ? '/var/www' : '') . '/htdocs/data',
Bien-sûr le chemin /htdocs/data
doit correspondre à votre cas réel.
Maintenant vous pouvez utiliser sans soucis la commande occ
Néanmoins, n’oubliez pas de supprimez la modification avant d’utiliser l’interface web, sinon vous ne pourrez pas vous connecter !
Problème remarqué par mes soins : lors du redémarrage du service PHP et/ou web, cela tend à récrire la variable en préfixant la variable datadirectory de /var/www/, empêchant le bon fonctionnement du site web, et provoquant une erreur 500. Si c’est votre cas, ré-éditez le fichier de config et supprimez le préfixe en question.
Plus simple :
sed -i -e 's#/htdocs#/var/www/htdocs#' nextcloud/config/config.php
sed -i -e 's#/var/www/htdocs#/htdocs#' nextcloud/config/config.php
Je tiens à remercier @h3artbl33d qui a trouvé l’astuce… car pendant des mois, cela m’a empêché d’utiliser la commande occ
.
Un article concernant l’amélioration de la Performance de Firefox !
Dans la barre d’adresse, tapez la commande about:config
puis nous
allons mettre en place différentes informations :
Préférez mettre ces options sur true
- il est probable que FF utilise
déjà ces options
layers.acceleration.force-enabled
layers.async-video.enabled
layers.offmainthreadcomposition.async-animations
layers.offmainthreadcomposition.enabled
html5.offmainthread
webgl.force-enabled
layout.frame_rate.precise
- peut atténuer le défilement instable - préférez sur true
image.mem.max_decoded_image_kb
- l’impact du nombre d’images compressées
gérées par FF ; plus la valeur est haute, plus cela améliore la vitesse,
au dépend de l’utilisation mémoire.javascript.options.mem.max
: limite la mémoire que Javascript peut
consommer - une valeur -1
signifie une gestion automatiquejavascript.options.mem.high_water_mark
: demande au “Garbage Collector” -
purgeur de mémoire de démarrer quand Javascript atteint tel nombre de mémoirebrowser.cache.memory.capacity
: limite la taille de la mémoire cache, en Mobrowser.download.animateNotifications
: désactive ou non les notifications
de téléchargement - préférez sur false
browser.sessionhistory.max_entries
: limite le nombre maximum de pages
gardées en mémoire dans l’historique de la session.browser.sessionstore.max_tabs_undo
: limite le nombre maximum d’onglets
fermés que vous pouvez ouvrir à nouveaubrowser.tabs.animate
: désactive ou non les animations des onglets -
préférez sur false
config.trim_on_minimize
: réduite l’usage de la mémoire lorsque la
fenêtre est minimisée - préférez sur true
- (utile que sous Windows)Lire les manpages n’est pas forcément agréable, voire aisé - heureusement il est possible avec des outils natifs à OpenBSD de les agrémenter pour en faire une sortie html, markdown, pdf, postscript puis de les lire dans un lecteur adéquat.
De petites fonctions pertinentes à se rajouter dans son ~/.kshrc
qui
utilisent principalement l’outil mandoc
.
Dans tous les cas, il est possible de modifier à souhait la variable
editor
:
Testé avec firefox, links+.
Code : sh
man2html() {
editor=firefox
[ -n "$1" ] && name="$1"
[ -z "$2" ] && ext="1" || ext="$2"
tmp="/tmp/$name.$ext.html"
for dir in /usr/share/man /usr/local/man /usr/X11R6/man; do
[ -f "$dir/man$ext/$name.$ext" ] && { file="$dir/man$ext/$name.$ext"; break; }
done
[ -f "$file" ] && mandoc -K utf-8 -T html -O toc "$file" > "$tmp"
[ -f "$tmp" ] && $editor "$tmp"
unset editor ext file name tmp`
}
man2html nom-manpage numero-section-manpage
- s’il n’y a pas de
numéro de section, alors la fonction essaye d’appeler le manpage de la
section 1.
Exemple : $ man2html man
Testé avec geany
Code : sh
man2md() {
editor=geany
[ -n "$1" ] && name="$1"
[ -z "$2" ] && ext="1" || ext="$2"
tmp="/tmp/$name.$ext.md"
for dir in /usr/share/man /usr/local/man /usr/X11R6/man; do
[ -f "$dir/man$ext/$name.$ext" ] && { file="$dir/man$ext/$name.$ext"; break; }
done
[ -f "$file" ] && mandoc -K utf-8 -T markdown "$file" > "$tmp"
[ -f "$tmp" ] && $editor "$tmp"
unset editor ext file name tmp`
}
man2md nom-manpage numero-section-manpage
- s’il n’y a pas de numéro
de section, alors la fonction essaye d’appeler le manpage de la section 1.
Exemple : $ man2md hostname.if 5
Testé avec evince.
Code : sh
man2pdf() {
editor=evince
[ -n "$1" ] && name="$1"
[ -z "$2" ] && ext="1" || ext="$2"
tmp="/tmp/$name.$ext.pdf"
for dir in /usr/share/man /usr/local/man /usr/X11R6/man; do
[ -f "$dir/man$ext/$name.$ext" ] && { file="$dir/man$ext/$name.$ext"; break; }
done
[ -f "$file" ] && mandoc -K utf-8 -T pdf "$file" > "$tmp"
[ -f "$tmp" ] && $editor "$tmp" && rm -fP "$tmp"
unset editor ext file name tmp`
}
man2pdf nom-manpage numero-section-manpage
- s’il n’y a pas de
numéro de section, alors la fonction essaye d’appeler le manpage de la
section 1.
Exemple : $ man2pdf man.conf 5
Testé avec gs, ghostview
Code : sh
man2ps() {
editor=gs
[ -n "$1" ] && name="$1"
[ -z "$2" ] && ext="1" || ext="$2"
tmp="/tmp/$name.$ext.ps"
for dir in /usr/share/man /usr/local/man /usr/X11R6/man; do
[ -f "$dir/man$ext/$name.$ext" ] && { file="$dir/man$ext/$name.$ext"; break; }
done
[ -f "$file" ] && mandoc -K utf-8 -T ps "$file" > "$tmp"
[ -f "$tmp" ] && $editor "$tmp"
unset editor ext file name tmp`
}
man2ps nom-manpage numero-section-manpage
- s’il n’y a pas de numéro
de section, alors la fonction essaye d’appeler le manpage de la section 1.
Exemple : $ man2ps dhclient 8
LA fonction qui réunit toutes les précédentes !!!
Code : sh
man2doc() {
#ed2html=firefox
#ed2md=geany
#ed2pdf=evince
#ed2ps=gs
[ -n "$1" ] && format="$1"
[ -n "$2" ] && name="$2"
[ -z "$3" ] && nb="1" || nb="$3"
#eval "editor=\${ed2$format}"
tmp="/tmp/$name.$nb.$format"
[ -f "$tmp" ] && rm -fP "$tmp"
case "$format" in
"md") type="markdown" ;;
*) type="$format" ;;
esac
for file in $(find /usr/{local,share,X11R6}/man/ -name $name.$nb); do mandoc -K utf-8 -T "$type" "$file" >> "$tmp"; done
[ -f "$tmp" ] && xdg-open "$tmp" # $editor
unset editor file format name nb tmp
}
À la différence des précédentes fonctions, cette dernière cherchera tous les manpages correspondants, et les incluera les uns à la suite des autres…
man2doc format-fichier nom-manpage numero-section-manpage
.
format-fichier
: html
, md
, pdf
, ou ps
Exemples :
$ man2doc html man
$ man2doc pdf doas.conf 5
$ man2doc md makewhatis 8
$ man2doc ps vmm 4
Inspiré par Mi@mondo
La virtualisation de machine virtuelle sous OpenBSD est officiellement disponible nativement dans le système de base depuis OpenBSD 5.9. Néanmoins, la FAQ Virtualisation (EN, FR) apparaît à partir d’OpenBSD 6.4 - (preuve d’une certaine maturité !?)
ATTENTION : Ce tutoriel ne documente pas dans les moindres détails les phases d’installation, voire de configuration.
Il est VRAIMENT nécessaire de faire preuve de réflexion, discernement et d’avoir un minimum de compétences, pour comprendre les liens entre les différentes briques !
Merci de votre compréhension…
Il existe au moins deux manières d’installer Debian dans une VM.
Pour information, les commandes précédées du symbole $
sont à
exécuter en tant qu’utilisateur ; celles précédées du symbole #
le
sont avec des droits administrateurs, soit en tant que root, soit par
l’usage de la commande
doas
.
vether0
de l’hôte aura pour adresse IPv4 : 192.168.0.1
, cette adresse IP sera l’adresse de la passerelle pour l’interface réseau de la VM.enp0s3
de la VM Debian aura pour adresse IPv4 : 192.168.0.2
…/etc/resolv.conf
de la VM de Debian est, par convention 1.1.1.1
. C’est celui de Cloudfare. Mais il peut être très bien tout autre, pourvu qu’il soit respectueux de la confidentialité… tel que ceux de Quad9, par exemple !Il est nécessaire que votre machine sur laquelle vous souhaitez virtualiser ait un CPU compatible avec les fonctions adéquates. Pour le vérifier, tapez dans votre terminal/console la commande suivante :
$ dmesg | egrep '(VMX/EPT|SVM/RVI)'
La réponse du système doit être :
⇒ pour CPU Intel :
vmm0 at mainbus0: VMX/EPT
⇒ pour CPU Amd :
vmm0 at mainbus0: SVM/RVI
Si aucune ligne n’apparaît, aucune virtualisation ne sera possible. Par acquis de conscience, vérifiez votre BIOS|UEFI que celle-ci ne soit pas désactivée.
De même, en rapport avec les failles CPU relatives à Meltdown, Spectre, certains CPU Intel sont patchés pour remédier à L1TF. Sous OpenBSD, ces CPU reçoivent un correctif approprié. Malheureusement, cela impacte la virtualisation et rend celle-ci impossible. Vous pouvez vous retrouver dans la situation où vous auriez un CPU compatible, mais dans les faits, la virtualisation ne pourrait être pleinement fonctionnelle.
Préférez AMD, en attendant ARM…
Il est nécessaire d’installer le firmware vmm
pour que le kernel gère.
# fw_update vmm
Par convention, créons un répertoire vm dans notre répertoire
personnel, et nous travaillerons à partir de celui-ci :
$ mkdir vm && cd vm
Bien-sûr, vous pouvez travailler à partir de n’importe quel répertoire - débrouillez-vous !
Dans les deux cas présentés, nous commencerons par créer la VM, très
simplement avec l’outil natif à OpenBSD, nommé vmctl :
# vmctl create ~/vm/debian.qcow2 -s 10G
(bien-sûr, vous pouvez changer la taille de la nouvelle VM en spécifiant une autre…)
Ensuite, téléchargeons l’iso Debian :
$ ftp https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/{debian-9.7.0-amd64-netinst.iso,SHA512SUMS}
Une fois téléchargée, vérifions sa somme de contrôle :
$ sha512 -C SHA512SUMS debian-9.7.0-amd64-netinst.iso
(SHA512) debian-9.7.0-amd64-netinst.iso: OK
Si OK, alors c’est bon… sinon, re-téléchargez !
Cette méthode est la plus facile, mais non conventionnelle.
Pour pouvoir créer une VM avec cette méthode (ou tout autre
distribution GNU/Linux dedans…), il est nécessaire d’utiliser le
paquet qemu : # pkg_add qemu
Puis exécutez qemu pour faire l’installation de Debian dans la VM -
que nous ne détaillerons pas, puisque c’est exactement comme sur
toute machine permettant de faire fonctionner Debian :
$ qemu-system-x86_64 -hda ~/vm/debian.qcow2 -cdrom debian*.iso -boot d
à un détail près est qu’il vaut mieux à la fin de l’installation de
Debian ne pas redémarrer par le biais de l’installateur Debian, mais de
choisir le menu ’exit’ pour venir dans le shell, et d’exécuter la
commande : # halt
- ou son équivalent # shutdown -h now
- qui
permettra d’arrêter proprement la VM.
Ensuite, passons à la configuration
…
puis démarrons la VM debian : $ vmctl start debian -c
Puis une fois connecté, avec des droits administrateurs, il faut
modifier le fichier /etc/defaut/grub
de telle manière :
Fichier : /etc/default/grub
|
|
Puis de mettre à jour grub : # update-grub
Redémarrez votre debian, et profitez de son usage !
Une fois terminée, vous pouvez en finir avec la configuration… Voilà !
Cette méthode est un peu plus “sioux”, mais ne nécessite que des outils natifs à OpenBSD.
Nous allons utiliser l’image de démarrage avec le fichier initrd modifié pour Xen pour fonctionner avec…
Téléchargeons les fichiers nécessaires :
Code : sh
$ ftp http://ftp.debian.org/debian/dists/stretch/main/installer-amd64/current/images/hd-media/boot.img.gz
$ ftp http://ftp.debian.org/debian/dists/stretch/main/installer-amd64/current/images/netboot/xen/initrd.gz
$ ftp http://ftp.debian.org/debian/pool/main/l/linux/virtio-modules-4.9.0-8-amd64-di_4.9.135-1_amd64.udeb
virtio-modules
pourrait avoir changé… donc
parcourez le site
Debian
pour trouver la version la plus récente !Occupons-nous des différents phases de décompression des trois fichiers téléchargés :
Code : sh
$ gzip -d initrd.gz
$ mkdir stable
$ cd stable
$ ar -x ../virtio-modules-4.9.0-**-1_amd64.udeb data.tar.xz <= remplacez par le nom du paquet `virtio-modules` que vous avez téléchargé !
$ xz -d data.tar.xz
$ tar xf data.tar
$ rm data.tar
$ find . | cpio -o -A -H sv4cpio -O ../initrd
$ cd ..
$ gzip -9 initrd
$ gzip -d boot.img.gz
Il nous faut monter le fichier boot.img
afin de faire les
modifications systèmes nécessaires :
Code : sh
# vnconfig vnd1 ~/vm/boot.img
# mount /dev/vnd1i /mnt
# cp initrd.gz /mnt/INITRD.GZ
# sed -i -e "s/\(.*\)append vga=788 initrd=initrd.gz --- quiet/\1append vga=off initrd=initrd.gz --- quiet console=ttyS0,115200n8/" /mnt/TXT.CFG
# umount /mnt
# vnconfig -u vnd1
Ensuite, passons à la configuration … puis, démarrons la VM install.
$ vmctl start install -c
Lorsque le menu d’installation est affiché, choisir Install, puis une fois dans l’installateur, appuyez sur la touche ESC/ECHAP pour choisir le menu Execute a shell.
Une fois dans le shell, il faut taper les commandes qui suivent :
Code : sh
depmod
modprobe virtio_pci virtio_blk
lsmod
exit
puis, continuer la phase d’installation selon vos besoins.
Une fois l’installation terminée, ne redémarrez pas par le biais de
l’installateur, choisissez à nouveau d’exécuter le shell, puis écrivez
la commande : # halt
afin d’arrêter la VM proprement !
Maintenant, il faut démarrer la VM debian : $ vmctl start debian -c
afin de pouvoir voir le menu de Grub et l’éditer - si vous le ratez, vous démarrez en mode initramfs
et vous serez bon pour recommencer à démarrer la VM afin d’arriver à éditer le Grub !
Il faut éditer le menu Grub ; tapez sur la touche e puis
cherchez toutes les occurrences de vdb
pour les transformer en vda
-
ne touchez pas au numéro qui suit
, autrement vous vous
retrouveriez au prochain démarrage avec le même problème que décrit
ci-dessus… Une fois modifié, appuyez sur les touches
CTRL+x pour sortir de l’éditeur de Grub et démarrez le
système Debian fraîchement installé !
Une fois connecté, avec des droits administrateurs, il faut éditer le
fichier /boot/grub/grub.cfg
pour remplacer les mêmes occurrences de
vdb
en vda
, puis d’exécuter la commande update-grub
.
Pour finir, il faut éditer le fichier /etc/network/interfaces
pour
remplacer le nom de l’interface enp0s4
par enp0s3
:
# sed -i -e 's/enp0s4/enp0s3/' /etc/network/interfaces
Maintenant vous pouvez redémarrer votre système Debian pour en profiter convenablement !
Une fois terminée, vous pouvez en finir avec la configuration… Voilà !
Le fichier de configuration se trouve être /etc/vm.conf
. Il faut
écrire votre compte identifiant dans la variable USER
, cela permettra
à votre utilisateur d’utiliser l’outil vmctl
…
Fichier : /etc/vm.conf
|
|
Vérifiez la configuration à l’aide de l’option -n
de vmd :
$ vmd -n
Après avoir configuré les interfaces réseaux
, il faudra démarrer le
service vmd
.
Il est assurément utile de s’occuper de la traduction d'adresses réseaux , et aussi des règles du parefeu …
Créons les interfaces réseaux nécessaires que sont vether0
et
bridge0
qui permettront un contrôle fin de l’adressage IP et des
règles PF.
Pour l’interface vether0
, il est possible d’utiliser n’importe
quelle classe privée IPv4 (A: 10.0/8 ; B: 172.0.0/16 ; C:
192.168.0.0/24) - nous utiliserons un type de classe C privée, telle
que 192.168.0.x*
. Après tout, nous n’avons pas plus de 256 VM à administrer… ;)
Le fichier relatif est /etc/hostname.bridge0
: add vether0
Le fichier relatif est /etc/hostname.vether0
: inet 192.168.0.1 255.255.255.0
Une fois les fichiers d’interfaces créés, donnez des droits 0600 dessus, puis démarrez les deux interfaces :
# chmod 0600 /etc/hostname.{bridge,vether}0
# sh /etc/netstart {bridge,vether}0
Pour nous faciliter la vie avec notre futur VM, nous allons autoriser la redirection des paquets IP, pour qu’elle puisse communiquer sur Internet - ne serait-ce que pour faire les mises à jour…
Dans un terminal/console, écrivez :
# sysctl net.inet.ip.forwarding=1
# sysctl net.inet6.ip6.forwarding=1
La première ligne est pour IPv4, la seconde pour IPv6.
Puis, pour garder les paramètres au redémarrage, modifiez le fichier
/etc/sysctl.conf
pour ajouter :
net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1
Il sera ensuite nécessaire de modifier le fichier /etc/pf.conf ajouter au moins les règles suivantes :
Fichier : /etc/pf.conf
|
|
vether0
doit être traduit (NATé) vers les adresses IP faisant partie du groupe egress
domain
(port 53
) sur les protocoles udp
et tcp
depuis le réseau lié à l’interface vether0
soit redirigé vers le service en question. L’adresse IPv4 1.1.1.1
est celle du serveur DNS de Cloudflare ; elle peut être très bien celle de tout autre serveur DNS.vether0
depuis l’interface locale
vers ailleurs…vether0
vers partout !Une fois que vous avez fini l’installation de Debian dans votre VM, que
vous avez fait les derniers réglages nécessaires pour son bon
fonctionnement, vous pouvez faire deux choses utiles liés à l’édition
du fichier /etc/vm.conf
:
install
…disable
par enable
pour la VM debian
- si vous désirez que la VM correspondante démarre, soit lors du démarrage de votre machine, si et seulement si le service vmd
est bien actif et démarré lors du processus de démarrage machine, soit lorsque vous redémarrez le service vmd
lui-même par vos soins.Un tout petit laïus sur la commande vmctl : $ man vmctl
pour
découvrir les différentes options bien utiles, dont show, status,
start, et stop qu’il semble nécessaire de maîtriser !
Vous n’avez tout simplement pas installé le firmware vmm !
Enjoy-IT! Enjoy-ID!
Nextcloud est un logiciel de nuage informatique afin de partager depuis et sur Internet des fichiers mais aussi un ou plusieurs agendas, des contacts, des notes, etc… de manière modulaire.
ATTENTION : Ce tutoriel ne documente pas dans les moindres détails les phases d’installation, voire de configuration. Ce n’est pas accessible aux nouveaux utilisateurs d’OpenBSD…
Il est VRAIMENT nécessaire de faire preuve de réflexion, discernement et d’avoir un minimum de compétences, pour comprendre les liens entre les différentes briques !
Merci de votre compréhension - ne venez pas pleurer ; ne cherchez pas à me contacter par quelques moyens existants - venez vous faire aider amicalement sur le forum de la communauté obsd4a !
Installez le paquet nextcloud.
Par convention, disons que nous déposerons l’archive dans le répertoire
/var/www/htdocs/nextcloud
- que vous pouvez/devez modifier/adapter à votre besoin…
# mkdir /var/www/htdocs/nextcloud
$ cd /var/www/htdocs/nextcloud
Téléchargeons l’archive et le fichier de sommes de contrôle sha256 adéquate :
$ ftp https://download.nextcloud.com/server/releases/nextcloud-17.0.1.zip{,.sha256}
Puis vérifions que l’archive est bien téléchargée :
$ sha256 -C nextcloud-*.sha256
(SHA256) nextcloud-17.0.1.zip: OK
Si le message est identique, alors l’archive téléchargée est bonne. Nous pouvons donc l’utiliser :
$ unzip nextcloud*.zip
# mv nextcloud /var/www/htdocs/
# chown -R www:daemon /var/www/htdocs/nextcloud
Il est nécessaire d’installer les paquets PHP suivants, tels que : php-bz2 php-curl php-gd php-pdo_sqlite php-intl php-zip pecl72-redis redis libmcrypt oniguruma icu4c-wwwdata
pecl7*-redis
!Certaines options de Nextcloud nécessitent la gestion de bibliothèque cryptographique ; il nous faut installer la libsodium
pecl7*-libsodium
(où 7* est à remplacer par le numéro de version de PHP-7) - qui n’existe plus dès PHP 7.3, car ce dernier gére correctement la libsodium.Ensuite, il faut activer les différentes extensions :
cd /etc/php-7.3.sample
for i in *; do ln -sf ../php-7.3.sample/$i ../php-7.2/; done
Puis, redémarrer le service PHP-FPM.
Activer le service le service PHP-FPM php73_fpm !
Par défaut, Nextcloud fonctionne avec sqlite ; veillez à ce que le package nécessaire soit installé : sqlite3 php-pdo_sqlite php-pdo_odbc
Néanmoins Nextcloud fonctionne aussi avec les bases de données MySQL/MariaDB, PostgreSQL… à vous de choisir et d’installer les paquets correspondants !
Dans tous les cas, il faudra activer les nouvelles extensions php et redémarrer le service adhoc.
La documentation officielle de Nextcloud pour nginx étant bien faite, je vous laisse la regarder !
Faites simplement attention à bien changer la valeur de root
pour
qu’elle corresponde à votre racine, ici /var/www/htdocs/nextcloud
et
à adaptez le reste à votre besoin.
Retrouvez les règles principales de nginx au-travers de ce
document
que je partage ! Il est bien-sûr nécessaire de l’intégrer à votre
schéma server
…
Il est nécessaire, pour que Nextcloud fonctionne bien, de configurer votre fichier php-fpm afin d’ajouter :
allow_url_fopen = on
env[PATH] = /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin
post_max_size = 512M
upload_max_filesize = 512M
open_basedir
, veillez à autoriser l’accès à /dev/urandom
.Redémarrez le service PHP-FPM…
Étant donné que PHP est chrooté, la commande occ
, ainsi que les jobs
cron échouent.
Lorsque occ
est exécuté, vous obtenez au moins ce message d’erreur :
Citation :
Your data directory is invalid Ensure there is a file called ".ocdata" in the root of the data directory. Cannot create "data" directory This can usually be fixed by giving the webserver write access to the root directory. See https://docs.nextcloud.com/server/16/go.php?to=admin-dir_permissions
Résoudre ce problème est simple : il suffit d’éditer le
fichier de config de nextcloud, nextcloud/config/config.php
pour modifier la valeur de la variable datadirectory
. (cf :
Nextcloud Php Chroot OpenBSD (astuce)
)
Bien sûr, le chemin /data
doit correspondre à votre cas, surtout si vous l’avez déplacé hors de
la racine nextcloud - ce qui est recommandé !
Ce changement étant fait, vous pouvez utiliser sans soucis la commande
occ
.
À quoi sert Collabora CODE ?
À pouvoir éditer les documents bureautique dans Nextcloud directement. Malheureusement, ne cherchez pas : cela ne fonctionne pas nativement sur OpenBSD !
Le moyen : dans une VM ! :p
Il existe deux méthodes pour pouvoir utiliser Collabora CODE :
Une fois dans votre VM Debian, il faut installer docker puis l’image fournie par les soins de Collabora.
# apt install docker-ce
$ docker pull collabora/code
Ensuite il faut exécuter la commande suivante en l’adaptant au nom de
domaine où se trouve votre instance de Nextcloud :
$ docker run -t -d -p 127.0.0.1:9980:9980 -e 'domain=cloud\\.nextcloud\\.com' --restart always --cap-add MKNOD collabora/code
Je propose de créer un petit script shell qui permettra toute modification aisément de la commande au cas où :
#!/bin/sh
docker run -t -d -p 127.0.0.1:9980:9980 -e 'domain=nom<br>-domaine<br>.tld' \--restart always \--cap-add MKNOD collabora/code
Il est très probable qu’il faille modifier iptables tel que, par exemple :
iptables -A FORWARD -i docker0 -o enp0s3 -j ACCEPT
iptables -A FORWARD -i enps0s3 -o docker0 -j ACCEPT
iptables -A INPUT -i docker0 -j ACCEPT
Depuis votre machine hôte, normalement il est possible de pinger la VM et de tester une requête CURL.
Code : sh
$ ping -c3 192.168.0.2
PING 192.168.0.2 (192.168.0.2): 56 data bytes
64 bytes from 192.168.0.2: icmp_seq=0 ttl=64 time=0.254 ms
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.278 ms
64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.301 ms
--- 192.168.0.2 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.254/0.278/0.301/0.019 ms
$ curl -Iv http://192.168.0.2:9980
* Rebuilt URL to: http://192.168.0.2:9980/
* Trying 192.168.0.2...
* TCP_NODELAY set
* Connected to 192.168.0.2 (192.168.0.2) port 9980 (#0)
> HEAD / HTTP/1.1
> Host: 192.168.0.2:9980
> User-Agent: curl/7.61.1
> Accept: */*
>
* Empty reply from server
* Connection #0 to host 192.168.0.2 left intact
curl: (52) Empty reply from server
Si curl répond ainsi, c’est que cela semble bon !
Maintenant, passons aux modifications du serveur nginx , puis à l’administration de Nextcloud.
Récupère la nouvelle image : $ docker pull collabora/code
Arrêt de l’image en cours :
$ docker container ls
$ docker container stop CONTAINER_ID
, ou NAMES
fonctionne aussi
$ docker container rm CONTAINER_ID
, ou NAMES
On relance la commande docker run…
, vue précédemment ci-dessus !
Les modifications des règles location
pour nginx sont fournies dans ce
document…
Veillez à remplacer les écritures http://localhost
, par votre schéma
Puis relancer le service nginx… et administrons Nextcloud !
Il suffit de cloner le dépôt et d’exécuter le script shell officeonline-install.sh.
L’intérêt de ce script est d’installer tout ce qui est nécessaire afin de se débarrasser des limitations fournies dans le projet Docker de l’entreprise Collabora.
$ git clone https://github.com/husisusi/officeonlin-install.sh.git
$ cd officeonlin-install.sh
ATTENTION, ce script demande de grosses ressources machine car la phase de compilation et d’installation se déroule durant des heures !
Voir le projet sur le forum d’entraide de Nextcloud…
Les valeurs actuellement fonctionnelles, sur une Debian Stretch, du
fichier de configuration officeonline-install.cfg
sont
celles-ci:
set_online_regex='collabora/collabora-online-4$' #CODE 4 Branch
lool_src_commit='173510fdbf6f52d1d6288b809c8d14bc630afd20' #CODE-4-RC2
set_core_regex='cp-6.0$' #LibO 6.0.x
Pensez à modifier aussi la valeur de allowed_domains
en début de
fichier, en faisant correspondre avec le nom de domaine qui gère votre
nextcloud ou le service collabora s’il est sur un serveur distinct.
Une fois le fichier de configuration modifié, exécutez la commande
suivante :
# officeonline-install.sh -c officeonline-install.cfg
Puis, patientez le temps de la phase de compilation et d’installation…
Si à la fin, vous avez un message ressemblant au suivant, alors c’est bon :
Code : bash
(…)
### loolwsd is running. Enjoy!!! Service will be stopped after this ###
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
loolwsd 19422 lool 17u IPv6 320498 0t0 TCP *:9980 (LISTEN)
#
Redémarrez votre VM, vérifiez votre config nginx, puis modifiez votre configuration de Nextcloud …
Se connecter à l’interface web de Nextcloud en tant qu’administrateur, puis dans le menu Applications > Section Office & text/Bureautique et installer l’application Collabora Office.
Ensuite, choisir le menu Settings/Paramètres > Collabora Online et spécifier le nom du domaine sur lequel fonctionne la VM Debian ; il doit correspondre ABSOLUMENT selon votre choix de configuration, soit :
domain
que vous avez rempli lors de l’exécution du containeur Docker…allowed_domains
remplie pour la configuration du script officeonline
…Pour pouvoir communiquer par vidéo et/ou par chat, il faut installer l’application officielle Talk avec un compte administrateur depuis l’interface d’administration de Nextcloud.
Ensuite, il faut configurer un serveur Turn !
Pour finir, chaque utilisateur inscrit de votre nuage informatique pourra communiquer avec un autre, soit à partir de l’application Nextcloud Talk sur un smartphone, soit à partir de l’interface web de Nextcloud une fois connecté.
L’installation d’un serveur STUN/TURN, pour que l’application Talk fonctionne, est expliqué dans mon tutoriel OpenBSD : Service TURN .
Ensuite, il est nécessaire de paramétrer Nextcloud. Connectez-vous à son interface en tant qu’administrateur, puis choisissez le menu Settings/Paramètres > Talk/Discussion.
Voici en image l’interface :
Écrivez dans les champs :
Serveur STUN
, écrivez : nom-domaine.tld:3478
Serveur TURN
, écrivez : nom-domaine.tld:5349
, puis le champ suivant le secret d’authentification que vous avez configuré pour l’option static-auth-secret
dans le fichier de configuration du serveur Turn. Puis changez si besoin les protocoles utilisés.Une fois configuré, il n’y a plus qu’à utiliser l’application Nextcloud Talk soit sur votre smartphone, soit à-partir de l’interface web de Nextcloud depuis votre compte.
Source:
Enjoy-IT! Enjoy-ID!
Un serveur TURN est un serveur de VoIP - un serveur de trafic qui passe sur les réseaux NAT et au-travers des passerelles.
Installez le paquet turnserver !
Un utilisateur _turnserver
sans droit système est créé !
/etc/turnserver.conf
Il faut décommenter ou remplir les options suivantes :
fingerprint
lt-cred-mech
use-auth-secret
static-auth-secret
- pour générer un secret d'authentification
…realm
- écrire le nom de domaine ou sous-domainetotal-quota
- paramétrer la à la valeur de 100
bps-capacity
- valeur de 0
stale-nonce
no-loopback-peers
no-multicast-peers
Quelques options à modifier pour avoir une configuration fonctionnelle :
tls-listening-port
- la valeur par défaut du port est 5349
listening-port
- la valeur par défaut du port est 3478
Si vous utilisez HTTPS, il faut en plus paramétrer ces options :
cert
- chemin vers le certificat HTTPS du serveurpkey
- chemin vers la clé privée liée au certificat HTTPS du serveurcipherlist
- il est fortement recommandé de modifier cette option à l’identique de la configuration de votre serveur web, si vous en avez un actif sur le même serveur. Voici les valeurs minimales : ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AES:RSA+3DES:!ADH:!AECDH:!MD5
no-tlsv1
et no-tlsv1_1
dh-file
- n’utilisez pas le même que celui de votre serveur web ; générez-en exprès rien que pour ce service !Par défaut, l’interface d’administration en ligne de commande est activée !
Pour la désactiver, il faut décommenter l’option *no-cli…
Sinon, décommentez les options suivantes pour ajouter un peu de sécurité dessus :
cli-ip
- la valeur par défaut est 127.0.0.1
, sauf à raison contraire, laissez-la telle quelle.cli-port
- la valeur par défaut est 5766
.cli-password
- si l’option reste commentée, il n’y aura pas de mot de passe - générez un nouveau mot de passe
avec la commande turnadmin
et copiez-le…Par défaut, SQLite est utilisée, et les données sont enregistrées dans
/var/db/turndb
- là, encore, sous OpenBSD, il est nécessaire que
l’utilisateur _turnserver
ait les droits sur ledit fichier.
Pour les bases de données, MySQL/MariaDB, PostgreSQL, Mongo, Redis, veuillez lire le fichier INSTALL !
Il est possible de gérer les journaux en modifiant/activant les options suivantes :
no-stdout-log
- empêcher que les journaux soient publiés sur la sortie standardsyslog
- rediriger les sorties vers le journal syslogsimple-log
-log-file
- donnez-lui le chemin absolu vers le nom de fichier dans lequel vous désirez que les journaux soient écrits. -/var/tmp/turn.log
.Pour générer un secret d’authentification, il suffit de se servir de la
commande openssl, tel que : $ openssl rand -hex 32
Là, aussi, openssl sera notre secours, tel que :
$ openssl dhparam -out dhparam_4096.pem 4096
ce qui nous générera un
fichier de 4096 bits.
Pour générer un mot de passe, il faut utiliser l’option -P
(ou son équivalent : --generate-encrypted-password*
) alliée de l’option
-p
(ou son équivalent : --password
).
cli-password
: $ turnadmin -P -p cli-password
Les journaux indiquent que le fichier relatif à la clé privée du certificat SSL/HTTPS ne peut être lu, tel que :
Dec 19 09:08:17 srvr turnserver: 0: WARNING: cannot find private key file: /etc/ssl/acme/private/mydomain.net.privkey.pem (1)
Dec 19 09:08:17 srvr turnserver: 0: WARNING: cannot start TLS and DTLS listeners because private key file is not set properly
En effet, lors de la génération par le client acme natif sous OpenBSD,
les droits sur ledit fichier appartiennent en lecture seule à
root:wheel
- or, le serveur fonctionne avec les droits de
l’utilisateur _turnserver
, il ne peut donc pas y accéder…
(bien sûr, je n’ai pas abordé la génération de certificats TLS avec
Lets’Encrypt… voici un exemple d’explication pour le client acme sous OpenBSD)
_turnserver
aura accès avec des droits en lecture seule, et sur le répertoire et sur le fichier de clé privée copié. Une fois fait, indiquez à l’option pvkey
le nouveau chemin._turnserver
et d’attribuer les droits 0440 sur le fichier original de la clé privée.Personnellement, je n’aime ni l’une, ni l’autre de ces deux solutions… mais je ne peux proposer mieux !
Une fois le fichier configuré, il ne vous reste plus qu’à activer le
service et le démarrer à l’aide de l’outil rcctl
:
# rcctl start turnserver
La configuration des règles du pare-feu PF est un peu plus délicate. Gardez à l’esprit que ce sont des règles à modifier selon vos nécessités :
Fichier : /etc/pf.conf
|
|
Il est très intéressant de déclarer une table abuse et de modifier la règle qui bloque la connexion à l’interface CLI afin que les IP correspondantes soient enregistrées dans la table abuse. Veillez à créer une tâche cron pour purger régulièrement ladite table ;)
Source : https://help.nextcloud.com/t/howto-setup-nextcloud-talk-with-turn-server/30794
Enjoy-ID! Enjoy-IT!
Ou comment créer un fichier sitemap.xml - ou sa version compressée sitemap.xml.gz en PHP.
Voyons comment écrire en PHP un sitemap.xml très basique :
Code : php
<?php
### créons les constantes utiles
# détection du protocole utilisé : scheme
if ( empty($_SERVER['HTTPS']) ) define('SCHEME', 'http');
else define('SCHEME', 'https');
# détection du nom d'hôte et écriture de la base URL
define('HOST', $_SERVER['HTTP_HOST']);
define('BASE', SCHEME."://".HOST);
# détection du chemin absolu, réel du script
define('ROOT', realpath(getenv('DOCUMENT_ROOT')));
# écriture de l'entête XML
$flux = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$flux .= '<urlset xmlns="http://www.google.com/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.9
http://www.google.com/schemas/sitemap/0.9/sitemap.xsd">'."\n";
# on récupère les informations du fichier index
$file_mtime = date ("c", filemtime(ROOT.'/index.php'));
# écriture du flux, relatif au fichier index
$flux .= ' <url>
<loc>'.BASE.'</loc>
<lastmod>'.$file_mtime.'</lastmod>
<priority>1</priority>
</url>'."\n";
# écriture finale du flux XML
$flux .= '</urlset>'."\n";
# on envoie le flux avec le bon entête et le bon encodage
header("Content-Type: application/xml; charset=utf-8");
echo $flux;
?>
Bien-sûr l’écriture du fichier sitemap.xml
est basique, non compressé,
et ne sert - dans ce cas - qu’à indexer le fichier index.php
- cas peu utile, avouons-le !
Maintenant, admettons que nous avons un répertoire ‘outils’, dans lequel nous avons différents scripts PHP que nous souhaitons indexer, eux aussi ;)
Pour cela, nous allons utiliser les Itérateurs par parcourir le répertoire, puis récupérer les informations de fichier par le biais de la classe SPL !
Code : php
<?php
# créons un tableau...
$folders = array ('tools');
# parcours du tableau et exécutions d'instructions relatives...
foreach($folders as $name) {
switch($name) {
case 'tools': $pattern = '/^.+\.php$/i'; break;
}
# Utilisons les fonctions Iterator pour parcourir le bon répertoire depuis sa racine absolue.
$Directory = new RecursiveDirectoryIterator(ROOT.'/'.$name.'/');
$Iterator = new RecursiveIteratorIterator($Directory);
$dirs = new RegexIterator($Iterator, $pattern, RecursiveRegexIterator::GET_MATCH);
# parcours de l'objet Iterateur, pour écrire le flux XML nécessaire,
foreach($dirs as $dir => $dirs) {
$flux .= ' <url>'."\n";
$info = new SplFileInfo($dir);
# construction de l'URL visible
$flux .= " <loc>".BASE.'/'.$name.'/'.$info->getBasename()."</loc>"."\n";
# récupération de la date de dernière modification du fichier - cf, l'argument ''c'' permet de restituer directement la date au bon format attendu
$flux .= " <lastmod>".date ("c", $info->getCTime())."</lastmod>"."\n";
### l'ancienne méthode donnerait ce code PHP
#$flux .= " <loc>".BASE.'/'.$name.'/'.basename($dir)."</loc>"."\n";
#$flux .= " <lastmod>".date ("c", filemtime($dir))."</lastmod>"."\n";
$flux .= ' </url>'."\n";
}
}
?>
Bien-sûr, ce code PHP de parcours de dossier et de restitution d’informations fichiers, envoyé dans le flux XML nécessaire, est à intégrer après le code relatif au fichier index et avant le code de fermeture du flux XML.
Maintenant, voyons comment compresser de manière simple et rapide le flux XML pour créer un fichier sitemap.xml.gz nécessaire :
Code : php
<?php
# on prend le flux XML dans son ensemble pour l'encoder en gz
$gzdata = gzencode($flux, 9);
?>
Ensuite pour envoyer les données, utilisons les bons entêtes, puis affichons le flux encodé :
Code : php
<?php
# déclaration des entêtes nécessaires
header("Content-Type: application/x-gzip");
header("Content-Encoding: gzip");
header("Content-Disposition: attachment; filename=sitemap.xml.gz");
# affichage du flux encodé - et non pas du flux normal !!!
echo $gzdata;
?>
Voici la version finale du code PHP pour créer dynamiquement un fichier sitemap.xml, et sa version compressée sitemap.xml.gz :
Fichier : sitemap.php
|
|
Et, voilà ! :D
Ou comment créer un fichier sitemap.xml - ou sa version compressée sitemap.xml.gz en PHP.
Voyons comment écrire en PHP un sitemap.xml très basique :
Code : php
<?php
### créons les constantes utiles
# détection du protocole utilisé : scheme
if ( empty($_SERVER['HTTPS']) ) define('SCHEME', 'http');
else define('SCHEME', 'https');
# détection du nom d'hôte et écriture de la base URL
define('HOST', $_SERVER['HTTP_HOST']);
define('BASE', SCHEME."://".HOST);
# détection du chemin absolu, réel du script
define('ROOT', realpath(getenv('DOCUMENT_ROOT')));
# écriture de l'entête XML
$flux = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
$flux .= '<urlset xmlns="http://www.google.com/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.9
http://www.google.com/schemas/sitemap/0.9/sitemap.xsd">'."\n";
# on récupère les informations du fichier index
$file_mtime = date ("c", filemtime(ROOT.'/index.php'));
# écriture du flux, relatif au fichier index
$flux .= ' <url>
<loc>'.BASE.'</loc>
<lastmod>'.$file_mtime.'</lastmod>
<priority>1</priority>
</url>'."\n";
# écriture finale du flux XML
$flux .= '</urlset>'."\n";
# on envoie le flux avec le bon entête et le bon encodage
header("Content-Type: application/xml; charset=utf-8");
echo $flux;
?>
Bien-sûr l’écriture du fichier sitemap.xml
est basique, non compressé,
et ne sert - dans ce cas - qu’à indexer le fichier index.php
- cas peu utile, avouons-le !
Maintenant, admettons que nous avons un répertoire ‘outils’, dans lequel nous avons différents scripts PHP que nous souhaitons indexer, eux aussi ;)
Pour cela, nous allons utiliser les Itérateurs par parcourir le répertoire, puis récupérer les informations de fichier par le biais de la classe SPL !
Code : php
<?php
# créons un tableau...
$folders = array ('tools');
# parcours du tableau et exécutions d'instructions relatives...
foreach($folders as $name) {
switch($name) {
case 'tools': $pattern = '/^.+\.php$/i'; break;
}
# Utilisons les fonctions Iterator pour parcourir le bon répertoire depuis sa racine absolue.
$Directory = new RecursiveDirectoryIterator(ROOT.'/'.$name.'/');
$Iterator = new RecursiveIteratorIterator($Directory);
$dirs = new RegexIterator($Iterator, $pattern, RecursiveRegexIterator::GET_MATCH);
# parcours de l'objet Iterateur, pour écrire le flux XML nécessaire,
foreach($dirs as $dir => $dirs) {
$flux .= ' <url>'."\n";
$info = new SplFileInfo($dir);
# construction de l'URL visible
$flux .= " <loc>".BASE.'/'.$name.'/'.$info->getBasename()."</loc>"."\n";
# récupération de la date de dernière modification du fichier - cf, l'argument ''c'' permet de restituer directement la date au bon format attendu
$flux .= " <lastmod>".date ("c", $info->getCTime())."</lastmod>"."\n";
### l'ancienne méthode donnerait ce code PHP
#$flux .= " <loc>".BASE.'/'.$name.'/'.basename($dir)."</loc>"."\n";
#$flux .= " <lastmod>".date ("c", filemtime($dir))."</lastmod>"."\n";
$flux .= ' </url>'."\n";
}
}
?>
Bien-sûr, ce code PHP de parcours de dossier et de restitution d’informations fichiers, envoyé dans le flux XML nécessaire, est à intégrer après le code relatif au fichier index et avant le code de fermeture du flux XML.
Maintenant, voyons comment compresser de manière simple et rapide le flux XML pour créer un fichier sitemap.xml.gz nécessaire :
Code : php
<?php
# on prend le flux XML dans son ensemble pour l'encoder en gz
$gzdata = gzencode($flux, 9);
?>
Ensuite pour envoyer les données, utilisons les bons entêtes, puis affichons le flux encodé :
Code : php
<?php
# déclaration des entêtes nécessaires
header("Content-Type: application/x-gzip");
header("Content-Encoding: gzip");
header("Content-Disposition: attachment; filename=sitemap.xml.gz");
# affichage du flux encodé - et non pas du flux normal !!!
echo $gzdata;
?>
Voici la version finale du code PHP pour créer dynamiquement un fichier sitemap.xml, et sa version compressée sitemap.xml.gz :
Fichier : sitemap.php
|
|
Et, voilà ! :D
Ou, comment configurer sa machine locale pour envoyer un mail depuis votre console, depuis OpenBSD, actuellement dans sa version 6.4, en se connectant à un service nécessitant une identification ?
OpenSMTPD est une libre implémentation du protocole SMTP côté serveur, tel que défini dans la RFC 5321 , avec quelques extensions standards additionnels. Il permet à des machines ordinaire d’échanger des mails avec d’autres systèmes parlant le protocole SMTP.
Informations :
Testé avec efficacité auprès des services de Gandi, de l’association L’autre.net, puis sur mes propres serveurs MX.
OpenBSD, depuis sa version 6.4, embarque nativement la nouvelle version d’OpenSMTPD… il n’y a donc rien de plus à installer, cela fait partie du système de base.
Donc, un coup de # rcctl start smtpd
et c’est partie le service SMTP
fonctionnera normalement sur votre machine !
Une petite précision sur les fichiers :
/etc/mail/smtpd.conf
./var/log/maillog
et permet de surveiller toute
l’activité liée à SMTP, vous y retrouverez aussi les erreurs d’envois.Pour envoyer un mail par SMTP à un service de mails nécessitant une
identification, tel que celui de Gandi, il est nécessaire de créer dans
un premier temps, un fichier secrets
avec les droits adéquats sur
votre système, ensuite il nous reste à configurer le fichier
smtpd.conf
.
Le manpage nous donne un exemple de ce qu’il faut faire - regardez le premier exemple, si besoin, mais je le restitue ici - :
Il nous faut créer ce fichier /etc/mail/secrets
:
# touch /etc/mail/secrets
Donnons lui les droits adéquats pour le “sécuriser”, selon la section “Exemples” du manpage :
# chmod 640 /etc/mail/secrets
# chown root:_smtpd /etc/mail/secrets
Ensuite, il est nécessaire de le remplir de telle manière :
identifiant username:password
n'écrivez pas TEXTUELLEMENT cette information
,
remplacez-là par les informations ci-dessous :
identifiant
est l’identifiant que vous choisissez soigneusement,
et qui vous servira plus tard dans la configuration du fichier
smtpd.conf
;
admettons pour l’exemple que ce sera la chaine de caractères :
perso.username
est votre identifiant de connexion mail au service mail de
votre fournisseur - généralement votre adresse mail - ;password
étant le mot de passe lié à votre identification mail.Il est possible de nommer autrement ce fichier secrets, et de le mettre ailleurs dans votre système de fichier ; comprenez-le principe et modifier en conséquence.
De même, je vous encourage fortement à ne mettre QUE des droits 0400 sur le fichier.
Même si l’accès au fichier par smtpd peut sans soucis être fait avec vos
droits personnels $USER:$USER
,
si vous l’avez mis ailleurs, tel que dans votre $HOME
, il est préférable
de mettre à minima les droits avec le groupe _smtpd
.
smtpd.conf
Maintenant modifions le fichier /etc/mail/smtpd.conf
# $OpenBSD: smtpd.conf,v 1.14 2019/11/26 20:14:38 gilles Exp $
# This is the smtpd server system-wide configuration file.
# See smtpd.conf(5) for more information.
table aliases file:/etc/mail/aliases
table secrets file:/etc/mail/secrets
queue compression
# To accept external mail, replace with: listen on all
#
## add on 6.7
listen on socket
listen on lo0
action "local_mail" mbox alias <aliases>
action "unbound" relay host smtp+tls://identifiant@serveur auth <secrets> mail-from "@your-domain.tld"
# Uncomment the following to accept external mail for domain "example.org"
#
# match from any for domain "example.org" action "local"
### 6.6 writings
#match for local action "local_mail"
#match for any action "unbound"
### 6.7 writings
match from local for local action "local_mail"
match from local for any action "outbound"
Explications
Par rapport à la version originale, nous avons donc rajouté :
table secrets
qui appelle le fichier /etc/mail/secrets
-
ou son équivalent, si vous l’avez personnalisé…action unbound
qui nous permet de définir l’action nécessaire
vers l’hôte relais par lequel nous enverrons les mails…
identifiant@serveur
:
identifiant
par celle que vous avez créée dans votre fichier secrets
.
Dans le contexte de notre exemple, il faudra écrire la chaine
de caractères perso.serveur
, c’est le nom du serveur SMTP qu’il
faut renseigner.
mail.gandi.net
.secrets
fournissant les données d’identification
mail nécessaires.Sender address rejected: Domain not found
;
il faut bien sûr que ce domaine vous appartienne…match … action "unbound"
est l’action qui sera déclenchée
lors de l’envoi de mails à l’extérieur !La v6.7 d’OpenBSD a apporté de légers changements de syntaxe :
listen on socket
smtpd.conf(5)#listen2
match from local for local action "local_mail"
match from local for any action "outbound"
La syntaxe des noms d’actions a légèrement changé entre les versions 6.4 et 6.6 :
local
devient local_mail
relay
devient unbound
Il est intéressant de gérer l’alias relatif à votre compte root
voire
celui de votre utilisateur principal…
Éditez le fichier /etc/mail/aliases
, et vers la fin du fichier,
modifiez root
en lui indiquant vers quelle adresse mail, vous désirez
que les messages systèmes adressés au compte root vous soit envoyés !
Faites de même pour votre utilisateur système ;)
N’oubliez pas de recharger la base des aliases, grâce à l’usage de la
commande newaliases
… avec des droits administrateurs !
Avant de redémarrer le service smtpd pour qu’il prenne en compte les
modifications faites, il nous faut tester l’écriture de la
configuration : # smtpd -n
qui devrait réponde par : configuration OK
informant ainsi que tout va bien…
Sinon, rééditez le fichier de configuration à la ligne indiquée en premier ; c’est d’elle que vient l’erreur principale !
Partons du principe que tout est bon, il suffit de redémarrer le service :
# rcctl restart smtpd
smtpd(ok)
smtpd(ok)
Le journal quant à lui indiquera le bon redémarrage par une ligne d’information
semblable à la suivante :
Apr 3 07:17:05 sh1 smtpd[68810]: info: OpenSMTPD 7.0.0 starting
De même, pensez à utiliser le contrôleur smtpctl
… je vous renvoie à son
manpage qui est très complet !
Soit :
echo "Test d'envois de mail on $(hostname); date: $(date)" | mail -s "Test de mail" adresse_mail_à_qui_envoyer
echo "Test d'envois de mail on $(hostname); date: $(date)" | mail -s "Test de mail" root
Dans un cas, comme dans l’autre, le journal vous indiquera l’équivalent, en cas de réussite, d’un tel message, par exemple :
Apr 3 07:20:20 sh1 smtpd[56183]: 2cda1df4efff97f2 mta connecting address=smtp+tls://89.234.141.148:587 host=mail2.automario.eu
Apr 3 07:20:20 sh1 smtpd[56183]: 2cda1df4efff97f2 mta connected
Apr 3 07:20:21 sh1 smtpd[56183]: 2cda1df4efff97f2 mta tls ciphers=TLSv1.3:AEAD-CHACHA20-POLY1305-SHA256:256
Apr 3 07:20:21 sh1 smtpd[56183]: 2cda1df4efff97f2 mta cert-check result="valid" fingerprint="SHA256:17af91bcb27a530cc278cd8be90551593bee38ebaf6ade68053a508b14a8f817"
Apr 3 07:20:21 sh1 smtpd[56183]: 2cda1df4efff97f2 mta delivery evpid=4138560f4bd626cf from=<***@huc.fr.eu.org> to=<***@stephane-huc.net> rcpt=<-> source="46.23.90.29" relay="89.234.141.148 (mail2.automario.eu)" delay=1s result="Ok" stat="250 2.0.0 eb1a48cf Message accepted for delivery"
Retrouvez ci-dessous les erreurs communes liées à une mauvaise configuration :
Vérifiez, re-vérifiez votre couple d’identification username
, password
écrits dans votre fichier secret
!
Ce message d’erreur est adressé parce que le service SMTP n’arrive pas à
comprendre l’ensemble identifiant@serveur
dans votre règle action.
Vérifiez vos écritures, afin que :
table secrets
renseigne bien le bon nom de fichier à interroger !identifiant username:password
dans votre fichier secrets
identifiant
par celle que vous
avez créée…serveur
: assurez-vous de l’existence du nom de
l’hôte relais.Ce message d’erreur vous est adressé lorsque le service SMTP ne trouve pas de correspondance avec le nom de domaine.
mail-from "@votre-domaine.tld"
n’oubliez pas la présence du symbole @
(arobase).Le protocol SMTP est défini par la RFC 5321 :
Le but de cet article est de montrer comment obtenir les différentes informations
qu’unbound permet de surveiller, et se base sur l’outil unbound-control
.
Pour rappel :
/var/unbound/etc/unbound.conf
unbound-checkconf
Je ne rappellerai pas comment configurer pleinement Unbound, lisez cet article OpenBSD : utiliser Unbound et celui-ci pour plus de “sécurité” autour des communications DNS OpenBSD : Unbound en mode DNSSEC + DNS/TLS ;-)
La première chose, à faire sur votre serveur, est l’usage de l’outil
unbound-control-setup
, afin de générer les clés et certificats nécessaires
pour gérer le service :
Code : shell
# unbound-control-setup
setup in directory /var/unbound/etc
generating unbound_server.key
Generating RSA private key, 3072 bit long modulus
...............................................................................................................++
............................................................++
e is 65537 (0x10001)
generating unbound_control.key
Generating RSA private key, 3072 bit long modulus
........................................................................++
..................++
e is 65537 (0x10001)
create unbound_server.pem (self signed certificate)
create unbound_control.pem (signed client certificate)
Signature ok
subject=/CN=unbound-control
Getting CA Private Key
Setup success. Certificates created. Enable in unbound.conf file to use
Les clés et certificats étant générés, il ne reste plus qu’à retoucher le fichier de configuration pour activer le service de gestion de contrôle, qui permet de le gérer aussi à distance !
Ouvrons le fichier de configuration d’unbound, pour le modifier de manière adéquate - par défaut, il se présente ainsi :
Code : shell
remote-control:
control-enable: yes
control-use-cert: no
control-interface: /var/run/unbound.sock
Pour pouvoir l’administrer localement, il est nécessaire de commenter la
déclaration control-interface
et d’ajouter celles-ci :
Code : shell
#control-interface: /var/run/unbound.sock
control-interface: 127.0.0.1
control-interface: ::1
Il est bien sûr possible de spécifier l’adresse IPv4 ou IPv6 du serveur, celles de votre LAN, ou celles accessibles sur Internet. Lire les règles de pare-feu envisageables pour sécuriser la connexion.
Maintenant, après avoir vérifié le fichier de configuration et recharger/relancer
le service unbound, il est possible au moins localement d’utiliser l’outil
unbound-control
.
Lisez ABSOLUMENT le manpage pour savoir quelles sont les différentes options, voici les plus utiles :
-c
: spécifier un fichier de configuration alternatif-h
: obtenir l’aide-s
: cibler le serveur à interroger ; fonctionne sur IPv4 et IPv6 :
server[@port]
:
8953
, Ensuite, il est possible d’envoyer des commandes qui interagiront avec
le serveur, de telle manière :
$ unbound-control -s 127.0.0.1 command_name
Il y a beaucoup de commande possibles, voici certaines :
start
: démarrer le serveur
stop
: arrêter le serveur
reload
: purge le cache et recharge la configuration
stats
: affiche les statistiques et remets à zéro les compteurs internes
stats_noreset
: affiche les statistiques sans remettre à zéro les compteurs internes
status
: affiche le status du serveur
0
, s’il fonctionne1
, s’il y a une erreur3
, soit s’il ne fonctionne pas, soit si la connexion est refusée.dump_cache
permet d’afficher/imprimer le contenu du cache ; il est
ainsi possible de le rediriger vers un fichier pour enregistrer ces données.
load_cache
charge le contenu d’un cache depuis stdin… aide au débogage.
get_option //option//
pour obtenir la valeur d’une option, où option
est le nom de l’option
set_option //option:valeur//
permet de définir la valeur d’une option…
où option
est le nom de l’option, et valeur
, sa valeur adéquate.
Les options paramétrables sont :
add-holddown
,cache-max-ttl
, cache-max-negative-ttl
, cache-min-ttl
del-holddown
, do-not-query-localhost
,harden-below-nxdomain
, harden-dnssec-stripped
, harden-glue
, harden-large-queries
, harden-referral-path
, harden-short-bufsize
,hide-identity
, hide-version
,identity
, ignore-cd-flag
, ip-ratelimit
,keep-missing
,log-queries
, val-log-level
, val-log-squelch
,max-udp-size
,prefetch
, prefetch-key
,ratelimit
,statistics-cumulative
, statistics-interval
,ssl-upstream
, tcp-upstream
,version
,Ensuite, il est possible de gèrer :
local-zone
local-data
,auth_*
, dump_*
, flush_*
, forward_*
, insecure_*
, list_*
, *ratelimit_*
, stub_*
, view_*
mais là, encore une fois, je vous invite à relire le manpage. ;)
status
:
Code : shell
$ unbound-control -s ::1 status
version: 1.8.1
verbosity: 1
threads: 2
modules: 2 [ validator iterator ]
uptime: 49932 seconds
options: reuseport control
unbound (pid 99951) is running…
get_option
:
$ unbound-control -s ::1 get_option harden-glue
yes
dump_cache
:
$ unbound-control -s ::1 dump_cache > dump.unbound
il ne vous reste plus qu’à lire le fichier dump.unbound
;
bien sûr, il peut porter tout autre nom que vous désirez.Voici quelques règles - d’exemples - pour le pare-feu PF :
Si vous utilisez l’option control-interface
en permettant que ce soit
l’IP publique sur Internet ou sur votre LAN qui soit consultable, il est
fortement recommandé de modifier vos règles PF, afin de n’autoriser que le flux venant d’une machine autorisée, telle que :
Code : PF
(…)
myhost = "192.168.1.1"
unbound_ctlr = "8953"
(…)
table <t_adm> const { 192.168.1.3, fd0::3 }
(…)
blog log
pass out
(…)
pass in quick on egress proto tcp from <t_adm> to $myhost port $unbound_ctlr flags S/SA modulate state
Autrement dit, on autorise le flux entrant sur l’interface egress
depuis les adresses IPv4|6 intégrées dans la table <t_adm>
vers le
serveur $myhost
sur le port $unbound_ctlr
.
Pour votre station autorisée ayant, par exemple, l’adresse IPv4 192.168.1.3
:
Code : PF
(…)
myhost = "192.168.1.3"
server = "192.168.1.1"
unbound_ctlr = "8953"
(…)
blog log
pass out
(…)
pass out quick on egress inet proto tcp from $myhost to $server port $unbound_ctlr flags S/SA modulate state
On autorise le flux sortant de votre machine autorisée vers le serveur sur le port adéquate… Bien-sûr, faites de même pour IPv6.
Enjoy-ID! Enjoy-IT!
Cet article a pour but de montrer comment configurer le service unbound pour que celui fasse ses requêtes en tenant compte du protocole DNSSEC, protocol de chiffrement des données, et aussi pour qu’elles soient transmises en tenant compte du protocol de chiffrement TLS.
Pour rappel :
/var/unbound/etc/unbound.conf
unbound-checkconf
Je ne rappellerai pas comment configurer pleinement Unbound, lisez cet article : OpenBSD : utiliser Unbound
La gestion DNSSEC se fait par l’usage de l’outil unbound-anchor
qui crée
un fichier de clé nécessaire et l’ajout de la variable auto-trust-anchor-file
qui pointe vers ledit fichier de clés, dans votre fichier de configuration,
tel quel :
auto-trust-anchor-file: "/var/unbound/db/root.key"
Auquel, il faut ajouté le mode de validation DNSSEC :
module-config: "validator iterator"
Même si sous OpenBSD, ce fichier de clé est généré automatiquement dès le premier démarrage, pour générer le fichier de clé :
# unbound-anchor -u _unbound -a "/var/unbound/db/root.key"
L’option -u
utilise ici le nom utilisateur, par défaut lié au projet
unbound, sous OpenBSD, à savoir _unbound
.
De même, il faut ajouter les variables suivantes à votre propre fichier de configuration :
harden-below-nxdomain: yes
harden-dnssec-stripped: yes
harden-referral-path: yes
Explications
harden-referral-path
’ renforce la validation DNSSEC -
c’est une option expérimentale, sans norme RFC, et peut poser des problèmes de performances !Depuis la version 1.7.0, unbound a une nouvelle option : aggressive-nsec
qui met en cache les enregistrements NSEC pour générer les réponses rapidement.
Depuis OpenBSD 6.4, unbound est fourni en version 1.8.1, donc profitez-en :
aggressive-nsec: yes
Oui, unbound est capable de communiquer aussi avec les serveurs DNS, en mode protocolaire DoT !
Il est nécessaire de bien comprendre l’impact de l’usage de ce mode de communication. Du fait d’utiliser TLS, la communication semble “ralentie”, donner la sensation de lenteur…
Cela est plus ou moins sensible selon la puissance de votre machine et des serveurs interrogés, de la qualité du réseau, etc.
Il faut configurer unbound ainsi, dans un premier temps :
do-tcp: yes
ssl-upstream: yes
Explications :
do-tcp
indique de communiquer sur le protocole TCPssl-upstream
ou tls-upstream
oblige à communiquer sur le protocole TLS.
*-upstream
sont indiquées, seule la dernière
sera prise en compte.Ensuite, il est nécessaire de décommenter - si ce n’est pas déjà fait -
la partie forward-zone
, pour indiquer le(s) serveur(s) à interroger sur
le port adéquat - par défaut : 853 - tel(s) que :
forward-zone:
name: "." # use for ALL queries
forward-ssl-upstream: yes
# FDN DoT
## https://www.fdn.fr/ouverture-des-services-dot-doh/
forward-addr: 80.67.169.12@853
forward-addr: 80.67.169.40@853
forward-addr: 2001:910:800::12@853
forward-addr: 2001:910:800::40@853
# Others
forward-addr: 9.9.9.9@853 # Quad9
forward-addr: 1.1.1.1@853 # Cloudflare
forward-addr: 149.112.112.112@853 # Quad9 secondaire
forward-addr: 1.0.0.1@853 # Cloudflare secondaire
forward-addr: 2620:fe::fe@853 # Quad9 / IPv6
forward-addr: 2606:4700:4700::1111@853 # Cloudflare / IPv6
forward-addr: 2606:4700:4700::1001@853 # Cloudflare secondaire / IPv6
(…)
Explications :
forward-ssl-upstream
ou son pendant forward-tls-upstream
-
(cette dernière semble n’être pas reconnue… sous OpenBSD) oblige
toutes les requêtes name: "."
à communiquer en mode DoT -
normalement la documentation unbound informe qu’il faut aussi configurer
l’option ssl-cert-bundle
, ou son pendant tls-cert-bundle
,
voire l’option tls-win-cert
pour authentifier les connexions.
Cela ne semble pas nécessaire sous OpenBSD. (<= à confirmer !)Un premier test à faire est l’usage de la commande dig
, tel que :
$ dig com. SOA +dnssec
; <<>> DiG 9.10.3-P4-Debian <<>> com. SOA +dnssec
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60764
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 14, ADDITIONAL: 1
(…)
Ce qu’il faut repérer dans la sortie complète de la commande dig
est
sur la ligne flags:
: il faut la présence du drapeau ad
-
si celui-ci figure bien, c’est bon signe ! :D
$ dig com. SOA +dnssec | grep ";; flags"
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
L’autre commande à utiliser est la commande unbound-host
qui permet de
s’assurer du même résultat, tel que :
$ unbound-host -v -f /var/unbound/db/root.key com.
com. has no address (secure)
com. has no IPv6 address (secure)
com. has no mail handler record (secure)
$ unbound-host -v -f /var/unbound/db/root.key www.ripe.net
www.ripe.net has address 193.0.6.139 (secure)
www.ripe.net has IPv6 address 2001:67c:2e8:22::c100:68b (secure)
www.ripe.net has no mail handler record (secure)
$ unbound-host -v -f /var/unbound/db/root.key www.afnic.fr
www.afnic.fr is an alias for lb01-1.nic.fr. (secure)
lb01-1.nic.fr has address 192.134.5.24 (secure)
lb01-1.nic.fr has IPv6 address 2001:67c:2218:30::24 (secure)
lb01-1.nic.fr has no mail handler record (secure)
$ unbound-host -v -f /var/unbound/db/root.key dnssec.cz
dnssec.cz has address 217.31.205.51 (secure)
dnssec.cz has IPv6 address 2001:1488:0:3::5 (secure)
dnssec.cz mail is handled by 10 mail.nic.cz. (secure)
dnssec.cz mail is handled by 15 mx.nic.cz. (secure)
dnssec.cz mail is handled by 20 bh.nic.cz. (secure)
# unbound-host -v -C /var/unbound/etc/unbound.conf dnssec.cz
dnssec.cz has address 217.31.205.51 (secure)
dnssec.cz has IPv6 address 2001:1488:0:3::5 (secure)
dnssec.cz mail is handled by 10 mail.nic.cz. (secure)
dnssec.cz mail is handled by 15 mx.nic.cz. (secure)
dnssec.cz mail is handled by 20 bh.nic.cz. (secure)
Un moyen visuel est d’ouvrir votre navigateur internet favori, puis d’aller sur les sites suivants :
Pour savoir comment :
Dans le contexte de mon projet NAS **OpenBSD Multimedias View-IT que j’ai présenté, il y a quelques jours, j’ai durci le système de fichiers OpenBSD .
L’expérience m’apprenant que mettre à niveau son OpenBSD sur un système de fichiers durci n’est pas si simple qu’on pourrait le croire - et ce n’est pas la faute directement de l’installateur d’OpenBSD.
À quoi faut-il penser ?
/etc/rc.local
, etc/rc.shutdown
,
voire /etc/daily.local
, ou à les déplacer le temps de la mise à niveau !
(en effet, les services et autres scripts inscrits dedans pourraient
démarrer, s’arrêter inutilement, voire de manière impromptue, surtout indésirée !)Pourquoi ?
Le problème ne se situe pas lors de la mise à jour du système après avoir récupérer le nouveau bsd.rd, l’avoir vérifié, puis démarré dessus ; il se situe après le démarrage du nouveau noyau, lors de l’exécution de certains scripts, qui eux ont besoin d’écrire et d’interagir sur le système, mais qui ne le peuvent !
Donc, voici mon nouvel article qui explique comment faire pour mettre à niveau sereinement son système de fichiers durci, par quelles étapes passer, et les raisons de celles-ci ;-)
Voilà !
Officiellement, il faut éditer le fichier /etc/rc.securelevel
et lui
écrire : sysctl -w kern.securelevel=1
puis redémarrer la machine !
Si vous avez eu la bonne idée de durcir votre FS par l’usage - principalement -
de l’option de montage ro
sur les principales
partitions de votre système, il va falloir user de l’astuce suivante :
/etc/fstab
, telle que montrée
dans mon article
OpenBSD : durcir le système de fichier
, alors
faites tout simplement en premier :
# mv /etc/fstab /root/fstab ; mv /root/fstab.origin /etc/fstab ; chmod 0644 /etc/fstab
/etc/fstab
pour transformer toutes les écritures de
l’option ro
en rw
et mettre en commentaire la ligne déclarant le fichier
de swap mfs pour /dev
. Soit vous le faites à la main, soit vous utilisez ce one-liner :
# sed -i -e 's/ro/rw/g;s/swap \/dev mfs \(.*\)/#swap \/dev mfs \1/g' /etc/fstab
Ceci étant fait, vérifiez l’écriture de votre système de fichier dans
le fichier /etc/fstab
, afin d’être bien sûr de l’écriture de
celui-ci !
Pensez à mettre de côté les scripts /etc/rc.local
, /etc/rc.shutdown
,
voire /etc/daily.local
, - si vous en avez créez - afin d’être
tranquille lors de la mise à niveau !
Puis faites votre procédure de mise à niveau selon le Guide de Migration fourni par l’équipe OpenBSD - par exemple, celui de la 6.4 et sa traduction (in)officielle en Français…
En fait, l’installateur d’OpenBSD passe en rw
lors de la mise à
niveau ; le problème se pose après le redémarrage du système mise à
niveau. En effet, logiquement le système va faire exécuter ses routines
liées au script /etc/sysmerge
et /etc/rc.firsttime
qu’il renomme
pour l’occasion en *.run
respectivement - ce qui a normalement pour
propos d’exécuter les utilitaires sysmerge
, fw_update
principalement…
Si le système est initialement en mode lecture seule avant la mise à
niveau, lesdits processus échoueront et vous avertiront par des messages
d’erreurs vous informant que le système ne peut pas renommer les deux
scripts en *.run
, ni exécuter de fait leur contenu, et donc ne peut
finaliser correctement la mise à niveau !
Il ne vous restera plus qu’à appeler vous-même l’exécution des
binaires sysmerge
, fw_updates
en espérant que tout se passe
correctement… :(
Puis vous pourrez terminer le processus de migration en mettant à jour
les packages ; ceci une fois fait, il ne vous restera plus qu’à faire
une analyse de l’ensemble du système grâce aux deux outils, l’un natif
pkg_check
, l’autre à installer sysclean
.
OU, alors, à relancer à nouveau la mise à niveau de votre
système, en appelant le binaire bsd.rd
au redémarrage de la
machine, SEULEMENT après avoir pris les précautions
nécessaires pour remettre le système de fichiers en écriture
avant le redémarrage !
/etc/rc.local
, /etc/rc.shutdown
,
voire /etc/daily.local
, en veillant à ce que les droits utilisateurs
soient bien liés à root:wheel
et en 0644
.Cet article devait vous permettre d’avoir des binaires debian, pour votre imprimante multi-fonctions, appelés MFP , depuis le site de téléchargement de l’entreprise Seiko Epson.
printer-driver-escpr
, anciennement epson-inkjet-printer-espcr,
fonctionnel pour beaucoup d’imprimantes MFP Epson.Pour ce qui est de configurer la partie Scanner, lisez MFP Scanner Epson sous Debian/Devuan.
sources.list
Avec les droits administrateur, modifiez le fichier sources.list
ou
mieux créez un fichier epson.list
correspondant :
# apt edit-sources epson
deb http://download.ebz.epson.net/dsc/op/stable/debian/ lsb3.2 main
La clé GPG est celle-là :
# apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 8AA65D56
Si vous avez correctement configuré votre fichier personnel ~/.gnupg/gpg.conf
,
il est très possible que vous ayez ce message d’erreur concernant la clé
GPG fournie par Epson :
Signature by key E5220FB7014D0FBDA50DFC2BE5E86C008AA65D56 uses weak digest algorithm (SHA1)
Cela signifie simplement que leur clé a été créé avec le protocole par défaut SHA1… bref, une clé peu fiable !!!
Vous ne devriez probablement pas l’utiliser, mais c’est le seul moyen fourni par eux ; à vous de voir, si vous voulez lui faire confiance ; en tout cas, ne signez pas une telle clé !!!
cf : gpg.conf
Puis mettez à jour votre système !
Tous les pilotes EPSON, pour Debian et assimilés, sont disponibles à partir de l’URL suivante : http://download.ebz.epson.net/dsc/search/01/search/?OSC=LX
lsb
, voire
lsb-base
, installé dans le système… Si ce n’est pas fait, faites-le !Certains pilotes sont spécifiques à plusieurs imprimantes ; d’autres sont plus génériques.
L’information correspondant au nom de votre MFP est signifiée dans l’onglet Description de la fenêtre Propriétés des binaires proposés, ou la partie Information de l’outil Synaptic.
Autrement, avec l’outil apt, faites d’abord une recherche :
# apt-cache search nom_modele
Où nom_modele
est le nom du modèle de votre imprimante, tels que BX525WD,
SX210, WF-7510, etc…
Une fois le(s) pilote(s) installé(s), il vous faut utiliser l’outil de
configuration Imprimantes, à partir du menu Systèmes, ou à partir du
navigateur web à l’adresse : http://localhost:631
, pour installer et
configurer votre MFP.
Le protocole qui fonctionnera à tous les coups est le protocole lpd,
tel que : lpd://adr_ip/PASSTHRU
D’autres protocoles peuvent fonctionner, tel que :
ipp://adr_ip:631/ipp/print
http://adr_ip:631/ipp/print
socket://adr_ip:9100
Même si la détection par protocole dnssd semble fonctionner sans soucis, si les paquets correspondants sont installés, je ne suis personnellement pas arrivé à utiliser celui-ci au quotidien.
Retrouvez les informations concernant l’utilisation et la configuration de la partie scanner de votre MFP : MFP Scanner Epson sous Debian/Devuan
Il existe trois moyens différents pour arriver à installer/configurer une imprimante Epson :
printer-driver-escpr
, anciennement epson-inkjet-printer-espcr,
fonctionnel pour beaucoup d’imprimantes MFP Epson.Vérifiez que votre imprimante apparaisse dans la liste suivante sur la page du projet…
Si c’est le cas, il vous suffit de :
Si cela n’est pas le cas, vérifier que le paquet soit installé : printer-driver-gutenprint
Pour information :
ijsgutenprint
(qui est le pilote
GhostScript pour Gutenprint) et ijsgutenprint-ppds
ainsi que du
paquet foomatic-db-gutenprint
gutenprint-locales
fournit la gestion internationale des langues.escputil
pour assurer la maintenance des
modèles Stylus (nettoyage, alignement des têtes et niveaux d’encres).gimp-gutenprint
qui se trouve être un greffon pour assurer correctement l’impression
à partir de ce logiciel.Cette méthode permet aussi de gérer votre imprimante si elle fonctionne sur le réseau. Si celle-ci est supportée, restituez son adresse IP, dans le Gestionnaire d’Imprimantes !
Si malgré tout l’imprimante n’est pas supporté, essayez soit la méthode par le biais des dépôts d’Epson, soit par ceux d’OpenPrinting.
OpenPrinting est le site référence de la Fondation Linux qui recense les imprimantes, certaines marques, certains modèles fonctionnels sous Linux, grâce principalement au projet Gutenprint.
Dans un premier temps, recherchez dans la page Epson si votre imprimante est listée. Si c’est le cas, cliquez sur le lien correspondant… à votre imprimante, pour de plus amples informations.
De deux choses l’une, soit votre imprimante est :
Perfectly
- très bon signe -Mostly
- un peu moins bon, mais fonctionnel…Partially
- support très moyen, voire nul -Paperweight
- et là, c’est encore plus le drame.Si elle n’apparaît nulle part … il y a vraiment peu d’espoir ! Désolé … soit il vous faudra patienter, soit elle ne sera jamais supportée !
Si votre imprimante Epson est référencée dans les deux premières catégories principalement, tant mieux.
La page ‘Downloads’ du site permet de télécharger des fichiers PPD, mais aussi Foomatic, voire des pilotes IJS. Normalement, votre distribution propose depuis ses dépôts officiels, les-dits fichiers. Ainsi, par exemple, il est possible d’installer les paquets suivants :
foomatic-db
openprinting-ppds
Cette méthode consiste, pour les imprimantes dites MFP - MultiFunctions Printers, en anglais - Imprimantes Multifonctions -, relativement récentes, à utiliser les dépôts que fourni la société Seiko Epson pour installer et gérer correctement.
Veuillez lire le tuto relatif : Debian : Gestion des Imprimantes MFP Epson par depôt
Une fois le(s) pilote(s) installé(s), il vous faut utiliser l’outil de
configuration Imprimantes, à partir du menu “Système”, ou à partir du
navigateur web à l’adresse : http://localhost:631
, pour installer et
configurer votre MFP.
Après la phase de configuration, parfois l’imprimante ou la partie
scanner ne répond pas. Pensez à redémarrer le service udev
… ou, au
pire à redémarrer votre ordinateur !
Si malgré ces trois méthodes, votre imprimante de marque Epson n’est pas gérée… Dommage !
Il semble exister un logiciel payant, nommé TurboPrint for Linux qui apporte du support - (cf : la liste des Epson supportées.) celui-ci gère aussi la colorimétrie de manière professionnelle - à vous de voir… je n’en parlerai pas plus.
Voici mon projet de NAS, basé sur… OpenBSD !
Ce NAS fait fonction de :
Démarrons sur une clé USB, pour installer le système sur une clé USB voire un SSD chiffré… qui servira à enregistrer/diffuser les données, tels que fichiers documents, audio, vidéo, etc…
-game* -x* +xbase* +xfont*
, voire plus court -g* -x* +xb* +xf*
!À la fois, pour soulager la clé, mais aussi pour empêcher toute écriture non désirée ou involontaire, et donc toute modification potentielle du système, on va modifier le système de fichier de telle manière que l’on ne puisse ni écrire, ni exécuter quoique ce soit sur l’ensemble du système de fichiers.
ro
des partitions suivantes : /
, /usr
, /usr/
et toutes les autres partitions /usr/*
créées logiquement par l’installateurnodev,noexec,nosuid
des partitions /tmp
, et /var
nodev,noexec,nosuid
de la partition /home
- nous pourrions
mettre l’option ro
néanmoins cela complexifie encore plus le processus,
surtout à la connexion SSH, voire sur les autres protocoles.Ensuite il faut veiller à monter les périphériques /dev
dans un système
de fichier temporaire swap de type mfs
afin de ne pas avoir de problèmes
avec les périphériques, avec certains services qui ont besoin de “monter”
dynamiquement, tel SSH… autrement dans ce cas, les connexions auraient dû
mal à se faire, voire à ne pas s’exécuter.
Lire mon article “
OpenBSD : durcir le système de fichier
” -
retrouvez le script sysmount
dans la section Fichiers de configuration
ci-dessous, en fin d’article…
Personnellement, j’utilise deux disques durs en mode Raid 1C (à savoir Raid 1 + chiffrement).
Puis, un troisième qui sert de sauvegarde, lui aussi chiffré.
Dans ce contexte, j’utilise une seule clé USB pour assumer le déchiffrement.
Veuillez lire mon article " OpenBSD : monter un disque dur chiffré automatiquement
“… vous y retrouverez comment chiffrer, mais aussi les informations nécessaires pour le montage automatique de ces disques.
N’oubliez pas de modifier les fichiers /etc/rc.local
et /etc/rc.shutdown
pour attacher et monter le disque dur au démarrage et respectivement le
démonter puis le détacher à l’extinction du serveur.
Retrouvez ces scripts ainsi que le script bioctlr
modifié, dans
la section Fichiers de configuration
ci-dessous, en fin d’article…
Choisissez une arborescence du disque dur NAS chiffré, une fois attaché et
monté sur /mnt/nas
, par exemple, tel que :
/mnt/nas/Documents
- répertoire de tout document numérique crée par
les utilisateurs, dans leur propre répertoire/mnt/nas/Medias
- qui est le répertoire qui recevra tous les fichiers
images, audios, et vidéos, chacuns dans leur répertoire respectif/mnt/nas/P2P
- qui sert à déposer les fichiers torrents…# mkdir -p /mnt/nas/{Documents,Medias,P2P}
# mkdir -p /mnt/nas/Medias/{Images,Music,Video}
# mkdir /mnt/nas/P2P/torrents
Dans le répertoire de documents, créez autant de répertoires nécessaires que d’utilisateurs qui se serviront de votre NAS, et liez symboliquement ces répertoires vers les répertoires home des utilisateurs :
# mkdir /mnt/nas/Documents/$user
# chown $user /mnt/nas/Documents/$user
# chmod 0700 /mnt/nas/Documents/$user
# ln -s /mnt/nas/Documents/$user /home/$user/Documents
Ensuite, liez symboliquement les différents répertoires de médias, et celui des torrents avec votre utilisateur principal - le premier utilisateur que vous aurez créé, qui seul aura le droit d’écrire dedans.
# chown -R $user /mnt/nas/{Medias,P2P}
# for name in Images Music Video; do ln -s /mnt/nas/Medias/$name /home/$user/$name; done
Si jamais vous voulez que chacun des utilisateurs systèmes que vous créerez ait son propre répertoire dans les différents répertoires des médias, appliquez la même méthode que le code ci-dessus pour la création des répertoires utilisateurs dans le répertoire des documents, mais faites-le sur le répertoire des médias, tel que :
# for name in Images Music Video; do mkdir -p /mnt/nas/Medias/$user/$name && ln -s /mnt/nas/Medias/$user/$name /home/$user/$name; done
# chown -R $user /mnt/nas/Medias/$user
# chmod 0700 /mnt/nas/Medias/$user
Dans la suite de ce tutoriel, nous resterons sur la situation simple où seul l’utilisateur principal a des droits en écriture sur les trois répertoires enfants…
En cas où vous avez un énième disque dur, qui lui servirait de sauvegarde des données écrites sur le disque NAS, le script de montage automatique est profondément modifié pour pouvoir attacher et monter cet autre disque dur, qui lui aussi sera chiffré, bien sûr !
Actuellement, j’utilise Borg pour effectuer ma sauvegarde.
Retrouvez les différents fichiers de configuration disponibles, tels que :
ALERTE : Tous ces services seront automatiquement démarrés que si et seulement si le disque dur chiffré est attaché ET monté. En effet, cela ne sert à rien de les activer et de les démarrer si le disque dur n’est pas correctement monté ; ils se mettraient en échec inutilement !
Ils seront donc activé à partir du script /etc/rc.local
et arrêté avant
l’extinction machine, depuis le script /etc/rc.shutdown
.
Si vous souhaitez en faire un serveur multimédia, j’explique l’installation et surtout la configuration du service MiniDLNA dans l’article suivant : “ MiniDLNA (OpenBSD) ”.
Pour ce qui est de la configuration du fichier /etc/minidlna.conf
,
voici les modifications faites :
friendly_name=OpenBSD Multimedia View-IT
media_dir=A,/mnt/nas/Medias/your-user/Music
media_dir=V,/mnt/nas/Medias/your-user/Video
max_connections=7
Les explications d’installation de base sont fournies dans cet article “ OpenBSD : Introduction à Samba ”.
Je vous invite à créer un groupe dédié, dans lequel ajouter les différents utilisateurs - ainsi, nous utiliserons les options d’autorisations par groupe, plutôt que par utilisateurs autorisés :
# groupadd _smb
# usermod -G _smb $user
Concernant les modifications du fichier /etc/samba/smb.conf
:
interfaces
: décommentez-la, et écrivez votre réseau lan IPv4, et si
vous avez la bonne idée d’avoir un réseau IPv6 ULA, (de type fd0::/64
,
par exemple) alors faites les ajouts adéquats.server string = OpenBSD NAS
workgroup
- personnellement,
je le fais en le renommant par une seule lettre, me facilitant la vie ;)hosts allow = 192.168.1. fd0::/64
- Attention à bien modifier
selon vos propres adressages IP…Utilisons la section [Homes] pour autoriser la connexion à nos différents utilisateurs, à leurs répertoires Documents.
Code : cfg
Section [homes]
browseable = No
comment = Documents
create mask = 0644
directory mask = 0700
force directory mode = 0700
hide dot files = No
hide special files = Yes
hosts allow =
path = /mnt/nas/Documents/
read only = No
valid users =
write list =
browseable = no
: le parcours du répertoire par tout autre que les
utilisateurs autorisés est interdit ;create mask
force le chmod sur les fichiers créés/ajoutés/modifiésdirectory mask
et force directory mode
obligent le chmod en question
sur les répertoires.hide dot files = No
autorise la lecture des fichiers et répertoires
cachés - ce qui pour un utilisateur autorisé, sur ses propres fichiers,
est normal.hide special files = Yes
empêche la lecture de tout fichier spécialhosts allow
indiquons IMPÉRATIVEMENT les adresses IP des machines
autorisées à se connecter à ce partage…read only
: étant que nous voulons autoriser les utilisateurs à écrire/ajouter
leurs propres documents, laissons/mettons la sur no
valid users
renfermera les utilisateurs, ou le groupe samba dédié,
autorisés à se connecter à ce partage - à remplir impérativement -
c’est ici que nous ajouterons, de préférence, le groupe smb
que
je vous ai invité à créer dans l’astuce au début de ce chapitre,
tel que : valid users = @_smb
write list
autorisera seuls les utilisateurs renseignés à pouvoir écrire
dans ce partage ! -
c’est ici qu’il est préférable d’ajouter le groupe samba dédié, créé
plutôt, tel que : write list = @_smb
Maintenant occupons nous des partages Samba pour les documents audios, et
vidéos - la configuration sera exactement la même, seul le nom de section
change ainsi que les options comment
, path
… !
Nous appellerons, par préférence, :
Section [Music]
,Section [Video]
.[homes]
, permettons que ces partages multimédias
soient parcourables par tous : browseable = yes
, et guest ok = yes
read only = yes
nous y aidera. De même que l’option printable = no
empêchera toute tentative d’impression des documents…hide dot files = yes
et hide special files = yes
write list
nous permettra d’autoriser au moins votre utilisateur
à écrire dedans ! :pCode : cfg
[Music]
browseable = yes
comment = Musique
create mask = 0664
directory mask = 0755
ea support = no
force directory mode = 0755
guest ok = yes
hide dot files = yes
hide special files = yes
inherit acls = yes
inherit permissions = no
path = /mnt/nas/Medias/Music/
printable = no
read only = yes
store dos attributes = no
write list =
Code : cfg
[Video]
browseable = yes
comment = Videos
create mask = 0664
directory mask = 0755
ea support = no
force directory mode = 0755
guest ok = yes
hide dot files = yes
hide special files = yes
inherit acls = yes
inherit permissions = no
path = /mnt/nas/Medias/Video/
printable = no
read only = yes
store dos attributes = no
write list =
À la différence des autres services, celui-ci sera bel et bien monté normalement
dès le démarrage de la machine… et donc géré depuis le fichier /etc/rc.conf.local
par le biais de l’outil rcctl
.
En effet, nous voulons pouvoir y accèder à tout moment…
Veuillez lire mon article suivant sur comment avoir une
configuration et générer des clés sécurisées , actuellement !
Étant donné que mon utilisateur système principal est autorisé à se connecter en SSH sur le serveur, il est facile de monter localement le système de fichier, soit par SSHFS en mode console, soit avec un outil graphique, tel que Gigolo.
C’est plus lent qu’avec le partage Samba, ce qui est normal du fait de la couche “sécurité” lié aux chiffrements de la connexion… mais c’est aussi pratique ET à ma préférence ! :D
Enjoy-ID! Enjoy-IT!
La suite Samba est un ensemble de programmes qui implémentent un serveur pour les protocoles de partage de fichiers, d’imprimantes Windows (SMB /CIFS ) ainsi que de contrôleur de domaine compatible avec Active Directory.
Installez
le
paquet samba
!
Il va être nécessaire de créer le répertoire /var/run/samba
et
d’attribuer les droits systèmes 0755
sur les répertoires /var/samba
et /var/cache/samba
.
Il faut créer un premier utilisateur qui sera autorisé :
# pdbedit -a -u $user
La commande pdbedit
est utile pour gérer, non seulement les utilisateurs
mais aussi pour vérifier certaines choses, grâce au jeu des options :
-a
ou --create
: pour créer un nouvel utilisateur ; il est nécessaire
d’ajouter l’option -u
avant de spécifier le nom de l’utilisateur
-L
ou --list
liste les différents utilisateurs gérés, dans un format
simple, abrégé.
-L -v
affiche toutes les informations liées aux différentes informations
utilisateurs, de manière complète. La version contractée -Lv
est
fonctionnelle.
-c
ou --account-control
permet de spécifier les propriétés du compte
utilisateur… plusieurs drapeaux définissent le contrôle
-D
ou --drive
permet de définir la lettre de mappage du lecteur réseau
à utiliser, tel que -D "H: "
-h
ou --homedir
permet de redéfinir le chemin réseau du répertoire
personnel d’un utilisateur
-l
ou --log-basename=/repertoire_des_logs
spécifie le répertoire
du fichier journal
-s
ou --configfile=nom_de_fichier_config
spécifie le fichier de
configuration.
-v
ou --verbose
est le mode verbeux
-x
ou --delete
pour supprimer un utilisateur…
Bien sûr, il existe d’autres options intéressantes ; lisez le manpage, installé en même temps que le logiciel samba.
Contrairement à ce qu’on pense, la configuration n’est pas compliquée - un peu longue, mais pas compliquée ;)
wins:*
- laissez-les commenter !Tout se fait principalement dans le fichier /etc/samba/smb.conf
:
# This is the main Samba configuration file. You should read the
# smb.conf(5) manual page in order to understand the options listed
# here. Samba has a huge number of configurable options (perhaps too
# many!) most of which are not shown in this example
#
# For a step to step guide on installing, configuring and using samba,
# read the Samba-HOWTO-Collection. This may be obtained from:
# http://www.samba.org/samba/docs/Samba-HOWTO-Collection.pdf
#
# Many working examples of smb.conf files can be found in the
# Samba-Guide which is generated daily and can be downloaded from:
# http://www.samba.org/samba/docs/Samba-Guide.pdf
#
# Any line which starts with a ; (semi-colon) or a # (hash)
# is a comment and is ignored. In this example we will use a #
# for commentry and a ; for parts of the config file that you
# may wish to enable
#
# NOTE: Whenever you modify this file you should run the command "testparm"
# to check that you have not made any basic syntactic errors.
#
#======================= Global Settings =====================================
[global]
# workgroup = NT-Domain-Name or Workgroup-Name, eg: MIDEARTH
workgroup = Workgroup
# server string is the equivalent of the NT Description field
server string = Samba Server
# Server role. Defines in which mode Samba will operate. Possible
# values are "standalone server", "member server", "classic primary
# domain controller", "classic backup domain controller", "active
# directory domain controller".
#
# Most people will want "standalone server" or "member server".
# Running as "active directory domain controller" will require first
# running "samba-tool domain provision" to wipe databases and create a
# new domain.
server role = standalone server
# This option is important for security. It allows you to restrict
# connections to machines which are on your local network. The
# following example restricts access to two C class networks and
# the "loopback" interface. For more examples of the syntax see
# the smb.conf man page
; hosts allow = 192.168.1. 192.168.2. 127.
# Uncomment this if you want a guest account, you must add this to /etc/passwd
# otherwise the user "nobody" is used
; guest account = pcguest
# this tells Samba to use a separate log file for each machine
# that connects
log file = /var/log/samba/smbd.%m
# Put a capping on the size of the log files (in Kb).
max log size = 50
# Specifies the Kerberos or Active Directory realm the host is part of
; realm = MY_REALM
# Backend to store user information in. New installations should
# use either tdbsam or ldapsam. smbpasswd is available for backwards
# compatibility. tdbsam requires no further configuration.
; passdb backend = tdbsam
# Using the following line enables you to customise your configuration
# on a per machine basis. The %m gets replaced with the netbios name
# of the machine that is connecting.
# Note: Consider carefully the location in the configuration file of
# this line. The included file is read at that point.
; include = /usr/local/samba/lib/smb.conf.%m
# Configure Samba to use multiple interfaces
# If you have multiple network interfaces then you must list them
# here. See the man page for details.
; interfaces = 192.168.12.2/24 192.168.13.2/24
# Where to store roving profiles (only for Win95 and WinNT)
# %L substitutes for this servers netbios name, %U is username
# You must uncomment the [Profiles] share below
; logon path = \\%L\Profiles\%U
# Windows Internet Name Serving Support Section:
# WINS Support - Tells the NMBD component of Samba to enable it's WINS Server
; wins support = yes
# WINS Server - Tells the NMBD components of Samba to be a WINS Client
# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
; wins server = w.x.y.z
# WINS Proxy - Tells Samba to answer name resolution queries on
# behalf of a non WINS capable client, for this to work there must be
# at least one WINS Server on the network. The default is NO.
; wins proxy = yes
# DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names
# via DNS nslookups. The default is NO.
dns proxy = no
# These scripts are used on a domain controller or stand-alone
# machine to add or delete corresponding unix accounts
; add user script = /usr/sbin/useradd %u
; add group script = /usr/sbin/groupadd %g
; add machine script = /usr/sbin/adduser -n -g machines -c Machine -d /dev/null -s /bin/false %u
; delete user script = /usr/sbin/userdel %u
; delete user from group script = /usr/sbin/deluser %u %g
; delete group script = /usr/sbin/groupdel %g
#============================ Share Definitions ==============================
[homes]
comment = Home Directories
browseable = no
; follow symlinks = yes
; wide links = yes
writable = yes
(…)
Les options importantes en terme de sécurité sont :
hosts allow
permet de restreindre l’accès à un réseau local, une adresse
IP précise, et empêchera tout autre hôte à se connecter.interfaces
permet de cibler sur quelle interface réseau les services
de Samba seront diffusés et autorisés.valid users
permet de spécifier quels utilisateurs ou groupe d’utilisateurs
ont le droit d’accéder aux différents partages, ou services fournis.Garder à l’esprit que le fichier de configuration est, de base, minimaliste, et dans l’état n’offre aucune sécurité !
J’attire votre attention sur le manpage très long de smb.conf(5), disponible de par l’installation du paquet samba.
Pour les besoins de test de fonctionnement, ne pas toucher au reste de la configuration…
La commande testparm
est utile pour vérifier que le configuration du
fichier soit correcte.
À exécuter AVANT de démarrer le service, et APRÈS toute modification…
Si testparm se plaint du message suivant :
Weak crypto is allowed
Sachez qu’il n’est rien possible de faire, à moins d’utiliser le mode FIPS
seulement.
Cela ne signifie pas que Samba utilise une cryptographie faible, ou qu’elle est permise. Dans les faits, Samba utilise GnuTLS, qui dans des contextes de compatibilité, basculera sur de faibles algorithmes cryptographiques autorisés par GnuTLS.
Et, oui, le message n’est pas clair !
Pour plus d’informations:
Il est nécessaire de reconfigurer les limites systèmes en ajoutant :
/etc/login.conf.d/samba
pour y ajouter le bloc suivant :samba:\
:openfiles-max=16384:\
:tc=daemon:
/etc/sysctl.conf
pour modifier de manière permanente
kern.maxfiles
: kern.maxfiles=16384
Ces modifications systèmes nécessitent au plus simple de redémarrer votre machine !
Les règles pour le pare-feu PF sont très simples à paramétrer :
# lan: IPv4
lan="192.168.1.0/24"
# adress IPv4 of my host
myhost="192.168.1.1"
smb_ports_tcp = "{ 135 137 139 445 }"
smb_ports_udp = "{ 135 137 138 445 }"
(...)
pass in quick on egress proto tcp from $lan to $myhost port $smb_ports_tcp flags S/SA modulate state
pass in quick on egress proto udp from $lan to $myhost port $smb_ports_udp allow-opts
pass in quick on egress inet proto udp from $myhost to $lan port 138 allow-opts
pass out quick on egress proto tcp from $myhost to $lan port $smb_ports_tcp flags S/SA modulate state
pass out quick on egress proto udp from $myhost to $lan port $smb_ports_udp allow-opts
Elles sont à configurer et sur le serveur Samba, et sur votre station.
Bien sûr, ces règles sont un exemple ; il faut les adapter à vos besoins.
Sous OpenBSD 6.5, il y a un problème avec le lancement de Samba, créant des
timeouts
.
J’explique sur le forum de la communauté française “OpenBSD Pour Tous” la raison et le fait qu’il est nécessaire de lancer à nouveau le service samba ; pas de le relancer, juste le démarrer !
# rcctl start samba
smbd(timeout)
# rcctl check samba
smbd(ok)
nmbd(failed)
# rcctl start samba
nmbd(ok)
#rcctl check samba
smbd(ok)
nmbd(ok)
Il est possible de vérifier que les processus soient bien lancés :
$ ps auxw | grep mbd
(faites le après le timeout et après la deuxième exécution du start,
vous comprendrez !)
man 8 pdbedit
, man 5 smb.conf
Ainsi que le met en exergue le manpage de smb.conf
, il est fortement
conseillé de lire les deux guides suivants, fournis par le projet :
Ces guides sont basés sur Samba v3. Et, même si nous utilisons une version supérieure, il y a toujours quelque chose de bon à en tirer, à en apprendre…
Localement sur le système, retrouvez les fichiers de :
/usr/local/share/doc/pkg-readmes/samba
/usr/local/share/examples/samba/smb.conf.default
Enjoy-ID Enjoy-IT!
Par défaut, actuellement le niveau de sécurité par défaut d’OpenBSD semble être déjà un acquis.
Le manpage securelevel nous restitue une information pertinente. Il est possible d’augmenter ce
niveau en utilisant la commande sysctl
, telle que :
# sysctl -w kern.securelevel=2
Mais soyez conscient des difficultés créées :
Un autre moyen est de rester en securelevel
par défaut à 1
, mais
d’utiliser les options de montage, tel que ro
principalement, mais
aussi nodev,noexec,nosuid
sur les différentes partitions du système de
fichier ffs.
Pour cela, il faut d’abord modifier le fichier /etc/fstab
, de manière
à ce que soit créé au démarrage un système de fichier mfs
(swap)
pour monter les périphériques /dev
dedans
Ne pas oublier cette écriture, sinon, vous aurez quelques difficultés pour "monter" dynamiquement certains périphériques spéciaux , parfois nécessaires, pour certains services, tel SSH !
Copiez votre fichier /etc/fstab
de manière à en faire une sauvegarde - cela pourrait être utile plus tard !
# cp /etc/fstab /root/fstab.origin ; chmod 0400 /root/fstab.origin
/etc/fstab
Fichier : /etc/fstab
|
|
sysmount
Le script sysmount
nous facilitera la vie, pour autoriser l’écriture et verrouiller des différentes partitions le nécessitant :
Fichier : sysmount
|
|
L’usage en est très simple : avant l’installation d’un binaire, ou la modification d’un fichier de configuration, un coup de :
./sysmount rw
pour autoriser l’écriture sur le système de fichier,./sysmount ro
pour l’empêcher à nouveau`et, voilà !
Lorsqu’il faudra mettre à niveau le système d’exploitation, veuillez lire cet autre article : [Mini-Tuto] Upgrade Hardened OpenBSD
Un petit “gros” merci @Vincent pour ces tutoriels sur le durcissement du système de fichier OpenBSD : ici ou là.
Retrouvez ci-dessous la traduction EN → FR de l’article “Running OpenBSD on Raspberry Pi 3”, écrit par Joel Carnat.
Pour installer OpenBSD 6.3 sur le Raspberry Pi 3 v1.2, j’ai utilisé une microSD de 128 Mo (pour héberger l’installateur), un adaptateur USB pour la microSD, une clé USB sans marque de 30 Go, un convertisseur USB-TTL et un câble RJ45.
Tout a été fait depuis un Macbook Pro utilisant MacOS 10.13.5. Les commandes de préparation ne devraient pas différer beaucoup si vous utilisez un des *BSD ou Linux.
J’ai démarré les deux versions d’OpenBSD 6.3, la stable et la current mais le support matériel était le même. Pas d’interface Wifi…
Récupérez votre fichier d’installation d’OpenBSD favori. J’ai utilisé miniroot63.fs.
Formatez votre microSD et votre clé USB. Cela n’est absolument pas requis mais je préfère démarrer vraiment vide.
# diskutil list
# diskutil unmountDisk /dev/disk2
# dd if=/dev/zero of=/dev/disk2 count=4096
(…)
# diskutil eject /dev/disk2
Disk /dev/disk2 ejected
# diskutil unmountDisk /dev/disk3
# dd if=/dev/zero of=/dev/disk3 count=4096
(…)
# diskutil eject /dev/disk3
Disk /dev/disk3 ejected
Insérez la microSD au dos du MacBook, ignorez les messages d’initialisation de MacOS et copiez le fichier miniroot.fs sur la carte.
# diskutil list
(…)
/dev/disk2 (external, physical):
#: TYPE NAME SIZE IDENTIFIER
0: *126.0 MB disk2
# dd if=miniroot63.fs of=/dev/disk2 bs=1m
21+0 records in
21+0 records out
22020096 bytes transferred in 7.937130 secs (2774315 bytes/sec)
# diskutil list
(…)
/dev/disk2 (external, physical):
#: TYPE NAME SIZE IDENTIFIER
0: FDisk_partition_scheme *126.0 MB disk2
1: Windows_FAT_32 BOOT 4.2 MB disk2s1
2: OpenBSD 13.6 MB disk2s4
# diskutil eject /dev/disk2
Disk /dev/disk2 ejected
Pour être capable de démarrer depuis la clé USB, le Raspberry a été
“patché”. Cela a été fait en ajoutant un drapeau dans le OTP. Vous
devrez insérer la microSD dans le Mac, et éditer le fichier
BOOT/config.txt
en ajoutant une simple ligne de code.
|# echo “program_usb_boot_mode=1” » /Volumes/BOOT/config.txt|
Insérez la microSD dans le slot microSD du RPI3, la clé USB dans un des connecteurs USB du RPI3. Connectez le câble Ethernet au RPI3. Connectez le RPI3 et le MacBook en utilisant l’adaptateur USB TTL.
Depuis mon terminal, j’ai utilisé les commandes suivantes pour accéder à la console :
# cu -l /dev/cu.usbserial -s 115200 | tee cu.log
Branchez le câble électrique microUSB au RPI3. J’ai utilisé un câble microUSB-USB et l’ai connecté au port USB3 de mon Synology. Cela a fonctionné. Bien que la console émette parfois des messages d’avertissements relatifs à la tension.
Vérifiez dans la console que tout démarre :
U-Boot 2018.03 (Mar 20 2018 - 04:28:27 -0600)
DRAM: 948 MiB
RPI 3 Model B (0xa02082)
U-Boot 2018.03 (Mar 20 2018 - 04:28:27 -0600)
DRAM: 948 MiB
RPI 3 Model B (0xa02082)
MMC: mmc@7e202000: 0, sdhci@7e300000: 1
Loading Environment from FAT… *** Warning - bad CRC, using default environment
Failed (-5)
In: serial
Out: vidconsole
Err: vidconsole
Net: No ethernet found.
starting USB…
USB0: Core Release: 2.80a
scanning bus 0 for devices… 4 USB Device(s) found
scanning usb for storage devices… 1 Storage Device(s) found
Hit any key to stop autoboot: 0
U-Boot> usb storage
Device 0: Vendor: USB Rev: 1100 Prod: Flash Disk
Type: Removable Hard Disk
Capacity: 30720.0 MB = 30.0 GB (62914560 x 512)
U-Boot> boot
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1…
Found EFI removable media binary efi/boot/bootaa64.efi
Scanning disk mmc@7e202000.blk…
Card did not respond to voltage select!
Scanning disk sdhci@7e300000.blk…
Disk sdhci@7e300000.blk not ready
Scanning disk usb_mass_storage.lun0…
Found 4 disks
82780 bytes read in 12 ms (6.6 MiB/s)
## Starting EFI application at 01000000 …
>> OpenBSD/arm64 BOOTAA64 0.11
boot>
cannot open sd0a:/etc/random.seed: No such file or directory
booting sd0a:/bsd: 2417208+377168+8373432-
+732352 [179732+96+291264+160768]=0xf498
f0
type 0x0 pa 0x0 va 0x0 pages 0x1 attr 0x8
type 0x7 pa 0x1000 va 0x0 pages 0x1ff attr 0x8
type 0x2 pa 0x200000 va 0x200000 pages 0x4000 attr 0x8
type 0x7 pa 0x4200000 va 0x0 pages 0x3e00 attr 0x8
type 0x6 pa 0x8000000 va 0xe0250b000 pages 0x8 attr 0x8000000000000008
type 0x7 pa 0x8009000 va 0x0 pages 0x312c0 attr 0x8
type 0x2 pa 0x392c9000 va 0x392c9000 pages 0x4 attr 0x8
(…)
type 0x2 pa 0x39f41000 va 0x39f41000 pages 0x146a attr 0x8
type 0x5 pa 0x3b3ab000 va 0xe358b6000 pages 0x1 attr 0x8000000000000008
type 0x2 pa 0x3b3ac000 va 0x39f41000 pages 0x54 attr 0x8
type 0xb pa 0x3f100000 va 0xe358b7000 pages 0x1 attr 0x8000000000000000
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.
Copyright (c) 1995-2018 OpenBSD. All rights reserved. https://www.OpenBSD.org
OpenBSD 6.3 (RAMDISK) #212: Sat Mar 24 20:24:43 MDT 2018
deraadt@arm64.openbsd.org:/usr/src/sys/arch/arm64/compile/RAMDISK
real mem = 959180800 (914MB)
avail mem = 892710912 (851MB)
mainbus0 at root: Raspberry Pi 3 Model B Rev 1.2
cpu0 at mainbus0 mpidr 0: ARM Cortex-A53 r0p4
efi0 at mainbus0: UEFI 2.7
efi0: Das U-Boot rev 0x0
simplefb0 at mainbus0: 656x416
wsdisplay0 at simplefb0
wsdisplay0: screen 0 added (std, vt100 emulation)
simplebus0 at mainbus0: "soc"
bcmintc0 at simplebus0
bcmdog0 at simplebus0
bcmrng0 at simplebus0
pluart0 at simplebus0
bcmaux0 at simplebus0
com0 at sim����: ns16550, no workingcom0: console
dwctwo0 at simplebus0
simplebus1 at mainbus0: "clocks"
agtimer0 at mainbus0: tick rate 19200 KHz
usb0 at dwctwo0: USB revision 2.0
uhub0 at usb0 configuration 1 interface 0 "Broadcom DWC2 root hub" rev 2.00/1.00 addr 1
uhub1 at uhub0 port 1 configuration 1 interface 0 "Standard Microsystems product 0x9514" rev 2.00/2.00 addr 2
smsc0 at uhub1 port 1 configuration 1 interface 0 "Standard Microsystems SMSC9512/14" rev 2.00/2.00 addr 3
smsc0: address xx:xx:xx:xx:xx:xx
ukphy0 at smsc0 phy 1: Generic IEEE 802.3u media interface, rev. 3: OUI 0x0001f0, model 0x000c
umass0 at uhub1 port 3 configuration 1 interface 0 "USB Flash Disk" rev 2.00/11.00 addr 4
umass0: using SCSI over Bulk-Only
scsibus0 at umass0: 2 targets, initiator 0
sd0 at scsibus0 targ 1 lun 0: <USB, Flash Disk, 1100> SCSI2 0/direct removable serial.090c1000000000014806
sd0: 30720MB, 512 bytes/sector, 62914560 sectors
bootfile: sd0a:/bsd
boot device: sd0
root on rd0a swap on rd0b dump on rd0b
WARNING: CHECK AND RESET THE DATE!
erase ^?, werase ^W, kill ^U, intr ^C, status ^T
Welcome to the OpenBSD/arm64 6.3 installation program.
(I)nstall, (U)pgrade, (A)utoinstall or (S)hell? i
Procédez à l’installation d’OpenBSD. Ici, rien de spécial. La carte
réseau sera une smsc0
et peut utiliser DHCP. En utilisant -
“Whole disk” - cela créera automatiquement et remplira une partition
MSDOS pour activer le démarrage depuis la clé USB. Au moment d’écrire
cela, il n’est pas possible d’installer OpenBSD sur une microSD ; il
n’y a pas de pilote pour cela. Je ne suis pas sûr, mais il semble
qu’eMMC n’est pas non plus supporté, pas encore. La seule manière
d’installer OpenBSD est d’utiliser un disque USB compatible pour démarrer.
Choisissez - “Halt” - à la fin de l’installation. Déconnectez l’alimentation USB. Enlevez la microSD d’installation.
Reconnectez l’alimention microUSB et regardez OpenBSD démarrer.
U-Boot 2018.03 (Mar 20 2018 - 04:28:27 -0600)
DRAM: 948 MiB
RPI 3 Model B (0xa02082)
MMC: mmc@7e202000: 0, sdhci@7e300000: 1
Loading Environment from FAT… WARNING at /usr/obj/ports/u-boot-aarch64-2018.03-aarch64/u-boot-2018.03/drivers/mmc/bcm2835_sdhost.c:438/bcm2835_send_command()!
WARNING at /usr/obj/ports/u-boot-aarch64-2018.03-aarch64/u-boot-2018.03/drivers/mmc/bcm2835_sdhost.c:438/bcm2835_send_command()!
Card did not respond to voltage select!
** Bad device mmc 0 **
Failed (-5)
In: serial
Out: vidconsole
Err: vidconsole
Net: No ethernet found.
starting USB…
USB0: Core Release: 2.80a
scanning bus 0 for devices… 4 USB Device(s) found
scanning usb for storage devices… 1 Storage Device(s) found
Hit any key to stop autoboot: 0
WARNING at /usr/obj/ports/u-boot-aarch64-2018.03-aarch64/u-boot-2018.03/drivers/mmc/bcm2835_sdhost.c:438/bcm2835_send_command()!
WARNING at /usr/obj/ports/u-boot-aarch64-2018.03-aarch64/u-boot-2018.03/drivers/mmc/bcm2835_sdhost.c:438/bcm2835_send_command()!
WARNING at /usr/obj/ports/u-boot-aarch64-2018.03-aarch64/u-boot-2018.03/drivers/mmc/bcm2835_sdhost.c:438/bcm2835_send_command()!
Card did not respond to voltage select!
Device 0: Vendor: USB Rev: 1100 Prod: Flash Disk
Type: Removable Hard Disk
Capacity: 30720.0 MB = 30.0 GB (62914560 x 512)
… is now current device
Scanning usb 0:1…
Found EFI removable media binary efi/boot/bootaa64.efi
WARNING at /usr/obj/ports/u-boot-aarch64-2018.03-aarch64/u-boot-2018.03/drivers/mmc/bcm2835_sdhost.c:438/bcm2835_send_command()!
WARNING at /usr/obj/ports/u-boot-aarch64-2018.03-aarch64/u-boot-2018.03/drivers/mmc/bcm2835_sdhost.c:438/bcm2835_send_command()!
WARNING at /usr/obj/ports/u-boot-aarch64-2018.03-aarch64/u-boot-2018.03/drivers/mmc/bcm2835_sdhost.c:438/bcm2835_send_command()!
Card did not respond to voltage select!
Scanning disk mmc@7e202000.blk…
Disk mmc@7e202000.blk not ready
Card did not respond to voltage select!
Scanning disk sdhci@7e300000.blk…
Disk sdhci@7e300000.blk not ready
Scanning disk usb_mass_storage.lun0…
Found 3 disks
82780 bytes read in 88 ms (918 KiB/s)
## Starting EFI application at 01000000 …
3996244+595624+583064+805616 [281462+96+464664/
type 0x0 pa 0x0 va 0x0 pages 0x1 attr 0x8
type 0x7 pa 0x1000 va 0x0 pages 0x1ff attr 0x8
type 0x2 pa 0x200000 va 0x200000 pages 0x4000 attr 0x8
type 0x7 pa 0x4200000 va 0x0 pages 0x3e00 attr 0x8
type 0x6 pa 0x8000000 va 0x20987be000 pages 0x8 attr 0x8000000000000008
type 0x7 pa 0x8009000 va 0x0 pages 0x317f6 attr 0x8
type 0x2 pa 0x397ff000 va 0x397ff000 pages 0x4 attr 0x8
(…)
type 0x5 pa 0x3b3ab000 va 0x20cbb69000 pages 0x1 attr 0x8000000000000008
type 0x2 pa 0x3b3ac000 va 0x39f41000 pages 0x54 attr 0x8
type 0xb pa 0x3f100000 va 0x20cbb6a000 pages 0x1 attr 0x8000000000000000
[ using 994392 bytes of bsd ELF symbol table ]
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.
Copyright (c) 1995-2018 OpenBSD. All rights reserved. https://www.OpenBSD.org
OpenBSD 6.3 (GENERIC.MP) #41: Sat Mar 24 20:06:13 MDT 2018
deraadt@arm64.openbsd.org:/usr/src/sys/arch/arm64/compile/GENERIC.MP
real mem = 964644864 (919MB)
avail mem = 905125888 (863MB)
mainbus0 at root: Raspberry Pi 3 Model B Rev 1.2
cpu0 at mainbus0 mpidr 0: ARM Cortex-A53 r0p4
efi0 at mainbus0: UEFI 2.7
efi0: Das U-Boot rev 0x0
simplefb0 at mainbus0: 656x416
wsdisplay0 at simplefb0 mux 1
wsdisplay0: screen 0-5 added (std, vt100 emulation)
simplebus0 at mainbus0: "soc"
bcmintc0 at simplebus0
bcmdog0 at simplebus0
bcmrng0 at simplebus0
pluart0 at simplebus0
bcmtemp0 at simplebus0
bcmaux0 at simplebus0
com0 at sim����: ns16550, no workingcom0: console
dwctwo0 at simplebus0
simplebus1 at mainbus0: "clocks"
agtimer0 at mainbus0: tick rate 19200 KHz
cpu1 at mainbus0 mpidr 1: ARM Cortex-A53 r0p4
cpu2 at mainbus0 mpidr 2: ARM Cortex-A53 r0p4
cpu3 at mainbus0 mpidr 3: ARM Cortex-A53 r0p4
usb0 at dwctwo0: USB revision 2.0
uhub0 at usb0 configuration 1 interface 0 "Broadcom DWC2 root hub" rev 2.00/1.00 addr 1
uhub1 at uhub0 port 1 configuration 1 interface 0 "Standard Microsystems product 0x9514" rev 2.00/2.00 addr 2
smsc0 at uhub1 port 1 configuration 1 interface 0 "Standard Microsystems SMSC9512/14" rev 2.00/2.00 addr 3
smsc0: address xx:xx:xx:xx:xx:xx
ukphy0 at smsc0 phy 1: Generic IEEE 802.3u media interface, rev. 3: OUI 0x0001f0, model 0x000c
umass0 at uhub1 port 3 configuration 1 interface 0 "USB Flash Disk" rev 2.00/11.00 addr 4
umass0: using SCSI over Bulk-Only
scsibus0 at umass0: 2 targets, initiator 0
sd0 at scsibus0 targ 1 lun 0: <USB, Flash Disk, 1100> SCSI2 0/direct removable serial.090c1000000000014806
sd0: 30720MB, 512 bytes/sector, 62914560 sectors
vscsi0 at root
scsibus1 at vscsi0: 256 targets
softraid0 at root
scsibus2 at softraid0: 256 targets
bootfile: sd0a:/bsd
boot device: sd0
root on sd0a (01654b77d1056385.a) swap on sd0b dump on sd0b
WARNING: CHECK AND RESET THE DATE!
Automatic boot in progress: starting file system checks.
/dev/sd0a (01654b77d1056385.a): file system is clean; not checking
setting tty flags
pf enabled
starting network
smsc0: bound to 10.0.0.23 from 10.0.0.1 (xx:xx:xx:xx:xx:xx)
reordering libraries: done.
openssl: generating isakmpd/iked RSA keys… done.
ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519
starting early daemons: syslogd pflogd ntpd.
starting RPC daemons:.
savecore: no core dump
checking quotas: done.
clearing /tmp
kern.securelevel: 0 -> 1
creating runtime link editor directory cache.
preserving editor files.
starting network daemons: sshd smtpd sndiod.
running rc.firsttime
Path to firmware: http://firmware.openbsd.org/firmware/6.3/
No devices found which need firmware files to be downloaded.
Checking for available binary patches… done.
Run syspatch(8) to install:
001_perl
002_libtls
003_arp
004_gif
005_httpd
006_ipseclen
007_libcrypto
008_ipsecout
009_libcrypto
011_perl
starting local daemons: cron.
Sun Mar 25 07:56:40 CEST 2018
OpenBSD/arm64 (bagheera.tumfatig.net) (console)
login: root
Password:
OpenBSD 6.3 (GENERIC.MP) #41: Sat Mar 24 20:06:13 MDT 2018
Welcome to OpenBSD: The proactively secure Unix-like operating system.
Et voilà ! Rien de bien difficile.
Avec l’aimable autorisation de Joel Carnat !
Cette page est la traduction de la page Running OpenBSD on Raspberry Pi 3 du site TUM’FATIG. - licence de type BSD.
J’ai écrit historiquement cette traduction sur le wiki de la communauté “OpenBSD Pour Tous”.
MiniDLNA est un simple logiciel de serveur multimédia, écrit en C, dont le but est d’être totalement compatible avec différents clients DLNA et/ou UPnP-AV , tels que des téléviseurs, tablettes et autres médiums…
Installez le paquet minidlna.
Un utilisateur _minidlna
sans droit système est créé !
La configuration du fichier /etc/minidlna.conf
n’est pas complexe en
soi - si vous ne spécifiez aucune option, ce sont les valeurs par défaut
qui sont prises en charge.
Le port de connexion au service, par défaut, est le 8200
.
Veillez néanmoins à configurer les répertoires à scanner media_dir
,
en faisant attention à ces options, avec une virgule séparant l’option
et le répertoire cible :
A
pour le contenu audioP
pour les images - (P pour pictures, en anglais)V
pour les vidéosPV
pour le contenu rassemblant et les images et les vidéos.Profitez-en pour lui donner à votre service un joli petit nom, avec
l’option friendly_name
Activez l’option tivo : enable_tivo=yes
- Attention, cette
option nécessite que le service de recherche Avahi soit fonctionnel !
Une option intéressante est de limiter le nombre de connexion simultanée : max_connections
Une fois le fichier configuré, il ne vous reste plus qu’à :
minidlna
-R
minidlna
La configuration des règles du pare-feu PF est un peu plus délicate. En effet, il est nécessaire de ne pas filtrer le flux mdns, et d’ouvrir les ports adéquates :
Fichier : /etc/pf.conf
|
|
Deluge est un client BitTorrent léger, logiciel libre et multiplate-forme.
Déluge contient les fonctionnalités communes aux clients BitTorrent telles que chiffrement de protocole, DHT , découverte entre homologues locaux (LSD), échange entre homologues (PEX ), UPnP , NAT-PMP , prise en charge du proxy, ressources Web, limites de vitesse globales et par torrent.
Deluge a été conçu pour fonctionner à la fois comme une application autonome normale et en tant que client-serveur. Dans le modèle de client léger, un démon Deluge gère toute l’activité de BitTorrent et peut fonctionner sur des machines sans et avec interfaces utilisateur permettant de se connecter à distance depuis n’importe quelle autre plateforme.
Depuis la version d’OpenBSD 6.3, deluge-torrent est intégré en tant que paquet - ce qui installe toutes les dépendances nécessaires.
Installez deluge.
Néanmoins, il y a quelques étapes supplémentaires à franchir !
_deluge
, sans droit particulier,
sans shell nologin
:Code : sh
$ userinfo _deluge
login _deluge
passwd *
uid 706
groups _deluge
change NEVER
class
gecos deluge user
dir /home/_deluge
shell /sbin/nologin
expire NEVER
deluged
, tel que /etc/rc.d/deluged
:Fichier : /etc/rc.d/deluged
|
|
Ensuite, donnez-lui les droits d’exécution nécessaire : # chmod 0755 /etc/rc.d/deluged
Ce script permet à minima de démarrer le service : # rcctl start deluged
En admettant que vos règles bloquent tout ce qui doit être bloqué, et laissent passer les connexions entrantes et sortantes, relatives au flux déjà établis, quelques règles de cet acabit permettent de s’assurer d’un minima :
Fichier : /etc/pf.conf
|
|
user _deluge
est seulement pour “obliger” que ce flux lui appartiennent - tout autre flux TCP qui ne viendrait pas de lui serait bloqué ! (c’est un pis-aller…)Il ne vous reste plus qu’à exécuter le binaire deluge-web
avec un autre utilisateur…
Enjoy-ID! Enjoy-IT!
Non, je ne vais pas vous apprendre à créer un disque dur chiffré sous OpenBSD - la FAQ officielle (en anglais), ou la version traduite (en Français), vous l’apprendra mieux que moi-même !
Vous vous êtes assuré que le disque dur est connecté… électriquement, et soit en USB, en SATA, etc… Admettons que celui-ci soit reconnu par le système en tant que sd0.
L’étape 0 - de base - est d’enregistrer la passphrase dans un fichier, et de lui donner les droits nécessaires au
bon fonctionnement de bioctl
: 0600
.
Par convention, nous appellerons ce fichier /root/crypt_passwd
.
disk="sd0"
file_passwd="/root/crypt_passwd"
file_tmp="/tmp/raid.info"
Une méthode plus sûre est l’usage d’une clé USB dédié au déchiffrement. À savoir qu’il est possible d’utiliser une seule et même clé pour le chiffrement de plusieurs disques, une partition par chiffrement.
La première étape est d’obtenir le duid
- c’est l’identifiant du disk, fourni par disklabel - relatif à notre périphérique sd0
.
duid="$(disklabel ${disk0} | awk -F':' '/duid/ { gsub(/[[:space:]]*/, "", $2) ; printf "%s",$2 }')"
Que fait awk
dans les détails ?
Il recherche la ligne comportant la mention duid
, et supprime tout espace, pour enfin afficher le résultat
recherché, sans retour à la ligne !
Obtenons la lettre de partition relative à la partition RAID - en réalité, la partition chiffrée par bioctl.
Code : sh
# get partition's letter
s="$(disklabel ${disk} | awk -F':' '/RAID/ { gsub(/[[:space:]]*/, "", $1); printf "%s",$1 }' )"
slide="${duid}.$s"
Attachons le périphérique chiffré à un périphérique softraid0 :
bioctl -c C -l ${slide} -p ${file_passwd} softraid0 > ${file_tmp}
Le fichier temporaire contiendra très certainement une mention, telle que la suivante : softraid0: CRYPTO volume attached as sd2 - néanmoins cela dépend du fait d’avoir d’autres périphériques connectés, soit sur les ports SATA, USB, etc…
De toute façon, quelque soit l’écriture restituée dans le fichier temporaire, nous récupérerons l’identifiant du périphérique attaché, de manière "dynamique".
device="$(awk '/CRYPTO/ { printf "%s",$6 }' ${file_tmp})"
Dans cet exemple, la valeur obtenue sera sd2
.
Maintenant, obtenons à nouveau la lettre de partition, mais cette fois-ci du périphérique attaché, pour construire les variables nécessaires :
Code : sh
s="$(disklabel ${device} | awk -F':' '/'4.2BSD/ { gsub(/[[:space:]]*/, "", $1); printf "%s",$1 }' )"
partition="${disk}$s"
slide="${duid}.$s"
mkdir -p /mnt/${device}
mount -o noatime,nodev,noexec,nosuid,rw,softdep /dev/${partition} /mnt/${device}
Voilà, normalement nous avons accès au périphérique chiffré attaché et monté !
Il n’y a plus qu’à le remplir…
Si le montage ne se fait pas correctement, exécutons une vérification du système de fichier :
fsck -y /dev/${partition}
Si c’est OK, essayez de remonter la partition vers le répertoire choisi, avec la commande mount
ci-dessus.
Le démontage et le détachement du périphérique se fait très simplement :
umount -f /mnt/${device}
bioctl -d ${device}
Pense-bête pour supprimer le fichier temporaire qui n’est plus nécessaire :
rm -fP "${file_tmp}"
Voici le script complet, dont je me sers, pour monter et démonter automatique un périphérique chiffré avec bioctl dès le démarrage du système OpenBSD.
Il faut l’utiliser ainsi :
./mount_crypt_hd mount
- créez le fichier /etc/rc.local
et appelez le script de la manière à le monter…./mount_crypt_hd umount
- créez le fichier /etc/rc.shutdown
et appelez le script de la manière à le démonter…Fichier : mount_crypt_hd
|
|
Retrouvez ci-dessous la traduction EN → FR de l’article “Running Telegraf on OpenBSD”, écrit par Joel Carnat.
J’ai essayé d’exécuter Telegraf d’InfluxData sur la version 6.2 d’OpenBSD mais il n’était pas disponible dans les ports et n’ai pas été capable de le compiler depuis les sources. Mais cela a changé puisque j’ai pu faire fonctionner une instance dans OpenBSD 6.3. Voici comment le compiler et exécuter Telegraf sur OpenBSD.
Utilisez OpenBSD 6.3, architecture amd64. Il peut peut-être fonctionner sur d’autres architectures et versions.
Installez les outils de développement requis :
# pkg_add gmake git go
(...)
gmake-4.2.1: ok
git-2.16.2: ok
go-1.10: ok
Configurez l’environnement de compilation :
# export GOPATH=~/go
# export PATH=$PATH:~/go/bin
Démarrez la compilation de l’outil de gestion des dépendances du langage Go :
# go get github.com/golang/dep
# cd $GOPATH/src/github.com/golang/dep
# go install ./...
Ensuite, compilez Telegraf, lui-même :
# go get github.com/influxdata/telegraf
# cd $GOPATH/src/github.com/influxdata/telegraf
# gmake
dep ensure -vendor-only
go build -ldflags " -X main.commit=c7e2945a -X main.branch=master" ./cmd/telegraf
Cela compilera la branche master. On devrait être capable de compiler une branche stable en utilisant les bascules et les étiquettes de Git. Je n’ai pas pu compiler la version 1.7.4.
Quand le binaire est prêt, installez-le :
# gmake install
go build -ldflags " -X main.commit=c7e2945a -X main.branch=master" ./cmd/telegraf
mkdir -p /usr/local/bin/
cp telegraf /usr/local/bin/
J’utilise les fonctions de Classes et Utilisateurs d’OpenBSD, ainsi Telegraf ne sera pas exécuté avec les droits root :
# vim /etc/login.conf
(...)
telegraf:\
:tc=daemon:
# cap_mkdb /etc/login.conf
# groupadd -g xxxx _telegraf
# useradd -u xxxx -g xxxx -c "Telegraf agent" -d /var/telegraf -s /sbin/nologin -L telegraf _telegraf
Le fichier de configuration par défaut sera dans /etc
:
# mkdir /etc/telegraf
# chown _telegraf:_telegraf /etc/telegraf
# chmod 0750 /etc/telegraf
# doas -u _telegraf telegraf config > /etc/telegraf/telegraf.conf
Finalement, il faut créer un script rc.d
pour faciliter la gestion :
# cat > /etc/rc.d/telegraf
#!/bin/ksh
#
# Start InfluxData Telegraf agent
daemon="/usr/local/bin/telegraf"
daemon_flags="--config /etc/telegraf/telegraf.conf"
daemon_user="_telegraf"
. /etc/rc.d/rc.subr
pexp='.*telegraf'
rc_reload=NO
rc_pre() {
/usr/bin/install -d -o _telegraf -g _telegraf -m 0750 /var/telegraf
}
rc_cmd $1
#EOF
# chmod 0755 /etc/rc.d/telegraf
# chown root:wheel /etc/rc.d/telegraf
# rcctl enable telegraf
# rcctl start telegraf
Il y a un problème avec la fonction rc_check() lors de l’utilisation de
start
ou restart
. Je n’ai pas pu trouver pourquoi. Selon
`/etc/rc.d/rc.subr” : “(…) # XXX for unknown reason, rc_check can fail (…)”.
Jusque là, Telegraf exécute les filtres d’entrée d’Apache, MySQL, PHP-FPM et SNMP et le filtre de sortie d’InfluxDB. Et, il ne semble pas utiliser plus de ressources que Collectd.
Avec l’aimable autorisation de Joel Carnat !
Cette page est la traduction de la page Running Telegraf on OpenBSD du site TUM’FATIG. - licence de type BSD.
J’ai écrit historiquement cette traduction sur le wiki de la communauté “OpenBSD Pour Tous”.
Pour une raison quelconque, j’aime les petits ordinateurs portables et les contraintes qu’ils imposent (tant qu’ils sont encore utilisables). J’ai utilisé un Dell Mini 9 pendant des jours et j’utilisais jusqu’à récemment un MacBook Air 11" comme principale machine de développement, et ce pendant de nombreuses années. Récemment, Microsoft a annoncé une version plus petite et moins chère de ses tablettes Surface, appelées Surface Go, qui ont éveillé mon intérêt.
La Surface Go est disponible dans deux configurations matérielles :
Les deux sont livrées avec un processeur Intel Pentium Gold 4415Y qui n’est pas très rapide, mais reste certainement utilisable.
La tablette mesure 23,5 cm de long, ~ 17.5 cm de large, ~ 0.8 cm d’épaisseur. Elle a un écran tactile de 10" de diagonale (3:2), recouvert d’un Gorilla Glass et une résolution de 1800x1200. Le pourtour est assez large, spécialement pour un si petit écran, mais cela a du sens sur un périphérique qui est destiné à être tenu, pour éviter les appuis accidentels sur l’écran.
Le clavier et le pavé tactile sont situés sur une dalle amovible distincte, appelée Surface Signature Type Cover, vendue séparément. J’ai opté pour la couverture “bleu de cobalt” qui contient un matériau en alcantara doux, semblable à un tissu. Le couvercle se fixe magnétiquement le long du bord inférieur de l’appareil et présente des claviers et des pavés tactiles reliés par USB. Lorsque le capot est replié contre l’écran, il envoie un signal de veille ACPI et est maintenu magnétiquement sur l’écran. En utilisation normale, le couvercle peut être placé à plat sur une surface ou légèrement relevé d’environ 3/4, près de l’écran pour une meilleure ergonomie. Lorsque vous utilisez l’appareil comme une tablette, vous pouvez faire pivoter le couvercle derrière ce qui arrête automatiquement l’envoi des événements clavier et pavé tactile jusqu’à ce qu’il soit à nouveau retourné.
Le clavier a une bonne quantité de touches et une bonne disposition, avec Home / Fin / Page Up / Page Down accessible via Fn + Gauche / Droite / Haut / Bas, mais aussi les touches Home / Fin / Page Up / Page Down dédiées. Je trouve les touches F9 à F12 assez utiles puisque la disposition du clavier est un peu petite. Par défaut, les touches F1 à F12 n’envoient pas les codes de touches F1-F12, la touche Fn doit être utilisée, soit enfoncée temporairement , soit appuyée pour activer le verrouillage Fn. Les touches sont rétroéclairées avec trois niveaux de réglage, gérés par le clavier lui-même avec la touche F7.
Le pavé tactile du Type Cover est un pavé tactile Windows Precision connecté via USB HID. Il a un clic décent, mais lorsque la couverture est inclinée au lieu d’être plate sur une surface, cela sonne un peu creux et bon marché.
L’écran tactile est alimenté par une puce Elantech connectée via HID-over-i2c, qui prend également en charge la saisie au stylet. Un stylet Surface Pen est disponible séparément auprès de Microsoft et est disponible dans les mêmes couleurs que les dalles amovibles “Type Covers”. Le stylet fonctionne sans aucun appairage, bien que le bouton supérieur fonctionne en Bluetooth, il faut donc l’appairer pour l’utiliser. Dans tous les cas, le stylet nécessite une pile AAAA pour fonctionner. Le stylet peut être fixé magnétiquement sur le côté gauche de l’écran lorsqu’il n’est pas utilisé.
Une béquille peut basculer derrière l’écran pour utiliser la tablette dans un format de portable pouvant s’ajuster à n’importe quel angle jusqu’à environ 170 degrés. La béquille reste fermement en place partout où elle est positionnée, ce qui signifie également qu’elle nécessite un peu de force pour la sortir lors de la première mise en place de la Surface Go sur un bureau.
En haut de l’écran, vous trouverez un bouton d’alimentation et des boutons à bascule pour le volume du son. Sur le côté droit se trouvent la prise casque 3,5 mm, le port USB-C, le port d’alimentation et le logement pour carte microSD située derrière la béquille.
La charge peut être effectuée via le port USB-C ou le port de charge dédié, qui accueille une fixation magnétique similaire à l’adaptateur MagSafe de première génération d’Apple. Le câble de charge a une LED blanche qui brille quand il est connecté, ce qui est assez ennuyeux car il est près de la ligne médiane de l’écran plutôt que vers le bas du clavier. Contrairement au MagSafe d’Apple, le voyant n’indique pas si la batterie est chargée ou non. La prise du chargeur électrique peut être placée vers le haut ou le bas, mais dans les deux sens, je trouve que le câble d’alimentation qui en sort est soumis à une contrainte gênante en raison de la position verticale du port.
La connectivité sans fil est assurée par une puce Qualcomm Atheros QCA6174 802.11ac qui fournit également une connectivité Bluetooth.
La plupart des capteurs de l’appareil, tels que le gyroscope et le capteur de lumière ambiante, sont connectés derrière un périphérique PCI Intel Sensor Hub, ce qui permet de réaliser des économies d’énergie car le processeur hôte n’a pas à interroger les capteurs en permanence.
Pour accéder au menu BIOS ou micrologiciel de la Surface Go, maintenez le bouton Volume Haut enfoncé, puis appuyez sur le bouton Marche / Arrêt et relâchez-le, puis relâchez la touche Volume Up lorsque le menu apparaît. Secure Boot ainsi que divers composants matériels peuvent être désactivés dans ce menu. L’ordre de démarrage peut également être ajusté. Un menu de démarrage temporaire peut être affiché de la même manière, mais en utilisant plutôt Volume Down.
L’installation était très facile, le clavier “Type Cover” fonctionnant immédiatement, la plupart du matériel étant des composants PC standard.
Pour démarrer l’installateur d’OpenBSD, utilisez dd
pour installer
l’image install64.fs
sur un disque USB ; entrez dans le BIOS comme
indiqué ci-dessus et désactivez “Secure Boot”, puis définissez le
périphérique USB comme priorité de démarrage.
Lorsque vous partitionnez le SSD de 128 Go, vous pouvez supprimer en toute sécurité la partition Windows Recovery qui occupe 1 Go, car elle ne peut pas réparer une partition Windows totalement supprimée et une image de récupération complète peut être téléchargée du site Web Microsoft et copiée sur un disque USB.
Après avoir installé OpenBSD mais avant de redémarrer, montez la
partition EFI ( sd0i
) et supprimez le répertoire /EFI/Microsoft
.
Sans cela, la tablette peut essayer de démarrer le chargeur de
récupération Windows. Le chargeur de démarrage EFI d’OpenBSD
/EFI/Boot/BOOTX64.EFI
sera chargé par défaut.
Un inconvénient à noter : si vous appuyez sur le pavé tactile ou si vous appuyez sur les touches F1 à F6 lors de l’installation, le “Type Cover” détachera tous ses périphériques USB, puis les ré-activera. Cela est dû au fait que le ramdisk ne contient aucun pilote de pavé tactile ou autre périphérique prenant en charge les contrôles de consommation USB HID pour les touches F1-F6. Par conséquent, les canaux USB de ces périphériques ne sont pas fonctionnels. Il est probable que le “Type Cover” se redémarre dans cette situation en tant que sécurité intégrée pour le forcer à se rattacher, plutôt que de demander à l’utilisateur de détacher le capot et de le rattacher.
Cela ne se produira pas pour le pavé tactile une fois que le noyau
normal sera démarré car il contient le pilote umt
. Lisez mes remarques
ci-dessous pour utiliser usbhidcontrol
afin de répondre aux touches
F1-F6 qui maintiendront le bon canal USB ouvert afin d’empêcher le
détachement ou la réinstallation lors de l’utilisation de ces touches.
23-08-2018 : J’ai reçu la Surface Go et j’ai démarré un disque USB
OpenBSD après avoir désactivé Secure Boot. J’ai pu installer OpenBSD à
la place de la partition Windows, en conservant la partition de
récupération Windows. Après le redémarrage, la Surface a continué
d’essayer de démarrer Windows Recovery, qui échouait encore et encore.
J’ai démarré sur une installation USB Windows et j’ai pu utiliser
EasyUEFI pour ajouter une nouvelle option
de démarrage UEFI et démarrer explicitement le BOOTX64.EFI
d’OpenBSD.
OpenBSD démarre maintenant par défaut.
J’ai remarqué que l’écran avait un pixel mort dans le coin inférieur gauche, alors j’ai décidé de l’apporter au Microsoft Store proche pour un échange. Mais avant, je devais réinstaller Windows, ce qui a pris plusieurs heures, car la partition de récupération Windows ne peut actuellement rien récupérer si la partition Windows a été effacée. J’ai téléchargé une image de récupération de la Surface à partir du site Web de Microsoft et créer un disque USB pour réinstaller Windows. Finalement, je me suis rendu au Microsoft Store et ils m’ont rapidement donné une nouvelle en échange.
Lors de l’installation d’OpenBSD sur le nouveau périphérique, j’ai
décidé d’effacer la partition de récupération de Windows car elle est de
toute façon inutile et me permettrait d’économiser un gigaoctet d’espace
supplémentaire. Avant de redémarrer, j’ai compris que les variables de
démarrage UEFI pointaient d’abord vers les fichiers EFI de récupération
de Windows dans \EFI\Microsoft
. J’ai donc supprimé tout ce répertoire
en laissant \EFI\Boot\BOOTX64.EFI
qui est le chargeur de démarrage
d’OpenBSD. Cela a fonctionné comme prévu et OpenBSD démarre maintenant
par défaut.
24-08-2018 : Le pavé tactile du Type Cover se connecte à ums
mais
c’est un pavé tactile Windows Precision qui devrait donc fonctionner
comme mon pilote imt
, mais via USB. ums
ne prend en charge qu’un
seul doigt de saisie et le matériel a la fonction “tap-to-click” activée
par défaut, il ne peut pas être désactivé. J’ai écrit un nouveau pilote
umt
pour le brancher sur USB à la place de hidmt
, ensuite j’ai perdu
beaucoup de temps pour déboguer les raisons pour lesquelles le
périphérique ne fonctionnait pas correctement dans le mode PTP. Je l’ai
traqué jusqu’à trouver une certaine confusion entre ihidev
et hidmt
qui devait être corrigés en premier, j’ai donc envoyé un diff à tech@
.
25-08-2018 : J’ai envoyé
les modifications des pilotes ihidev
et hidmt
et un
diff pour importer umt
à tech@
pour analyse. Il a été rapidement
importé .
28-08-2018 : Ces deux derniers jours, j’ai passé du temps à chercher
ce qui était nécessaire pour que l’écran tactile Elan fonctionne. Il
s’attache à ihidev
en tant que périphérique HID-over-i2c, mais il ne
s’attache pas à imt
. Finalement, j’ai découvert que ce n’est pas un
périphérique compatible PTP, mais conforme à l’ancien multitouch de type
Windows 8. J’ai commencé à ajouter
un support pour ces périphériques de type Windows 8 à hidmt
et déplacé
du code dupliqué dans umt
et imt
dans hidmt
.
J’ai aussi examiné les boutons de volume en haut de l’écran.
Malheureusement, ils ne fonctionnent pas avec notre pilote
acpisurface
existant, alors
j’ai démarré un disque USB Linux et ai tracé leur fonctionnement.
Apparemment, c’est un périphérique “Intel 5-button Array” qui fonctionne
via ACPI. J’ai écrit un nouveau pilote
acpihid
pour cela et les boutons de volume contrôlent maintenant le volume audio.
Il y a certaines surcharges dans acpihid
, dans la gestion du bouton
d’alimentation et de la méthode d’interruption ACPI GPE standard, afin
de recevoir la pression sur le bouton d’alimentation. J’ai donc dû prendre
en compte que acpibtn
capture acpihid
s’il est attaché. Ce serait
bien s’il y avait une variable sysctl
comme machdep.lidaction
qui
spécifiait si le bouton d’alimentation était en mode arrêt, suspendu ou
ne faisait rien.
29-08-2018 : Je voulais faire fonctionner les fonctions F1
à F6 du clavier (luminosité, lecture / pause, sourdine,
diminution / augmentation du volume) sur le Type Cover. Actuellement,
chaque fois qu’ils sont pressés, le Type Cover redémarre, car le
rétro-éclairage s’éteint et tous ses périphériques USB se détachent puis
se reconnectent. En traçant comment cela fonctionne sous Linux, j’ai vu
qu’il s’agissait essentiellement d’utiliser leur pilote générique
hid-input
, donc il ne devrait pas avoir besoin de le personnaliser.
J’ai commencé à travailler sur un pilote générique d’entrée USB HID
(contrairement à ukbd
/ hidkbd
qui nécessite des utilisations
spécifiques au clavier), mais j’ai eu des soucis sur
usbhidaction
que nous avons
déjà en base et qui devrait bien fonctionner pour cette tâche.
Malheureusement, usbhidaction
requiert de connaître le chemin
spécifique uhid du périphérique HID qui doit être contrôlé et le quitter
dès que le périphérique disparaît. Pour la dalle Type Cover de la Surface,
ce périphérique peut changer en fonction de ce qui a été branché au
démarrage, et se détachera à chaque fois que la machine sera arrêtée
alors usbhidaction
s’arrêtera simplement.
Après avoir passé beaucoup de temps à modifier usbhidaction
pour
interroger le périphérique /dev/usbN
afin d’attendre les ajouts et les
suppressions de périphérique, j’ai réalisé que la page de manuel était
obsolète et que tous ces événements étaient sortis du noyau il y a
plusieurs années. J’ai
enlevé
cette ligne dans la page de manuel.
30-08-2018 : Afin d’être capable d’utiliser usbhidaction
pour
qu’il trouve automatiquement un périphérique USB en fonction de son
fournisseur et de son identifiant, et être capable d’attendre que le
périphérique s’affiche automatiquement, je l’ai connecté à
/dev/hotplug
. Malheureusement,
hotplug ne prend en charge qu’un seul lecteur simultané. J’ai donc
implémenté le clonage de périphérique
dans le pilote hotplug
afin que plusieurs processus puissent lire à
partir de /dev/hotplug
et que chacun reçoive sa propre file d’événements.
Je l’ai envoyé par courrier électronique à la liste des développeurs
OpenBSD et j’ai reçu quelques premiers commentaires à ce sujet.
J’ai fait beaucoup de progrès sur les changements d’ usbhidaction
, et
je les ai envoyés
dans mon arborescence.
J’ai également envoyé
un changement en amont pour créer 8 périphériques /dev/uhidN
,
puisqu’il n’y en avait que 4 auparavant.
31-08-2018 : J’ai décidé d’abandonner mon support multitouch Windows
8 pour le moment, car l’écran tactile devrait être utilisable avec le
support de base par ims
(agissant comme une souris à un bouton).
Utiliser imt
signifiait de réclamer tous les rapports HID (25 !) sur
le périphérique, ce qui brisait la prise en charge de l’utilisation d’un
stylet et mon stylet Surface est arrivé, je voulais l’utiliser. De cette
façon, ims
peut juste l’attacher au rapport de l’écran tactile et un
autre ims
peut l’attacher au rapport de saisie du stylet.
En faisant des ims
correspondant aux rapports de l’écran tactile, je
suis tombé sur ce qui ressemble à un bogue dans notre analyseur HID (ou,
il n’est tout simplement pas pris en charge) où il correspondait à
l’utilisation de pages qu’il ne devrait pas. Le résultat de ceci était
que, quand hidms
cherchait la page d’utilisation indiquant le minimum
logique et le maximum X / Y de l’écran (afin de pouvoir mapper les
coordonnées d’entrée de l’écran tactile sur l’affichage de l’écran), il
y avait des utilisations pour d’autres choses sans rapport, cela faisait
penser au pilote que l’écran était beaucoup plus grand qu’il ne l’était.
Lorsque je touchais l’écran et que je le parcourais complètement, cela
ne faisait déplacer le curseur que d’un quart environ.
J’ai envoyé un diff
à tech@
pour contourner cet ims et attacher des ims
aux écrans tactiles.
01-09-2018 : Les diff d’hidms
et d’ims
ont été acceptés. OpenBSD 6.4 prendra en charge l’écran tactile, le
stylet, le clavier et le pavé tactile multitouch.
Je suis toujours en attente de retours sur mon changement de hotplug
,
ce qui me permettra ensuite de développer plus profondément mes
modifications sur usbhidaction
.
J’ai aussi besoin de commencer à travailler sur un pilote pour le périphérique PCI Intel Sensor Hub qui me permettrait ensuite de prendre en charge le capteur de lumière ambiante et le gyroscope pour la détection de la rotation. Cependant, en regardant le pilote Linux, il semble qu’il y ait une tonne de code et bien sûr, il n’y a pas de documentation ouverte pour que je puisse trouver.
Le statut est relatif à OpenBSD-current en date du 03-09- 2018.
Composant | Fonctionnel | Remarques |
---|---|---|
Adaptateur électrique AC | Oui | Pris en charge via acpiac et le statut est disponible via apm et hw.sensors , qui supporte également la charge via USB-C. |
Détecteur de lumière ambiante | Non | Connecté derrière un périphérique PCI Intel Sensor Hub qui nécessite un nouveau pilote. |
Audio | Oui | Audio HDA avec un codec Realtek 298 pris en charge par azalia . |
État de la batterie | Oui | Pris en charge via acpibat et le status est disponible via apm et hw.sensors . |
Bluetooth | Non | Le périphérique Atheros apparaît comme un périphérique ugen , mais OpenBSD ne prend pas en charge le Bluetooth. Peut être désactivé dans le BIOS. |
Les caméras | Non | Il existe apparemment des caméras avant, arrière et infrarouge, dont aucune n’est prise en charge (ni souhaité). Peut être désactivées dans le BIOS. |
Le Gyroscope | Non | Connecté derrière le périphérique PCI Intel Sensor Hub qui requiert un nouveau pilote qui pourrait alimenter le [[https://man.openbsd.org/man9/sensor_attach.9 |
Hibernation | Oui | Fonctionne bien avec zzz |
Slot MicroSD | Oui | Un Realtek RTS522A, supporté par rtsx . |
Le SSD | Oui | Le périphérique Toshiba NVMe accessible via nvme . |
Le stylet | Oui | Fonctionne sur l’écran tactile via ims . Le bouton situé en haut du stylet nécessite la prise en charge du Bluetooth qui n’est pas pris en charge. Du fait que dwiic nécessite toujours l’interrogation de ces chipsets, dessiner avec le stylet n’est pas aussi fluide qu’avec des interruptions correctes. |
Mise en veille / Réveil | Oui | Fonctionne bien à partir de zzz et en fermant le Type Cover contre l’écran. Il ne se réveille pas automatiquement lorsque vous retirez le Type Cover, il faut appuyer sur le bouton d’alimentation pour le réveiller. |
L’Écran tactile | Oui | HID-over-I2C, supporté par ims . |
Le clavier Type Cover | Oui | USB, supporté par ukbd . 3 niveaux de contrôle du rétroéclairage sont réglables par le clavier lui-même avec F7. Les actions des touches F1 à F6 apparaissent dans le rapport 3 et peuvent être répondues avec usbhidaction -u 045e:096f -r 3 . |
Le pavé tactile Type Cover | Oui | USB, pris en charge par mon nouveau pilote umt pour le multitouch à 5 doigts, le défilement à deux doigts, l’hystérésis et être capable de désactiver le tap-to-click qui est activé par défaut en mode souris normal. |
USB | Oui | Le port USB-C fonctionne bien pour les données et la charge. |
La Vidéo | Oui | inteldrm a pris en charge Kaby Lake en ajoutant la vidéo accélérée, le DPMS, le contrôle gamma, le contrôle de rétroéclairage intégré et la reprise S3 appropriée. |
Les boutons de volume | Oui | Intel à 5 boutons, pris en charge par mon nouveau pilote acpihid non encore importé en amont. |
Wifi | Non | Puce sans fil Qualcomm Atheros QCA6174 802.11ac, non prise en charge. FreeBSD a un port en cours de travail d’ath10k partir de Linux (sous licence ISC) qui peut être porté. J’utilise actuellement un petit adaptateur sans fil USB-A qui est rendu moins volumineux par un adaptateur USB-A vers USB-C. |
Avec l’aimable autorisation de Joshua Stein !
Cette page est la traduction de la page [OpenBSD on Microsoft Surface Go]]]1 du site BSDHowto.ch.
J’ai écrit historiquement cette traduction sur le wiki de la communauté “OpenBSD Pour Tous”.
Retrouvez ci-dessous la traduction EN → FR de l’article “More Falsehoods programmers believe about time”, écrit par l’auteur Noah Sussman, sous Licence CC-By.
(…)
Toutes ces hypothèses sont fausses :
Sérieusement ? Des trous noirs ?
Hé, si Bruce Sterling dit que mon logiciel a besoin d’être résilient contre les distorsions du temps causé par les trous noirs, je vais être attentif à ce propos.
Le reste n’est volontairement pas traduit du fait de remerciements de l’auteur envers plusieurs personnes…
J’ai écrit historiquement cette traduction sur le wiki de la communauté “OpenBSD Pour Tous”.
Retrouvez ci-dessous la traduction EN → FR de l’article “Falsehoods programmers believe about time”, écrit par l’auteur Noah Sussman, sous Licence CC-By.
(…)
Toutes ces hypothèses sont fausses :
La réflexion à-propos du fait que la minute puisse être plus longue qu’une heure est une blague, n’est-ce pas ?
Non.
C’est un fascinant bogue dans de vieilles version de KVM sur CentOS. Spécifiquement, une machine virtuelle KVM ne savait pas qu’elle ne fonctionnait pas sur du matériel physique. Cela signifiait que le système hôte mettait la VM dans un état de veille, l’horloge système virtualisée conservait le temps qu’elle avait au moment de sa suspension.
P. ex. si la VM était suspendue à 13:00 et qu’elle était remise à un état d’activité deux heures plus tard (à 15:00), l’horloge système sur la VM reflétait toujours l’heure locale à 13:00. Le résultat était que chaque fois qu’une machine virtuelle KVM devenait inactive, l’OS hôte la mettait dans un état suspendu et l’horloge système de la machine virtuelle commençait à s’éloigner de la réalité, parfois d’une large marge en fonction de la durée pendant laquelle la machine virtuelle était restée inactive.
Il y avait une tâche cron qui pouvait être installée pour garder l’horloge système virtualisée en ligne avec l’horloge matérielle de l’OS hôte. Mais il était facile d’oublier de le faire sur de nouvelles VMs et l’échec à le faire a conduit à beaucoup d’hilarité. Le bogue a été corrigé dans les versions plus récentes.
Le reste n’est volontairement pas traduit du fait de remerciements de l’auteur envers plusieurs personnes…
J’ai écrit historiquement cette traduction sur le wiki de la communauté “OpenBSD Pour Tous”.
Retrouvez ci-dessous la traduction EN → FR de l’article “Monitoring OpenBSD using CollectD, InfluxDB and Grafana”, écrit par Joel Carnat.
Regardons comment monitorer OpenBSD en utilisant le collecteur CollectD et le tableau de bord de rendu Grafana. OpenBSD 6.2-current fournit les packages InfluxDB et Grafana. Une superbe pile pour obtenir de jolis graphiques.
Les métriques du système sont stockés dans InfluxDB ; parce qu’il peut être utilisé comme ressource pour Grafana. L’installation et la configuration sont simples. L’essentiel est d’activer le protocole de collecte collectd.
# pkg_add influxdb
# vi /etc/influxdb/influxdb.conf
(...)
[[collectd]]
enabled = true
bind-address = ":25826"
database = "collectd"
retention-policy = ""
typesdb = "/usr/local/share/collectd"
# rcctl enable influxdb
# rcctl start influxdb
Notez que ce service fonctionne seulement sur UDP. Il semble ne pas y avoir d’options disponibles pour TCP ni TLS.
# netstat -na | grep 25826
udp 0 0 *.25826 *.*
Utilisons CollectD en tant que collecteur des métriques. Surtout parce qu’il connaît OpenBSD et qu’il est capable d’envoyer ses données à distance. Dans ce cas, à InfluxDB. Activez tous les plugins requis.
N’oubliez pas celui relatif au réseau afin que les données soient envoyées à InfluxDB.
# pkg_add collectd
# vi /etc/collectd.conf
(...)
<Plugin network>
<Server "127.0.0.1" "25826">
</Server>
ReportStats true
</Plugin>
# rcctl enable collectd
# rcctl start collectd
Ce qui est nouveau dans la version current d’OpenBSD 6.2 : Grafana est disponible en tant que package. Cela permettra de faire de jolis graphiques en utilisant OpenBSD.
# pkg_add grafana
# vi /etc/grafana/config.ini
# rcctl enable grafana
# rcctl start grafana
Ouvrez votre navigateur web à l’adresse http://localhost:3000/
et
connectez vous en utilisant les informations d’identification par défaut
(admin:admin
). Ceux-ci peuvent être modifiés de cette
manière
et depuis l’interface graphique.
Dans Grafana, ajoutez la source InfluxDB en tant que base de données.
Des exemples de tableaux de bord sont disponibles sur le site Web de Grafana, tels que le #554, #[555 et #755. Ils seront presque prêts à l’emploi et peuvent servir de base pour créer les vôtres. Ils semblent être centrés sur Linux mais voici à quoi ils ressemblent, une fois légèrement modifiés pour OpenBSD, disponible sur Grafana.
“That’s All Folks!”
Avec l’aimable autorisation de Joel Carnat !
Cette page est la traduction de la page Monitoring OpenBSD using CollectD, InfluxDB and Grafana du site TUM’FATIG. - licence de type BSD.
J’ai écrit historiquement cette traduction sur le wiki de la communauté “OpenBSD Pour Tous”.
Coupler des requêtes DNSSEC en utilisant “DNS-over-TLS” sous OpenBSD est non seulement possible, mais envisageable, et fonctionnel… plus ou moins nativement !
Pour les requêtes DNSSEC, nous avons nativement sous OpenBSD – un outil fort puissant et utile, à savoir : ‘‘unbound’’.
Unbound est capable de discuter sur la pile DualStack IPv4, IPv6 ; il nous permet aussi de créer/d’avoir en local un resolveur cache qui nous fait des requêtes auprès des DNS publiques, si besoin…
Il y a quelques mois, j’écrivais cet article sur comment Utiliser Unbound avec DNSSEC sur OpenBSD. Vous l’avez lu ? Très bien, sinon faites-le…
Quant à la question des requêtes DNS sur TLS, hier, nous avons vu l’usage de Stubby : Client DNS/TLS sous OpenBSD (EXPÉRIMENTAL) , lui aussi capable de discuter sur la DualStack (IPv4, IPv6) – c’est là qu’est la partie “EXPÉRIMENTAL”, car non natif, ni en tant que package, ni dans les ports : du moins, pour l’instant… mais c’est vraiment fonctionnel !
Alors comment faire pour utiliser sur notre machine ces deux logiciels de manière à avoir un resolveur cache local communiquant sur DNSSEC et avoir des requêtes DNS sur TLS, dans le même laps de temps ?
Il semble que nous soyons obligés de coupler :
La première chose à s’assurer est d’avoir paramétré correctement votre fichier
/etc/resolv.conf
pour n’interroger qu’en local !
nameserver 127.0.0.1
nameserver ::1
Ensuite, il faut modifier légèrement votre fichier /var/unbound/etc/unbound.conf
,
pour veiller à ajouter quelques paramètres ; il y a :
do-not-query-localhost
# $OpenBSD: unbound.conf,v 1.7 2016/03/30 01:41:25 sthen Exp $
server:
(...)
do-not-query-localhost: no
(...)
forward-zone:
name: "." # use for ALL queries
forward-addr: ::1@853
forward-addr: 127.0.0.1@853
Toute requête DNS qui n’est pas en cache dans la mémoire d’unbound sera transmise à stubby qui fera le nécessaire… unbound prendra absolument le relais pour toute requête DNS identique.
Il nous faut modifier le fichier de configuration de stubby /usr/local/etc/stubby/stubby.yml
,
en rapport avec le port spécifié sur les adresses que le service de
stubby va devoir écouter :
(...)
listen_addresses:
- 127.0.0.1@853
- 0::1@853
(...)
Si dans le fichier de configuration d’unbound, vous utilisez un autre numéro que celui-ci, veillez impérativement renseigner le même !
Pour information, il est envisageable de demander à stubby d’exécuter
ses requêtes sur le protocole DNSSEC ; pour cela, il faut décommenter
l’option dnssec_return_status: GETDNS_EXTENSION_TRUE
!
Cela augmente assurément le temps de charge des requêtes. Laissez donc à unbound le soin de les faire !
Dans la partie # Additional server
du fichier de configuration de stubby,
vous avez la possibilité de décommenter un ou plusieurs serveurs à interroger,
autant sur IPv4 qu’IPv6, dont le fameux Quad9 @9999….
Si (re)démarrer LE service relatif à unbound n’est pas bien difficile, à
coup de : # rcctl restart unbound
, (re)démarrer celui de stubby n’est
pas possible car rien n’existe par défaut pour que cela puisse être.
Avant de chercher à redémarrer les services, pensez d’abord à vérifier vos fichiers de configuration - pour rappel :
$ unbound-checkconf
$ stubby -i
Pour que stubby puisse interagir en tant que service sur votre système
OpenBSD, il faut lui créer un fichier rc, à positionner dans /etc/rc.d/stubby
avec pour contenu ceci, ni + ni - :
#!/bin/sh
#
# $OpenBSD: stubby,v 0.2.2 2018/03/22 12:00:00 Stephane HUC $
daemon="/usr/local/bin/stubby"
daemon_flags=""
. /etc/rc.d/rc.subr
#rc_reload=NO
rc_cmd $1
Attribuez-lui des droits suivants : # chmod 555 /etc/rc.d/stubby
Voilà, maintenant vous allez pouvoir jouer du contrôleur rc :
# rcctl enable stubby
# rcctl set stubby flags "-g"
# rcctl start stubby
Très basiquement avec l’outil dig
, tel que :
$ dig @::1 A www.gandi.net
; <<>> DiG 9.4.2-P2 <<>> @::1 www.gandi.net
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12892
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.gandi.net. IN A
;; ANSWER SECTION:
www.gandi.net. 46710 IN CNAME prod.gandi.map.fastly.net.
prod.gandi.map.fastly.net. 3600 IN A 151.101.37.103
;; Query time: 644 msec
;; SERVER: ::1#53(::1)
;; WHEN: Fri Mar 23 01:17:20 2018
;; MSG SIZE rcvd: 83
On la réitère pour se rendre compte de la différence en terme de temps d’accès :
$ dig @::1 www.gandi.net
; <<>> DiG 9.4.2-P2 <<>> @::1 www.gandi.net
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2032
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.gandi.net. IN A
;; ANSWER SECTION:
www.gandi.net. 46706 IN CNAME prod.gandi.map.fastly.net.
prod.gandi.map.fastly.net. 3596 IN A 151.101.37.103
;; Query time: 1 msec
;; SERVER: ::1#53(::1)
;; WHEN: Fri Mar 23 01:17:24 2018
;; MSG SIZE rcvd: 83
644 millisecondes la première interrogation ; 1 milliseconde, la seconde… unbound fait son travail de cache assurément !
Stubby est une application qui agit en tant que client DNS, sur protocole sécurisé (en utilisant DoT ). Ce logiciel chiffre les requêtes DNS envoyées d’une machine cliente vers un résolveur DNS, ou un serveur DNS faisant autorité afin d’augmenter la confidentialité des communications de l’utilisateur, par le chiffrement des requêtes DNS. De même, il peut faire des requêtes DNS selon le protocole DNSSEC.
Attention : il ne fait pas office de résolveur cache DNS, ni de serveur faisant autorité ; ce n’est qu’un client DNS !
De plus, il n’existe ni package, ni port de Stubby sous OpenBSD stable… et encore moins de port officiel du projet stubbly vers OpenBSD, d’où le titre “EXPÉRIMENTAL”. Nous allons devoir récupérer les sources, les compiler, installer, configurer, etc…
L’installation du client stubby se fait/fera sous OpenBSD stable.
OpenSSL
: installé par défautLibyaml
: à installer…autoconf
, automake
: à installer pour les phases de configuration,
compilation avant installation# pkg_add autoconf automake libyaml
quirks-2.414 signed on 2018-03-28T14:24:37Z
Ambiguous: choose package for autoconf
a 0: <None>
1: autoconf-2.13p4
2: autoconf-2.52p6
3: autoconf-2.54p5
4: autoconf-2.56p4
5: autoconf-2.57p4
6: autoconf-2.58p5
7: autoconf-2.59p5
8: autoconf-2.60p5
9: autoconf-2.61p5
10: autoconf-2.62p2
11: autoconf-2.63p1
12: autoconf-2.64p1
13: autoconf-2.65p1
14: autoconf-2.67p1
15: autoconf-2.68p1
16: autoconf-2.69p2
Your choice: 16
Ambiguous: choose package for automake
a 0: <None>
1: automake-1.10.3p8
2: automake-1.11.6p2
3: automake-1.12.6p1
4: automake-1.13.4p1
5: automake-1.14.1p0
6: automake-1.15.1
7: automake-1.4.6p5
8: automake-1.8.5p9
9: automake-1.9.6p12
Your choice: 6
Puis on va suivre les recommandations officielles d’installation depuis les sources
$ git clone https://github.com/getdnsapi/getdns.git
$ cd getdns
$ git checkout develop
La deuxième commande git nous permet d’obtenir les sources les plus récentes…
$ git submodule update --init
$ libtoolize -ci
$ export AUTOCONF_VERSION=2.69
$ export AUTOMAKE_VERSION=1.15
$ autoreconf -fi
$ mkdir build && cd build
$ ../configure --prefix=/usr/local --without-libidn --enable-stub-only --with-stubby
$ make
# make install
Bien-sûr, à la place de la dernière commande, si vous avez configuré
doas
, vous pouvez ainsi l’exécuter :
$ doas make install
Il est nécessaire de modifier votre fichier /etc/resolv.conf
afin de
communiquer directement avec stubby :
nameserver 127.0.0.1
nameserver ::1
Le fichier de configuration de stubby se trouve être dans
/usr/local/etc/stubby/stubby.yml
. Si vous en créez un au format yaml
dans votre répertoire personnel, tel que ~/.stubby.yml
, il sera lu en
premier.
Pour exécuter stubby, il suffit de :
# stubby
[12:57:39.896254] STUBBY: Read config from file /usr/local/etc/stubby/stubby.yml
[12:57:39.898479] STUBBY: DNSSEC Validation is OFF
[12:57:39.898585] STUBBY: Transport list is:
[12:57:39.898617] STUBBY: - TLS
[12:57:39.898681] STUBBY: Privacy Usage Profile is Strict (Authentication required)
[12:57:39.898713] STUBBY: (NOTE a Strict Profile only applies when TLS is the ONLY transport!!)
[12:57:39.898749] STUBBY: Starting DAEMON....
Quelques informations intéressantes :
-C
permet de spécifier un autre fichier de configuration,
à la place de l’original.-g
permet de fonctionner en arrière plan…-i
permet de vérifier la configuration !-l
a pour objectif de journaliser les connexions.
Pour l’instant, la sortie se fait sur la sortie standard stdout
!L’usage très simple de dig
nous permettra de nous assurer du bon
fonctionnement :
⇒ Version IPv4
$ dig @127.0.0.1 www.gandi.net
; <<>> DiG 9.4.2-P2 <<>> @127.0.0.1 www.gandi.net
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40041
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 4, ADDITIONAL: 0
;; QUESTION SECTION:
;www.gandi.net. IN A
;; ANSWER SECTION:
www.gandi.net. 21583 IN CNAME prod.gandi.map.fastly.net.
prod.gandi.map.fastly.net. 3600 IN A 151.101.37.103
;; AUTHORITY SECTION:
fastly.net. 3600 IN NS ns1.fastly.net.
fastly.net. 3600 IN NS ns2.fastly.net.
fastly.net. 3600 IN NS ns3.fastly.net.
fastly.net. 3600 IN NS ns4.fastly.net.
;; Query time: 1888 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Mar 22 14:15:51 2018
;; MSG SIZE rcvd: 155
⇒ Version IPv6 :
$ dig @::1 www.gandi.net
; <<>> DiG 9.4.2-P2 <<>> @::1 www.gandi.net
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24688
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 4, ADDITIONAL: 4
;; QUESTION SECTION:
;www.gandi.net. IN A
;; ANSWER SECTION:
www.gandi.net. 84574 IN CNAME prod.gandi.map.fastly.net.
prod.gandi.map.fastly.net. 3600 IN A 151.101.85.103
;; AUTHORITY SECTION:
fastly.net. 168207 IN NS ns4.fastly.net.
fastly.net. 168207 IN NS ns2.fastly.net.
fastly.net. 168207 IN NS ns1.fastly.net.
fastly.net. 168207 IN NS ns3.fastly.net.
;; ADDITIONAL SECTION:
ns1.fastly.net. 3600 IN A 23.235.32.32
ns2.fastly.net. 3600 IN A 104.156.80.32
ns3.fastly.net. 3600 IN A 23.235.36.32
ns4.fastly.net. 3600 IN A 104.156.84.32
;; Query time: 1614 msec
;; SERVER: ::1#53(::1)
;; WHEN: Thu Mar 22 14:16:40 2018
;; MSG SIZE rcvd: 219
Du fait de gérer moi-même la zone DNS pour mon propre ndd, dans le but “d’implémenter” DNSSEC.
Je commence maintenant à m’intéresser aux enregistrements DANE. Pour l’instant, je ne génère qu’un enregistrement pour le port 443/tcp - service web. Mais il est possible d’en générer pour d’autres services, tel que 25/tcp qui correspond à smtp, d’autres protocoles que tcp, etc…
Créer un enregistrement TLSA n’est pas compliqué !
Pour le propos, un enregistrement TLSA est ainsi construit :
_numeroDePort._protocol.domain. IN TLSA usage selecteur correspondance certificatAssocie
Veuillez consulter la documentation de l’Afnic, ci-dessous, pour bien comprendre le propos.
Pour générer un enregistrement TLSA en shell, c’est assez simple en somme :
openssl x509 -noout -pubkey -in /etc/ssl/acme/nomDeDomaine.cert.pem | openssl rsa -pubin -outform der 2>/dev/null | sha512 | tr "a-z" "A-Z"
Dans un premier temps :
algo="sha512"
domain="stephane-huc.net"
cert="/etc/ssl/acme/${domain}.cert.pem" # chemin vers le fichier cert SSL généré par LetsEncrypt, avec le client natif OpenBSD - acme secure !
tls_port=443
tls_proto="tcp"
tlsa_usage=3 # Usage Field; possible: 0 => 3
tlsa_selector=0 # Selector Field; 0: use cert; 1: use public key
tlsa_method=0 # Matching Type Field
case "${algo}" in
"sha256") tlsa_method=1 ;;
"sha512") tlsa_method=2 ;;
esac
#tlsa_cert_associated="$(openssl x509 -in "${cert}" -outform der | openssl $algo | cut -d ' ' -f2)"
tlsa_cert_associated="$(openssl x509 -noout -pubkey -in "${cert}" | openssl rsa -pubin -outform der 2>/dev/null | ${algo} | tr "a-z" "A-Z" )"
tlsa_record="_${tls_port}._${tls_proto}.${domain}. IN TLSA ${tlsa_usage} ${tlsa_selector} ${tlsa_method} ${tlsa_cert_associated}"
# ajout de l'enregistrement vers votre zone dns ; dans ce cas, l'enregistrement de cette dernière est dû au fait de l'outil ldnscript de @"22decembre" !
echo "${tlsa_record}" >> /etc/ns/${domain}
Voici le même code shell, pour gérer plusieurs domaines, pour exemple :
#!/bin/sh
algo=sha256
#cert="/etc/ssl/acme/${domain}.cert.pem"
domains="yeuxdelibad.net 3hg.fr ouaf.xyz"
tls_proto="tcp"
tls_ports="443"
tlsa_usage=3 # Usage Field; possible: 0 => 3
tlsa_selector=1 # Selector Field; 0: use cert; 1: use public key
tlsa_method=0 # Matching Type Field
case "${algo}" in
"sha256") tlsa_method=1 ;;
"sha512") tlsa_method=2 ;;
esac
for domain in ${domains}; do
cert="etc/ssl/acme/${domain}.cert.pem"
tlsa_cert_associated="$(openssl x509 -noout -pubkey -in "${cert}" | openssl rsa -pubin -outform der 2>/dev/null | ${algo} | tr "a-z" "A-Z" )"
for port in ${tls_ports}; do
tlsa_record="_${port}._${tls_proto}.${domain}. IN TLSA ${tlsa_usage} ${tlsa_selector} ${tlsa_method} ${tlsa_cert_associated}"
echo "${tlsa_record}" >> "/etc/ns/${domain}"
done
echo "You should update your ${domain} zone in 48h" | mail -s "${domain} TLSA update" root
sleep 1
# reload zone and nsd ; à décommenter, si vous utiliser nsd ;)
#/var/ldns/ldnscript signing "${domain}"
done
Merci Xavier ;)
Générer un enregistrement TLSA en PHP n’est guère plus compliqué, à partir du moment où on a les bonnes infos !
On veille à récupérer le certificat au format PEM, à l’injecter dans un formulaire HTML et à traiter les informations reçues par celui-ci. Je ne décris pas le code HTML.
<?php
function extractPublicKey($cert) {
$certificate = openssl_x509_read($cert);
$pub_key = openssl_get_publickey($certificate);
$pub_key = openssl_pkey_get_details($pub_key);
if (!isset($pub_key['key'])) {
// @codeCoverageIgnoreStart
throw new \InvalidArgumentException('Provided certificate is invalid.');
// @codeCoverageIgnoreEnd
}
return $pub_key['key'];
}
function pem2der($pem) {
return base64_decode(str_replace(["\n", "\r"], '', $pem));
}
function stripDatas($pem) {
$datas = [
'-----BEGIN PUBLIC KEY-----',
'-----END PUBLIC KEY-----',
'-----BEGIN CERTIFICATE-----',
'-----END CERTIFICATE-----'
];
$data = str_replace($datas, '', $pem);
return trim($data);
}
# $datas = certificat au format PEM
$pkey = extractPublicKey($datas);
$pem = pem2der(stripDatas($pkey));
switch($tlsa_match) {
case 0: $data = $pem; break;
case 1: $data = hash('sha256', $pem, true); break;
case 2: $data = hash('sha512', $pem, true); break;
}
$tlsa_cert_associated = bin2hex($data);
# les variables $port, $protocol, $domain ainsi que les $tlsa_* sont des variables créées dans le contexte du formulaire HTML, et nommées très simplement selon leur contexte.
$tlsa_gen = "_".$port."._".$protocol.".".$domain.". IN TLSA ".$tlsa_usage." ".$tlsa_selector." ".$tlsa_match." ".$tlsa_cert_associated;
# pour finir, un echo là où vous le désirez dans votre code HTML de restitution...
echo $tlsa_gen
?>
Les fonctions dans le code ne sont pas de moi - je partage ni + ni -
Il existe des modules à Firefox :
On peut le faire par l’usage de générateur TLSA en ligne - puis comparer les infos restituées avec celles que vous avez générées - malheureusement rien d’automati(que|sé) :
L’afnic a écrit des articles intéressants à-propos de :
Stéphane Bortzmeyer aussi parle de la RFC 6698 et explique beaucoup de choses intéressantes !
Un autre article expliquant de manière claire, simple DANE-TLSA.
Voilà !
Cet article répertorie les différentes erreurs plus ou moins classiques, et essaie d’apporter une réponse !
Faites à minima un chmod 0600 dessus :
$ chmod 0600 ~/.gnupg
error: cannot run gpg: No such file or directory
error: impossible de lancer gpg.
Le système ne trouve pas l’outil GPG. Vérifiez votre installation …
gpg: échec de la signature : Inappropriate ioctl for device
gpg: signing failed: Inappropriate ioctl for device
Vérifiez
que les paquets pinentry
, et/ou ses variantes pour gtk
sous Linux, *BSD soient installés : pinentry-gtk2
, pinentry-gtk3
Sinon, faites-le !
gpg: failed to start the dirmngr '/usr/bin/dirmngr': Aucun fichier ou dossier de ce type
gpg: connecting dirmngr at '/tmp/apt-key-gpghome.fPXOnUY2mr/S.dirmngr' failed: Aucun fichier ou dossier de ce type
gpg: keyserver receive failed: Pas de dirmngr
Vérifiez que le paquet dirmgnr soit installé ; sinon, faites-le !
La clé que vous cherchez à utiliser ou avec laquelle vous cherchez à signer est en mode “protégé”.
Le seul moyen que j’ai trouvé est de supprimer la clé en question :
Code :
$ gpg --delete-secret-and-public-key
gpg (GnuPG) 1.4.21; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
sec 4096R/*** 2016-03-28 Nom Prenom <email@domain.tld>
Faut-il supprimer cette clef du porte-clefs ? (o/N) o
C'est une clef secrète — faut-il vraiment la supprimer ? (o/N) o
pub 4096R/*** 2016-03-28 Nom Prenom <email@domain.tld>
Faut-il supprimer cette clef du porte-clefs ? (o/N) o
Puis de réimporter le fichier de signature de clé privée que vous avez créé suite à la création de ladite clé :
Code :
$ gpg --import ~/email@domain.tld.private_key.asc
gpg: clef *** : clef secrète importée
gpg: clef *** : clef publique « Nom Prenom <email@domain.tld> » importée
gpg: Quantité totale traitée : 1
gpg: importées : 1 (RSA: 1)
gpg: clefs secrètes lues : 1
gpg: clefs secrètes importées : 1
Avez-vous veillé à exporter la variable GPG_TTY ?
Ajoutez dans votre fichier .bashrc
, ou .kshrc
:
export GPG_TTY="$(tty)"
Ceci est un tutoriel pour utiliser l’interface graphique du logiciel client d’Urbackup - logiciel de sauvegarde sur serveur -
La première erreur à ne pas commettre est de bien télécharger le bon client :
Nécessite :
gksu
doit être installé sur la station à sauvegarder…# apt install build-essential "g++" libwxgtk3.0-dev "libcrypto++-dev" libz-dev
$ wget https://hndl.urbackup.org/Client/2.1.17/urbackup-client-2.1.17.tar.gz
$ tar xzf urbackup-client-2.1.17.tar.gz
$ cd urbackup-client-2.1.17
$ ./configure
$ make -j4
# make install
$ urbackupclientbackend -v info
2018-02-15 18:22:00: Started UrBackupClient Backend…
2018-02-15 18:22:01: Looking for old Sessions… 0 sessions
/etc/systemd/system/urbackup.service
:
Fichier : /etc/systemd/system/urbackup.service
|
|
# chmod a+x /etc/systemd/system/urbackup.service
# systemctl --system daemon-reload
# systemctl start urbackup.service
# systemctl enable urbackup.service
Code : shell
# systemctl status urbackup.service
● urbackup.service - Urbackup Backend
Loaded: loaded (/etc/systemd/system/urbackup.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2018-02-15 17:33:37 CET; 4min 5s ago
Process: 13362 ExecStart=/usr/local/sbin/urbackupclientbackend -d (code=exited, status=0/SUCCESS)
Main PID: 13364 (urbackupclientb)
Tasks: 11 (limit: 4915)
CGroup: /system.slice/urbackup.service
└─13364 /usr/local/sbin/urbackupclientbackend -d
Feb 15 17:33:37 ptb-mlm systemd[1]: Starting Urbackup Backend…
Feb 15 17:33:37 ptb-mlm systemd[1]: Started Urbackup Backend.
Le binaire du client graphique se nomme urbackupclientgui
et nécessite
des droits administrateurs pour le paramétrage de celui-ci :
# adduser USERID sudo
/usr/local/bin/urbackupclientgui
Ce menu est celui qui vous permettra d’ajouter ou supprimer les répertoires que vous voulez sauvegarder !
Enjoy-ID! Enjoy-IT!
L’usage de l’outil adb
pour communiquer avec vos périphériques sous Android (tel que smartphone, tablette, etc…) est possible !
Il existe une liste des périphériques connus pour fonctionner - vous y trouverez les identifiants vendeurs nécessaires.
Installez le paquet adb.
Veillez à ce que votre périphérique android soit en mode debug developper
, puis activez l’option debug USB
!
Pour être sûr que votre périphérique soit reconnu, utilisez la commande adb devices
:
Code : sh
$ adb devices
List of devices attached
0123456789ABCDEF device
Pour obtenir l’aide des différentes commandes liées à l’outil adb, tapez juste adb
dans votre terminal-console.
$ adb push -p /repertoire_local_machine/fichier /repertoire_peripherique_android
$ adb pull -a -p /repertoire_peripherique_android/fichier /repertoire_local_machine
L’option -a
copie les informations telles que le temps, et le mode du fichier.
La commande principale est : $ adb backup -f nom_fichier_sauvegarde.ab
$ adb backup -f nom_fichier_sauvegarde.ab -all
Cette commande implique la sauvegarde de toutes les applications installées, dont les applications systèmes.
$ adb backup -f nom_fichier_sauvegarde.ab -apk -obb
Cette commande sauvegarde les fichiers apk des applications installées.
$ adb backup -f nom_fichier_sauvegarde.ab package1 package2 package_n
Celle-ci sauvegarde juste les applications dont les noms sont concernés !
$ adb backup -f nom_fichier_sauvegarde.ab -shared
Sauvegarde le contenu de la SD Carte, ainsi que de tout répertoire de stockage partagé.
$ adb backup -f nom_fichier_sauvegarde.ab -system
Le moyen pertinent de sauvegarder tout correctement, sans s’occuper du contenu de la SD Carte, est :
$ adb backup -f nom_fichier_sauvegarde.ab -apk -obb -all
L’outil adb
peut servir à sauvegarder indirectement les partitions de votre périphérique…
Pour cela, il faut télécharger l’outil rkdump !
Puis l’installer ainsi :
Code : sh
$ adb push rkdump /data/
$ adb shell chmod 0755 /data/rkdump
Pour l’utiliser l’outil rkdump, veuillez lire son tutoriel…
$ adb restore nom_fichier_sauvegarde.ab
Il peut être intéressant d’effectuer la manipulation suivante :
~/.android/adb_usb.ini
, et écrivez dedans 0x
suivi de votre idVendorQuoiqu’il en soit, redémarrer le serveur adb : $ adb kill-server
Puis relancez la commande adb devices
.
Lorsque je tape adb devices
, le périphérique est reconnu mais affiché offline
.
Code : sh
$ adb devices
List of devices attached
0123456789ABCDEF offline
Il vous faudra alors :
Débogage USB
…Débogage USB
À ce moment-là, essayez à nouveau la commande adb devices
; vous devriez voir apparaître votre périphérique… correctement !
Lorsque je tape adb devices
, le périphérique n’est pas reconnu et il est affiché ???????????? no permissions
.
Il vous faut tuer le serveur, le redémarrer avec des droits administrateur ensuite le périphérique apparaîtra !
Code : sh
$ adb kill-server
$ adb start-server
daemon not running. starting it now on port 5037
daemon started successfully
$ adb devices
List of devices attached
0123456789ABCDEF device
Redshift est un utilitaire système qui paramètre la température des couleurs de votre écran selon l’heure du jour, et de votre position géographique. Le but de cet outil est de vous aider à moins fatiguer vos yeux, la nuit, et à réduire les risques liés au syndrome de retard de phase de sommeil, lors de votre vision informatique en soirée.
La température de couleur est paramétrée en fonction de la position du soleil. La température de couleur est réglée différemment selon le jour ou la nuit. Durant le crépuscule, et au petit matin, la température de couleur varie doucement de la nuit vers la température de jour en permettant à vos yeux de s’adapter lentement sur une période d’une heure environ. La nuit, la couleur de température devrait être paramétrée pour correspondre avec celles de vos lampes. C’est typiquement une basse température autour de 3000-4000K (par défaut est 3700K) . Durant la journée, la température de couleur doit correspondre avec celle de la lumière du jour, de fait entre 5500-6500K (par défaut est de 5500K). La lumière a une température plus haute par temps nuageux.
La température neutre est de 6500K. Utiliser cette valeur ne change pas la température de votre écran. Régler sur une valeur plus importante définira une lumière tirant vers le bleu ; définir une valeur plus bas se traduira par une lumière plus rouge.
Voici les valeurs par défaut de température : Jour: 5500K, Nuit: 3700K
Installez le paquet redshift .
redshift [-l LAT:LON | -l PROVIDER:OPTIONS] [-t DAY:NIGHT] [OPTIONS…]
Placez votre fichier de configuration personnelle dans ~/.config/redshift.conf
. C’est un simple fichier au standard INI.
Voici sa configuration de base :
[redshift]
temp-day=5500
temp-night=3700
gamma=0.8
adjustment-method=randr
location-provider=manual
[manual]
lat=44.1333
lon=0.35
L’option temp-day
doit être un entier allant de 6500 à 5500.
L’option temp-night
doit être un entier allant de 4000 à 3000.
Vous pouvez définir manuellement une température en utilisant redshift
,
tel que :
$ redshift -O TEMP
où TEMP
est un entier, à moduler selon la température de période jour
ou nuit désirée. (cf ci-dessous pour les températures de jour et de nuit).
Les températures de jour et de nuit peuvent aussi être gérées manuellement,
par l’usage de redshift
, tel que :
$ redshift -t JOUR/NUIT
où JOUR
correspond à la température de jour, et NUIT
respectivement
à celle de nuit.
Permet d’ajuster le mode gamma, soit de manière globale pour les deux périodes
de jour et de nuit, soit spécifique à l’une ou l’autre. Ce sont des valeurs
de type RGB qui sont utilisées, tel que R:G:B
.
Ajuste le mode gamma pour les deux périodes : gamma = R:G:B
Ajuste le mode gamma juste pour la période jour : gamma-day = R:G:B
Ajuste le mode gamma juste pour la période nuit : gamma-night = R:G:B
Le mode gamma global peut aussi être géré manuellement, en utilisant redshift
,
tel que :
$ redshift -g R:G:B
où R:G:B
sont bel et bien les valeurs de couleurs en mode RGB.
C’est le méthode utilisée pour régler la température des couleurs.
La plus commune semble être randr
.
Ajustez l’option adjustment-method = nom
.
Pour connaître le nom des différentes méthodes possibles, utilisez l’outil
redshift
, tel que :
$ redshift -m list
Méthodes d'ajustement disponibles :
drm
randr
vidmode
dummy
Spécifiez les options séparées par des deux-points en tant que « -m MÉTHODE:OPTIONS ».
Essayez « -m MÉTHODE:help » pour obtenir de l'aide.
Il y a deux moyens de définir vos coordonnées latitude et longitude,
toutes deux gérées par l’option location-provider
.
Pour connaître les différents fournisseurs de location supportés par
redshift
, utilisez-le tel que :
Code : shell
$ redshift -l list
Fournisseurs de localisation disponibles :
geoclue2
manual
Spécifiez les options séparées par des deux-points en tant que « -l FOURNISSEUR:OPTIONS ».
Essayez « -l FOURNISSEUR:help » pour obtenir de l'aide.
$ redshift -l list
Fournisseurs de localisation disponibles :
geoclue2
manual
Spécifiez les options séparées par des deux-points en tant que « -l FOURNISSEUR:OPTIONS ».
Essayez « -l FOURNISSEUR:help » pour obtenir de l'aide.
Le fournisseur geoclue est un mode de mise-à-jour automatique de vos coordonnées.
Vous pouvez utiliser le fournisseur geoclue, tel que, par exemple :
$ redshift -l geoclue2 -t 5500:3700 -b 1.0:0.8
Dans votre fichier de configuration, changez la valeur de location-provider
par geoclue2
.
Pour connaître la latitude, longitude de votre ville, faites une recherche
par le biais d’un moteur de recherche, en tapant latitude longitude ville pays
…
Dans votre fichier de configuration, changez la valeur de location-provider
par manual
. C’est le mode par défaut.
Puis dans la section [manual]
, définissez les valeurs lat
et lon
par les valeurs respectives de latitude et de longitude.
Il est possible d’activer un effet de transition lors de la bascule entre
les deux périodes de jour et de nuit. C’est l’option transition
qui
le gère et doit être un entier de type binaire, strictement, soit 0
, soit 1
.
Il est possible de gérer la luminosité de l’écran, soit pour la période jour,
soit pour la période nuit. Ce sont des valeurs strictement décimales à
utiliser qui vont de 0.1
à 1.0
.
Ajuste la luminosité de l’écran pour la journée : brightness-day = value
Ajuste la luminosité de l’écran pour la nuit : brightness-night = value
Le point d’élévation solaire définit le point de transition entre les deux périodes de jour et de nuit.
Le point d’élévation solaire se définit soit pour le jour, soit pour la nuit. C’est une valeur décimale à utiliser.
Ajuste le point d’élévation solaire pour le jour : elevation-high = decimal
Ajuste le point d’élévation solaire pour la nuit : elevation-low = decimal
Pour les différentes options de configuration, veuillez lire la page de
manuel de redshift(1)
, accessible seulement sur votre système :
man redshift
Voici une copie écran minimaliste de la version disponible dans OpenBSD 6.1 :
OPTIONS
-h Display this help message
-v Verbose output
-V Show program version
-b DAY:NIGHT
Screen brightness to apply (between 0.1 and 1.0)
-c FILE
Load settings from specified configuration file
-g R:G:B
Additional gamma correction to apply
-l LAT:LON
Your current location, in degrees, given as floating point
numbers, towards north and east, with negative numbers
representing south and west, respectively.
-l PROVIDER[:OPTIONS]
Select provider for automatic location updates (Use `-l list' to
see available providers)
-m METHOD[:OPTIONS]
Method to use to set color temperature (Use `-m list' to see
available methods)
-o One shot mode (do not continuously adjust color temperature)
-O TEMP
One shot manual mode (set color temperature)
-p Print mode (only print parameters and exit)
-x Reset mode (remove adjustment from screen)
-r Disable temperature transitions
-t DAY:NIGHT
Color temperature to set at daytime/night
The neutral temperature is 6500K. Using this value will not change the
color temperature of the display. Setting the color temperature to a
value higher than this results in more blue light, and setting a lower
value will result in more red light.
Default temperature values:
Daytime: 5500K, night: 3700K
Il est possible de l’exécuter directement en mode console, tel que :
$ redshift -l 44.1333:0.35 -t 5700:3600 -g 0.8 -m randr -v &
Allez dans le menu “Applications” > “Accessoires”.
Éxecutez le binaire redshit-gtk
:
$ /usr/local/bin/redshift-gtk
L’icône s’affichera dans le systray. Faites un clic droit et choisissez de cocher “Lancement automatique”.
Sinon, modifiez les paramètres systèmes, tel que “Session et démarrage” pour XFCE, puis l’onglet “Démarrage automatique d’application”, pour ajouter une application.
Dans le champ nommé “commande”, écrivez redshift-gtk
ou le chemin absolu
vers le binaire /usr/local/bin/redshift-gtk
.
Quand vous serez dans votre session graphique, vous aurez le logiciel qui fonctionnera en tâche de fond, et l’icône “redshift” dans le systray.
Redshift n’affecte pas la température de couleur si votre pilote graphique est configuré pour utiliser matériellement votre curseur.
Quelques pilotes logiciels graphiques ont l’option pour désactiver matériellement le curseur dans le fichier xorg.conf.
SSH a son propre format de génération de ses clés. Or, dans certains contextes, tel que le projet OMV, il est nécessaire de fournir votre clé publique au format RFC 4716 !
La norme RFC 4716 est une simple présentation de la clé privée ou publique dans un format texte, dit ASCII, ni plus, ni moins ;-)
Comme pour
créer sa clé
,
on utilise l’outil ssh-keygen
, de telle manière :
=> Pour une clé ed25519 :
$ ssh-keygen -e -f ~/.ssh/id_ed25519 > id_ed25519_rfc4716.pub
=> Idem pour une clé RSA :
$ ssh-keygen -e -f /home/zou/.ssh/id_rsa > id_rsa_rfc4716.pub
Il ne vous reste plus qu’à copier-coller le contenu du fichier dans l’interface ou sur le serveur où ce format vous est demandé.
Bien-sûr il est possible de la générer directement dans votre terminal ; pour cela, n’utilisez pas la redirection de sortie :
ssh-keygen -e -f ~/.ssh/id_ed25519
X-Content-Type-Options est une technique de base qui demande aux clients web de ne pas (télé)charger des ressources, tels que des scripts ou des feuilles de styles à moins que le serveur n’indique correctement le type MIME . Sans cette entête, les clients web pourraient télécharger n’importe quoi, et ainsi être victimes d’attaques.
X-Content-Type-Options est une entête HTTP , dont la mise-en-place est extrêmement aisé, mais le bénéfice est faible !
Il n’existe qu’une seule option possible : nosniff
Elle fait partie des entêtes de base à générer pour protéger son site web, au même titre que l’usage de HSTS , et des autres entêtes X-*-Options, telles que X-Frame-Options , ou X-XSS-Protections …
X-Content-Type-Options: nosniff
add_header X-Content-Type-Options "nosniff" always;
Et, oui, malheureusement, httpd ne peut pas gérer les entêtes, ce sera son binôme relayd(8) que l’on utilisera !
match response header set "X-Content-Type-Options" value "nosniff"
X-Frame-Options est une entête HTTP qui permet de contrôler comment les sites internet externes peuvent “encapsuler” le vôtre.
L’usage de cette entête est recommandé, d’autant qu’elle est simple à gérer et son bénéfice de sécurité est important.
Cette entête remplace l’historique entête Frame-Options
, et est
elle-même remplacée par la directive frame-ancestors
de l’entête
CSP
!
Elle fait partie des entêtes de base à générer pour protéger son site web, au même titre que l’usage de HSTS , et des autres entêtes X-*-Options, telles que X-Content-Type , X-XSS-Protections ,…
3 options sont permises :
DENY
: interdit aux autres de mettre votre site dans une iframe. C’est l’option recommandée
!SAMEORIGIN
: permet d’être mis dans une frame, à-partir de votre propre site.ALLOW-FROM uri
: Cette option est dépréciée
- il est clairement recommandée de ne plus l’utiliser au profit de la directive frame-ancestors
gérée par l’entête
CSP
.X-Frame-Options: DENY
add_header X-Frame-Options "DENY" always;
Et, oui, malheureusement, httpd ne peut pas gérer les entêtes, ce sera son binôme relayd(8) que l’on utilisera !
match response header set "X-Frame-Options" value "DENY"
X-XSS-Protection est une technique de protection dont le but est de stopper le (télé)chargement de pages lorsque certaines attaques sont détectées.
C’est une entête HTTP dont le bénéfice est minimale, et aisée à mettre en place… et dont l’impact n’est pas négligeable.
Il n’existe qu’une seule option : 1; mode=block
Elle fait partie des entêtes de base à générer pour protéger son site web, au même titre que l’usage de HSTS , et des autres entêtes X-*-Options, telles que X-Content-Type-Options , X-Frame-Options …
X-XSS-Protection: 1; mode=block
add_header X-Xss-Protection "1; mode=block" always;
Et, oui, malheureusement, httpd ne peut pas gérer les entêtes, ce sera son binôme relayd(8) que l’on utilisera !
match response header set "X-Xss-Protection" value "1; mode=block"
SRI est une norme du W3C pour protéger des attaques par modification des ressources proposées par votre site internet, ou de celles que vous ajoutez, fournies par d’autres. Dans l’immédiat, elle ne s’utilise que pour les scripts JS et les feuilles de styles. Si la somme de contrôle relative à la ressource attendue ne correspond pas à celle déclarée, alors la ressource n’est pas (télé)chargée par le client web.
Le bénéfice de cette technique est réelle, mais elle peut être un peut complexe à mettre en place.
Il est possible de l’utiliser conjointement avec la directive
require-sri-for
de l’entête
CSP
.
integrity
: la somme de contrôle, encodée en base64, précédée de la fonction de hash utilisée. Seuls les algorithmes sha256
, sha384
- recommandation minimale - , et sha512
sont supportés. Il est possible de spécifier plusieurs niveaux de hash, dans ce cas, ce sera le hash le plus fort qui sera consulté en priorité ; s’il n’est pas supporté, ce sera celui qui le précéde.crossorigin
: informe le client web que la ressource partagée l’est de manière anonyme, sans aucun cookie. Une seule option : anonymous
.Fichier :
|
|
Bien-sûr, il est possible de faire de même - c’est fortement encouragé
Ci-dessous, retrouvez le code de génération shell :
cat "${file}" | openssl dgst -"${algo}" -binary | openssl enc -base64 -A
L’entête HTTP Referrer est une politique de protection d’un site internet, récente, en cours de travail… Cette politique permet aux sites web un contrôle fin sur l’origine d’où vient le client web. Cela vous permet de limiter l’exposition de votre site web, en limitant voire interdisant les informations que peuvent contenir cette entête.
Cette entête complète la directive ‘referrer’ de l’entête CSP
4 options sont utiles :
no-referrer
: ne jamais envoyer l’entête ; elle aura une valeur à vide. same-origin
: envoie l’entête mais seulement si le client se connecte sur le même sitestrict-origin
: envoie l’entête, en ne contenant que votre URL, tel que : https://mon.domaine.netstrict-origin-when-cross-origin
: envoie l’entête complète… votre URL vers un site extérieur.Referrer-Policy: same-origin
add_header Referrer-Policy same-origin;
Et, oui, malheureusement, httpd ne peut pas gérer les entêtes, ce sera son binôme relayd(8) que l’on utilisera !
match response header set "Referrer-Policy" value "same-origin"
CSP est une politique de sécurité relative au contenu que votre site “distribue” vers l’utilisateur final, quelque soit son client web. Cette entête HTTP permet de contrôler très finement l’accès aux ressources de votre site et des ressources partagées par d’autres à-partir de votre site.
Cette politique de sécurité impose que le développement des codes CSS } et JS soit propre, c’est-à-dire “embarqué” par les balises HTML adéquates pour charger du code source correspondant, et non pas embarqués dans le code source HTML. On parle de code inline ; c’est cela qu’il faut éviter…
Le bénéfice de sécurité est vraiment important, mais regorge de difficultés conséquentes, car il est vraiment nécessaire de comprendre les impacts des différentes directives qui vont plus ou moins empêcher l’accès aux ressources !
Il faut aussi assimiler qu’avec une seule entête HTTP, il est possible d’avoir un éventail d’interactions qui ne sont pas anodines.
Il y a actuellement deux normes :
Il y a deux modes possibles, et il est vraiment conseillé de commencer avec le premier, histoire de réaliser les tenants et aboutissants :
Content-Security-Policy-Report-Only
: ce mode est à considérer comme un mode de test, qui n’a pas d’impact sur votre site web, mais permet de tester les différentes directivesContent-Security-Policy
: est le mode d’application des directivesIl a vraiment beaucoup de directives, d’autant que selon la version de la politique CSP, certaines sont déclarées obsolètes…
La première directive à mettre-en-place est la directive par défaut :
default-src
: est la directive qui définit par défaut le comportement de l’entête CSP. - norme CSP 1
- Attention, seules certaines directives sont assujetties à cette directive par défaut : child-src
, connect-src
, font-src
, img-src
, manifest-src
, media-src
, object-src
, script-src
, style-src
et worker-src
!Voici les autres directives qui peuvent être mises-en-place :
base-uri
: définit l’URI que le client web utilisera comme base de la page web affichée - norme CSP2
-block-all-mixed-content
: empêche que le client web (télé)charge du contenu sur le protocole HTTP alors que la page est consultée en mode HTTPSchild-src
: définit les sources valides relatives aux contenus autorisés - norme CSP2
-connect-src
: définit quelles sources sont valides pour les connexions de type XMLHttpRequest, WebSocket, et assimilées. - norme CSP 1
-disown-opener;
: assure qu’une ressource ne puisse être ouverte lors de sa consultation - norme CSP3
-font-src
: directive ayant un impact sur les polices à afficher. - norme CSP 1
-form-action
: définit l’interaction avec l’élément HTML form. - norme CSP2
-frame-ancestor
: directive pour les ressources partagées par les frames embarquées - norme CSP2
- c’est l’équivalent de l’entête X-Frame-Options…frame-src
: directive pour les ressources partagées par les frames embarquées. - norme CSP 1
- dépréciée
en CSP2
- réintroduite dans CSP 3
img-src
: directive ayant un impact sur les images à charger. - norme CSP 1
-manifest-src
: définit quel manifeste peut être appliquée à la ressource. - norme CSP3
-media-src
: directive pour les ressources audio, et vidéo. - norme CSP 1
-navigate-to
: directive pour contrôler les ressources autorisées à la navigation - norme CSP3
-object-src
: directive pour les ressources qui chargent des plugins, des applets et autres éléments embed. - norme CSP 1
-plugin-types
: directive qui définit le type des ressources qui peuvent être chargées. - norme CSP2
-referrer
: directive équivalent à l’entête Referrer - cette directive a ses propres mots-clés !reflected-xss
: directive pour filtrer les attaques de type XSS - équivalent de l’entête X-XSS-Protection - cette directive a ses propres mots-clés !report-to
: spécifie un jeton qui définit un groupe de rapports à envoyer. - norme CSP3
-report-uri:
: directive qui définit l’URL où reporter les violations de sécurité. - norme CSP 1
- dépréciée en CSP3
, au profit de report-to
-require-sri-for
: directive qui oblige l’attribut
SRI
pour les scripts et autres styles. - cette directive a ses propres mots-clés !sandbox
: directive qui utilise une sandbox HTML pour protéger l’exécution des ressources. - cette directive a ses propres mots-clés ! - norme CSP 1
-script-nonce
: directive qui autorise l’exécution d’un script seulement s’il y a correspondance avec l’attribut nonce
. cf : les explications liées au mot-clé nonce
ci-dessous…script-src
: directive qui régit les scripts exécutables, tels que JS. - norme CSP 1
-style-src
: directive qui régit les feuilles de styles. - norme CSP 1
-upgrade-insecure-requests
: oblige toute requête faite en HTTP à basculer en HTTPS si une page est chargée en HTTPS.worker-src
: définit quelles URL peuvent être chargées en tant que Worker, Sharedworker ou ServiceWorker.Il est très possible, du fait de l’évolution de la norme de cette entête que j’ai oublié la présentation de certaines directives… veuillez vérifier auprès du W3C.
default-src
n’a pas d’impact sur certaines directives, telles que frame-ancestor
, form-action
, si ces dernières ne sont pas spécifiées, alors l’émission de données correspondantes sera envoyée…block-all-mixed-content
est évaluée après la directive upgrade-insecure-requests
child-src
remplace la directive frame-src
child-src
n’est pas définie, elle est influencée par default-src
- c’est le cas de toutes les directives assujetties à cette dernièrescript-src
.frame-src
, work-src
ne sont pas spécifiées, la politique child-src
s’applique.plugins-type
n’accepte pas le caractère wildcard *
; il faut définir un type MIME : e.g : application/pdf
!==== Recommandations ===
default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self';
; et de voir comment cela réagit ! ;-)object-src
, préférez l’usage du mot-clé none
, sauf à avoir l’absolu nécessité d’exécuter des scripts Flash, ou Silverlight.block-all-mixed-content
et upgrade-insecure-requests
, il est recommandé d’activer ou l’une, ou l’autre, mais pas les deux !script-src 'self'
qui peut ne pas être sûre en présence de JSONP.report-uri
qui postera du contenu JSON pour relever les violations de sécurité, par vos propres moyens, ou au-travers d’un service fourni par un tiers.Aux directives, il est possible d’appliquer un ou plusieurs mots-clés :
*
: autorise toutes les ressources. Ce wilcard peut s’appliquer aussi dans l’écriture des schemes, des URL et des ports autorisés, tel que : *://*.domaine.xyz://
<= cet exemple signifie l’autorisation de toutes les ressources des différents sous-domaine, quelque soit le protocole utilisé, et sur n’importe quel port de connexion.'none'
: refuse toutes les ressources - C’est la politique à préférer, en terme de sécurité absolue, sur la directive par défaut !'self'
: autorise les ressources du domaine en cours ; ne gèrent pas les ressources de sous-domaines, s’ils existent… il faut les autoriser explicitement par l’ajout de l’URL correspondante ! - C’est la politique minimale à appliquer sur la directive par défaut.'strict-dynamic'
: autorisera les scripts à charger leurs dépendances sans avoir à les autoriser spécifiquement - norme CSP3
-'unsafe-inline'
: permet l’usage du code inline CSS ou JS.'unsafe-eval'
: permet l’évaluation de tout…'unsafe-hashed-attributes'
: autorisera les gestionnaires d’événements selon leur hash. - norme CSP3
-Mots-clés relatifs à la gestion des données - dans chaque cas, il est strictement nécessaire de spécifier une URI :
blob:
: autorise l’usage de binairesdata:
: autorise l’usage des données relatives à certaines directives utilisées, telles que les directives script-src
, styles-src
,… cela peut être des images encodées en base64filesystem:
: autorise l’usage de ressources depuis le système de fichiers.https:
: oblige les ressources à être chargées absolument par le biais du protocole HTTPS.mediastream:
: autorise le chargement de streaming de médias audio, vidéo,…wss:
: autorise le chargement des websockets !Mots-clés relatifs à la directive referrer :
origin
: le client web envoie toujours l’origine de l’entête vers le même siteorigin-when-cross-origin
: le client web enverra l’origine de l’entête uniquement vers le même site même lorsque les origines sont croisées.no-referrer
: n’envoie pas l’entêteno-referrer-when-downgrade
: n’envoie pas l’entête quand le client navigue depuis HTTPS vers HTTPsame-origin
: envoie l’entête si seulement vers le même siteunsafe-url
: envoie toujours l’entête vers tous.Mots-clés relatifs à la directive reflected-xss :
allow
: désactive toute protection contre les attaques XSS.block
: bloque le chargement des ressources si une attaque XSS est détectéefilter
: filtre la charge XSS avant son exécutionMots-clés relatifs à la directive require-sri-for :
script
: oblige l’attribut integrity pour les scriptsstyle
: oblige l’attribut integrity pour les stylesscript, style
: oblige l’attribut integrity pour les scripts et les stylesMots-clés relatifs à la directive sandbox :
sandbox
: active la protection avec toutes les restrictions en place. Aucune des autres valeurs ne doit être spécifiée afin que toutes les restrictions soient respectées !allow-forms
: permet une page à soumettre un formulaireallow-pointer-lock
: évalue la gestion du pointeur de souris.allow-modals
: permet les interactions avec le client web.allow-popups
: autorise l’ouverture de popupsallow-same-origin
: permet à une page d’accéder à du contenu depuis le même siteallow-scripts
: permet à une page d’exécuter ses scriptsallow-top-navigation
: permet à une page de ???Il existe deux mots-clés très spécifiques :
hash
: il permet d’autoriser un script, ou un style en particulier selon le hash définit… le hachage est calculé selon un des trois algorithmes SHA-2 (sha256, sha384 - politique minimale recommandée, sha512), encodé en base64. e.g. : style-src 'sha256-HashDigestHere='
nonce
: acronyme de Number used Once - Numéro utilisé une seule fois - ; il permet d’autoriser un script inline selon la valeur dynamique aléatoire autorisé.Il est très possible, du fait de l’évolution de la norme de cette entête que j’ai oublié la présentation de certains mots-clés… veuillez vérifier auprès du W3C.
https:
sur la directive par défaut, tel que : default-src: https:
. Cela désactive le code inline et oblige toute connexion en mode HTTPS seulement.unsafe-inline
! Malheureusement, parfois certains scripts “embarqués” ou styles extérieurs nécessitent des données et autres codes qu’il est difficile de gérer finement ; c’est la solution du “moins pire”unsafe-eval
!data:
: par ce biais, il peut remonter des contenus “dérivés” inhérents aux directives object-src
, script-src
,…nonce
doit être unique, re-généré à chaque fois, et bien entendu doit être non trivial et non devinable !`Les risques possibles sont liés à :
unsafe-*
…unsafe-inline
est l’équivalent de ne pas avoir de politique de sécurité ; quant à utiliser le mot-clé unsafe-eval
est assurément l’équivalent d’un trou béant dans votre site web où vous permettez à tout le monde de faire n’importe quoi… <= vous, voilà, prévenus !!! oui, j’exagère peut-être un peu… mais le risque est réel, et sérieux.Content-Security-Policy: default-src https:
Il est possible de la définir par le biais de l’élément HTML meta, tel que :
<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
add_header Content-Security-Policy "default-src 'self';" always;
Et, oui, malheureusement, httpd ne peut pas gérer les entêtes, ce sera son binôme relayd(8) que l’on utilisera !
match response header set "Content-Security-Policy" value "default-src 'self' data: 'unsafe-inline'; base-uri \*://domain.tld ; form-action 'self'; frame-ancestors 'none'; referrer no-referrer; reflected-xss block; sandbox allow-same-origin ; script-src 'self' cdnjs.cloudflare.com netdna.bootstrapcdn.com ;"
CORS est une entête HTTP qui contrôle quels sites, externes ou non, peuvent accéder au contenu de votre site web, par le biais de scripts, tel que le propose XMLHttpRequest.
C’est une technique très facile à mettre en place et dont le bénéfice est vraiment important !
L’usage du symbole *
accepte que n’importe quel site puisse se
connecter ; sinon, remplissez une URL !
Elle fait partie des entêtes de base à générer pour protéger son site web, au même titre que l’usage de HSTS , et des autres entêtes, telles que X-Content-Type-Options , X-Frame-Options , ou X-XSS-Protections ,…
Access-Control-Allow-Origin: *
add_header Access-Control-Allow-Origin "huc.fr.eu.org" always;
Et, oui, malheureusement, httpd ne peut pas gérer les entêtes, ce sera son binôme relayd(8) que l’on utilisera !
match response header set "Access-Control-Allow-Origin" value "huc.fr.eu.org"
Le but d’utiliser Unbound est d’avoir localement sur sa station son propre serveur DNS Cache - selon la RFC 8499 , un Résolveur complet avec mémoire (en anglais, full-service resolver), c’est à dire un client DNS qui fournit un service de résolution complet, avec mémorisation des enregistrements DNS récoltés.
Utiliser Unbound avec la gestion sécurisée des informations DNS, par le biais de la technologie DNSSEC, est un plus indéniable. (cela évite d’avoir à obtenir des informations DNS faussées, par une action pirate, par une action “étatique”…).
Sous OpenBSD, unbound
est intégré nativement !
# rcctl enable unbound
# rcctl start unbound
/etc/dhclient.conf
:
prepend domain-name-servers 127.0.0.1;
La configuration d’unbound ne pose pas de gros problème, en soit, il faut veiller à l’écriture correcte des informations !
Toutes les variables et leur impact sont expliquées dans la documentation officielle anglaise : https://unbound.net/documentation/unbound.conf.html
Voyons quelques détails dits de sécurité à paramétrer absolument dans
votre propre fichier de configuration :
/var/unbound/etc/unbound.conf
Pour tester la configuration de vos fichiers, utilisez la commande unbound-checkconf
!
Quand vous avez terminé votre configuration, pensez à redémarrer le service lié à unbound.
Le fichier root.hints
est une liste des serveurs de noms faisant autorité,
les premiers serveurs DNS, dits roots
.
Bien qu’OpenBSD semble avoir une liste intégrée, il est intéressant de récupérer ladite liste tous les 6 mois environ.
Pour le récupèrer :
# ftp -o /var/unbound/db/root.hints http://www.internic.net/domain/named.cache
Puis, modifiez le fichier de configuration, pour ajouter :
root-hints: "/var/unbound/db/root.hints
access-control: 127.0.0.0/8 allow
# autorise l’interface de bouclage local sur la couche IPv4
access-control: ::1 allow
# autorise l’interface de bouclage local sur la couche IPv6
access-control: 192.168.1.0/24 allow
# autorise le réseau local
access-control: 0.0.0.0/0 refuse
# interdit tout le reste de l’Internet !
access-control: ::0/0 refuse
# interdit tout Internet sur IPv6
À moins de savoir quoi modifier, laissez tel quel !
Le segment réseau peut-être de type IPv4 ou IPv6. L’action à allouer peut-être :
allow
permet l’accèsallow_snoop
permet l’accès, en utilisant une technique de “cache snopping”,
qui donne le droit d’examiner le contenu en cache.deny
refuse l’accès - option par défaut, si non spécifiée
deny_non_local
,refuse
refuse l’accès, tout en envoyant un message d’erreur adéquat.refuse_non_local
Pour les autres options, ou afin de mieux saisir les subtilités, merci de lire la page officielle anglaise !
Code : unbound
harden-algo-downgrade: no
harden-glue: yes
hide-identity: yes
hide-version: yes
private-address: 192.168.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
use-caps-for-id: no
val-clean-additional: yes
Explications
harden-algo-downgrade
empêche ou non de choisir l’algorithme le plus faible .
no
est choisi, ce sera l’algorithme le plus faible qui sera élu…no
.
Cette option n’est pas reconnue avec la version Jessie, utilisez la version backports !private-address
renforcent l’aspect privé de ces réseaux.
Cela empêche l’inclusion de ces segments réseaux dans les réponses DNS,
et protège de la technique des “Relais DNS”
(qui utilise, par exemple, un navigateur internet comme relais ou proxy réseau).use-caps-for-id
est expérimentale et peut créer des bogues,
ou résultats incorrects - ne pas l’utiliser à moins d’être sûr de ce que vous faites…val-clean-additional
assure de nettoyer toutes les données DNS non sécuriséesCode : unbound
num-threads: 4
key-cache-slabs: 8
infra-cache-slabs: 8
msg-cache-slabs: 8
rrset-cache-slabs: 8
key-cache-size: 16m
msg-cache-size: 4m
rrset-cache-size: 8m
outgoing-range: 206
qname-minimisation: yes
so-rcvbuf: 1m
so-sndbuf: 1m
so-reuseport: yes
Explications
num-thread
correspond au nombre de cœurs CPU dont dispose
votre station, soit pour 4 CPU ayant chacun deux cœurs, on lui attribuera
le chiffre 8
.
Une manière d’être sûr du nombre de cœurs utilisés dans votre machine
est d’utiliser la commande suivante :
$ sysctl hw.ncpu
hw.ncpu=4
$ sysctl hw.ncpufound
hw.ncpufound=4
slabs
doivent être paramétrées
au double de la variable num-thread
. Ces variables gèrent les conflits
de verrouillage en les diminuant.*-cache-size
est sensible et doit être ainsi
paramétrée : la variable rrset-cache-size
doit être le double de la
variable msg-cache-size
; quant à la variable key-cache-size
, elle
doit être elle-même le double de la variable rrset
.outgoing-range
qui gère le nombre de connexions par cœurs
CPU doit être ainsi calculée : 1024 / nb_coeurs_CPU - 50so-reuseport
permet d’améliorer significativement les performances
de l’usage du protocole UDP.
n'est fonctionnelle que sous Linux !
qname-minimisation
a pour propos d’améliorer les informations
privées liées à l’usage de DNS.so-rcvbuf
,
et so-sndbuf
qui doivent être augmentées dans le cas de serveur surchargé.
Autrement, laissez la valeur 0
par défaut - cela utilise les valeurs systèmes !Code : unbound
# garde en cache les bons résultats
prefetch: yes
cache-min-ttl: 3600
cache-max-ttl: 86400
Code : unbound
# gestion logs
logfile: /var/log/unbound/unbound.log
use-syslog: yes
unwanted-reply-threshold: 10000000
val-log-level: 2
verbosity: 1
Explications
unwanted-reply-threshold
est définie, le nombre paramétré
total de réponses indésirables est gardé dans chacun des processus.
Ce nombre paramétré atteint déclenche une action défensive de nettoyage
des caches rrset
et autres messages, un avertissement est affiché
dans les journaux.
Il est recommandé de positionner ce nombre à une valeur de 10 Millions !
Pour info, l’excellente documentation de Calomel recommande 10000.verbosity
est le degré de verbosité des journaux :
0
signifie que seules les erreurs seront affichées ;1
que ce sont des informations opérationnelles - valeur par défaut - ;2
que celles-ci seront plus détaillées ;3
définit les informations par niveau de requêtes et leurs sorties ;4
restitue l’information du niveau d’algorithme utilisé ;5
, quant à lui, enregistre l’identification des clients en cas d’erreurs de cache.val-log-level
à 2
permet d’atteindre un niveau d’explications
suffisant pour obtenir les raisons des échecs.
très utile à utiliser pour
unbound en mode DNSSEC
! ;)Code : unbound
statistics-interval: 0
extended-statistics: yes
statistics-cumulative: no
Explications
statistics-cumulative
est à paramétrer sur yes
-
si vous utilisez un outil d’affichage graphique des rapports, tel que Munin…Code : unbound
# bloque certaines pubs
local-zone: "doubleclick.net" redirect
local-data: "doubleclick.net A 127.0.0.1"
local-zone: "googlesyndication.com" redirect
local-data: "googlesyndication.com A 127.0.0.1"
local-zone: "googleadservices.com" redirect
local-data: "googleadservices.com A 127.0.0.1"
local-zone: "google-analytics.com" redirect
local-data: "google-analytics.com A 127.0.0.1"
local-zone: "ads.youtube.com" redirect
local-data: "ads.youtube.com A 127.0.0.1"
local-zone: "adserver.yahoo.com" redirect
local-data: "adserver.yahoo.com A 127.0.0.1"
local-zone: "ask.com" redirect
local-data: "ask.com A 127.0.0.1"
Pour savoir comment :
Sous ce nom barbare qu’est HSTS se cache une technique assez simple à mettre-en-œuvre et au bénéfice intéressant.
Cette technologie demande au client web de se connecter uniquement au protocole HTTPS, même si le serveur web permet la connexion sur le port associé au protocole HTTP. Cette technique transparente pour le client impose que toutes les connexions se font obligatoirement sur le port associé au protocole HTTPS, généralement le port 443.
Par contre, cette technique est très restrictive car elle empêche que le client web puisse contourner le protocole, en gérant finement les erreurs liées ; la finalité étant d’avertir le client des dysfonctionnements possibles.
Techniquement, c’est une entête HTTP !
C’est la première entête HTTPS à mettre en place, facile à gérer et nativement gérée par beaucoup de serveurs web !
Il y a trois options, dont une absolument nécessaire !
max-age
définit la durée dans le temps pendant laquelle le client
web est obligé à être redirigée. Cette durée, en nombre de secondes,
doit être minimale de six mois, et maximale de deux ans. C’est l’option
par défaut à implémenter !includeSubDomains
: cette directive oblige le client à traiter tous
les sous-domaines relatifs à un nom de domaine à être eux aussi résolu en HTTPS !preload
: cette directive permet à votre domaine d’être géré par
la liste de préchargement HSTS, après soumission.
Elle a pour propos d’empêcher certaines attaques mais n’est vraiment
recommandé que pour les sites dits sensibles. Si vous vous êtes soumis
à ladite liste, il est impératif que l’option ‘‘includeSubDomains’’ soit gérée !includeSubDomains
semble vraiment importante à
paramétrer sur votre nom de domaine principal. Celle-ci empêcherait une
attaque par détournement de DNS,
qui consiste à faire croire en l’usage d’un sous-domaine pour capturer
le trafic d’un client web et en prendre le contrôle. Du fait du rôle de
cette option, tout sous-domaine “déclaré” se voit obliger de communiquer
en HTTPS, en vérifiant les certificats, la relation avec le nom de domaine
principal et de sous-domaines et en interrogeant l’autorité de contrôle.Strict-Transport-Security: max-age=63072000
:
Ce qui correspond à une période de deux années.
Pour le serveur web d’OpenBSD :
Code : httpd
server mon.domaine.net {
listen on * tls port 443
# Enable HTTP Strict Transport Security (defaults to 1 year).
hsts
(...)
}
Pour le serveur nginx :
add_header Strict-Transport-Security "max-age=31536000;" always;
La technique de redirection du trafic HTTP vers HTTPS est généralement simple à comprendre et à mettre en place : Quand un client web interroge un site internet sur le port 80, il doit être redirigé automatiquement vers le port 443 qui distribue le même site, les mêmes ressources mais de manière chiffrée, par l’usage de certificats SSL au niveau du serveur.
La redirection doit être de type permanente.
Le bénéfice de sécurité est maximale pour un coût de mise-en-place simple et aisé.
Cette technique dev(r?)ait être complétée de la technologie HSTS afin de s’assurer que toute nouvelle connexion, au site web, soit directement transmise sur le port HTTPS.
Code : Apache
<VirtualHost *:80>
ServerName mon.domaine.net
Redirect permanent / https://mon.domaine.net/
</VirtualHost>
Pour le serveur web d’OpenBSD :
Code : httpd
server mon.domaine.net {
listen on * port 80
block return 301 "https://$SERVER_NAME$REQUEST_URI"
}
Code : nginx
server {
listen 80;
server_name mon.domaine.net
return 301 https://$server_name$request_uri;
}
Cette fonctionnalité est dépréciée, car difficile à mettre en place, sans parler des dangereux effets de bords si mal maîtrisée…
au profit de l’entête Expect-CT
!
Sous ce nom très barbare, HPKP se cache une fonctionnalité de sécurité qui est censée protéger les sites internet contre le vol de leur identité. Cette technique protège les certificats SSL par l’ajout de clés publiques d’authentification adressées au client web. Si les clés ne correspondent pas, le client web doit interdire purement et simplement l’accès au site internet en question.
C’est une technique très complexe à implémenter car il faut gérer correctement ces clés, les latences entre les différentes clés, celles utilisées, celles de sauvegarde. Elle est recommandée uniquement pour les sites dits à haut risque.
xenodm est un gestionnaire de sessions X, fourni dans le système de base d’OpenBSD, depuis 6.1 - le serveur X et les sessions graphiques !
C’est un dérivé du gestionnaire xdm
, purgé de beaucoup de codes, donc
plus léger, et débarrassé de potentielles failles de sécurités :
Xenodm is based on xdm source code. I’ve removed all support for XDMCP and other old cruft like ugly games with signals and setjmp(3)/longjmp(3) to set timeouts on potentially blocking operations. Another goal was to un-tangle the ifdef maze that supported various flavors of authentication methods, to only keep the BSDauth code used in OpenBSD.
ATTENTION :
Ne pas utiliser xenodm
avec l’environnement graphique Gnome3 !
Pour Gnome : Il est fortement recommandé d’utiliser GDM.
Tous les fichiers de configuration se trouvent normalement être sur :
/etc/X11/xenodm/
Quelques explications :
Le fichier /etc/X11/xenodm/xenodm-config
est le fichier de configuration
central du serveur xenodm. Il “redirige” vers les autres fichiers de
configuration spécifique… certains sont décrits ci-dessous.
Créer vos fichiers personnels, tel quel dans ~/.config/xenodm/
; faites
vos modifications dedans, puis modifier les variables DisplayManager*
dans le fichier /etc/X11/xenodm/xenodm-config
en la faisant pointer
vers vos fichiers personnels !
Mais attention à chaque upgrade de version d’OpenBSD, certains paramètres pourraient être dysfonctionnels - si vous avez des problèmes de connexion avec votre configuration personnalisée de xenodm, il serait plus prudent de repartir sur la base des fichiers originaux.
Vous désirez vous connecter automatiquement avec votre identifiant, sans avoir à le saisir constamment ?
Ajouter la variable suivante DisplayManager._0.autoLogin
, de telle manière :
DisplayManager._0.autoLogin: Identifiant
Exemple de fichier etc/X11/xenodm/xenodm-config
:
! $OpenBSD: xenodm-config.cpp,v 1.1 2016/10/23 08:30:37 matthieu Exp $
!
!
!
!
!
DisplayManager.authDir: /etc/X11/xenodm
DisplayManager.errorLogFile: /var/log/xenodm.log
DisplayManager.keyFile: /etc/X11/xenodm/xenodm-keys
DisplayManager.servers: /etc/X11/xenodm/Xservers
!DisplayManager*resources: /etc/X11/xenodm/Xresources
DisplayManager*resources: /home/UserId/.config/xenodm/Xresources
! All displays should use authorization, but we cannot be sure
! X terminals may not be configured that way, so they will require
! individual resource settings.
DisplayManager*authorize: true
!
DisplayManager*startup: /etc/X11/xenodm/Xstartup
DisplayManager*session: /etc/X11/xenodm/Xsession
DisplayManager*reset: /etc/X11/xenodm/Xreset
DisplayManager*authComplain: true
! The following three resources set up display :0 as the console.
!DisplayManager._0.setup: /etc/X11/xenodm/Xsetup_0
DisplayManager._0.setup: /home/UserId/.config/xenodm/Xsetup_0
!DisplayManager._0.startup: /etc/X11/xenodm/GiveConsole
DisplayManager._0.startup: /home/UserId/.config/xenodm/GiveConsole
DisplayManager._0.reset: /etc/X11/xenodm/TakeConsole
DisplayManager.*.authName: MIT-MAGIC-COOKIE-1
!
sont toutes des lignes de commentaires.DisplayManager*resources
,
DisplayManager._0.setup
, DisplayManager._0.startup
en commentant
celles en rapport avec les fichiers dans le répertoire de configuration
principal, pour paramétrer ceux de fichiers dans le $HOME.UserId
par votre identifiant de session…Le fichier /etc/X11/xenodm/Xresources
permet de modifier l’apparence
du gestionnaire (couleurs, polices, textes, etc.).
Pour sortir de l’exécution de xenodm, il est nécessaire de configurer le fichier Xresources afin d’ajouter ce qui suit :
xlogin.login.translations: #override \
Ctrl<Key>R: abort-display()
Cette astuce permet de basculer en mode console, en arrêtant le serveur de xenodm, par l’appui sur les touches Ctrl+R.
Pour interdire la connexion du compte root, il faut modifier ce fichier de configuration et décommenter la ligne 128, de telle manière :
xlogin.Login.allowRootLogin: false
Exemple personnalisé du fichier $HOME/.config/xenodm/Xresource
:
! $OpenBSD: Xresources.in,v 1.1 2017/07/26 21:14:54 matthieu Exp $
DisplayManager*terminateServer: true
! ----------------------------------------------------------------------
! XLogin
!
xlogin.Login.allowRootLogin: false
xlogin.Login.echoPasswd: false
xlogin.Login.fail: Authorization failed
xlogin.Login.greeting:
xlogin.Login.namePrompt:
xlogin.Login.passwdPrompt:
xlogin.Login.y: 340
xlogin.Login.width: 480
xlogin*borderWidth: 0
xlogin.Login.frameWidth: 0
xlogin.Login.innerFramesWidth: 0
xlogin.Login.sepWidth: 0
xlogin.Login.face: DejaVu Sans-16
xlogin.Login.failFace: DejaVu Sans-18:bold
xlogin.Login.greetFace: DejaVu Sans-0
xlogin.Login.promptFace: DejaVu Sans-18
! ----------------------------------------------------------------------
! XMessage
!
!xmessage*background: nord0
!xmessage*foreground: nord4
xmessage*borderWidth: 0
xmessage*font: -*-terminus-bold-*-*-*-16-*-*-*-*-*-iso8859-15
xmessage*message.scrollHorizontal: Never
xmessage*message.scrollVertical: Never
xmessage*timeout: 0
Le fichier /etc/X11/xenodm/Xsession
s’occupe de l’entrée en session
personnelle.
Un peu de décryptage utile :
~/.xsession-errors
, dont
le but est de permettre au système d’écrire dedans tout problème
relatif à l’exécution de l’entrée en session. C’est le fichier à
vérifier IMPÉRATIVEMENT si vous rencontrez des problèmes de connexion.~/.xsession
:
~/.Xresources
- copie personnelle du fichier
/etc/X11/xenodm/Xresources
- pour le charger, ainsi exécuter
les binaires xterm
, et fvwm
par défaut. C’est le seul cas,
où si ce fichier existe, il sera lu…Le fichier /etc/X11/xenodm/Xsetup_0
nous permet d’utiliser des binaires
X, tels que xconsole
(c’est la fameuse console de log qui s’affiche
par défaut), xclock
, display
, etc.
Exemple de fichier /etc/X11/xenodm/Xsetup_0
:
#!/bin/sh
# $OpenBSD: Xsetup_0,v 1.1 2016/10/23 08:30:37 matthieu Exp $
if [ "$DISPLAY" = ":0" -o "$DISPLAY" = ":0.0" ]
then
xconsole -geometry 480x130-0-0 -daemon -notify -verbose -fn fixed -exitOnFail
fi
⇒ display
permet, entres autres, d’avoir une image en fond d’écran…
/usr/local/bin/display -window root /home/user/Images/Wallpapers/OBSD_From_Dark_to_the_Light.png
(Retrouvez l’image en question…)
⇒ qiv
permet, entres autres, d’avoir un fond d’écran aléatoire, selon
les options fournies… à chaque fois que xenodm est relancé !
/usr/local/bin/qiv -zr /home/user/Images/Wallpapers/* &
(cet outil ne fait pas partie du système de base).
⇒ xclock
permet d’afficher une horloge…
/usr/X11R6/bin/xclock -d -update 1 -render &
Pour fermer automatiquement l’horloge, on récupère son id - dans le fichier
Xsetup_0
, sous la ligne déclarant le binaire, e.g.
:
echo $! > /var/run/xclock.pid
Exemple personnalisé du fichier $HOME/.config/xenodm/Xsetup_0
:
#!/bin/ksh
# $OpenBSD: Xsetup_0,v 1.1 2016/10/23 08:30:37 matthieu Exp $
if [ "$DISPLAY" = ":0" -o "$DISPLAY" = ":0.0" ]; then
BG_COLOR=$(/usr/X1R6/bin/xrdb -query | awk '/xroot.background/ { print $2 }')
OS_NAME=$(uname -n)
OS_INFO=$(uname -smr)
USER=id_user # changer par votre identifiant utilisateur
/usr/X11R6/bin/xrandr --output default --dpi 96
/usr/X11R6/bin/xset fp+ /usr/local/share/fonts/roboto
/usr/X11R6/bin/xsetroot -solid $BG_COLOR
# obtenir un fichier aléatoire dans un répertoire précis
set +A files /home/$USER/Images/OpenBSD-Art/*
N=${#files[@]} # Number of members in the array
((N=RANDOM%N))
img=${files[$N]}
/usr/local/bin/feh -b --bg-center -B $BG_COLOR -. -Z $img &
/usr/local/bin/qiv -zrd7 /home/$USER/Images/Wallpapers/* &
# menu
(
while true; do
/usr/X11R6/bin/xmessage -center \
-buttons "[ Sleep ]":20,"[ Restart ]":21,"[ Shutdown ]":22 ""
ACTION=$?
echo "Xmessage said: $ACTION"
if [ $ACTION -eq 20 ]; then /usr/sbin/zzz;
elif [ $ACTION -eq 21 ]; then
/usr/X11R6/bin/xsetroot -cursor_name watch
/sbin/shutdown -r now
elif [ $ACTION -eq 22 ]; then
/usr/X11R6/bin/xsetroot -cursor_name watch
/sbin/shutdown -p now
else echo "Something bad happened to Xmessage.";
fi
# stop looping if xclock died (hopefully killed by GiveConsole)
if [ -z "$(pgrep -U root /usr/X11R6/bin/xclock)" ]; then break; fi
done
) &
/usr/X11R6/bin/xclock -geometry -0+0 -d -update 1 -render \
-strftime "$OS_NAME ($OS_INFO) | %a. %d %b. %Y %H:%M:%S " &
#/usr/X11R6/bin/xclock -d -update 1 -render &
echo $! > /var/run/xclock.pid
fi
#sxpm OpenBSD.xpm &
À la différence, mon fichier appelle le shell ksh
, car pour définir un
fichier image aléatoire, je définis :
files
dans lequel est attribué les noms de fichiers
du répertoire cible…N
qui, dans un premier temps, définit le nombre d’éléments
du tableau files
, puis après être passer par un calcul RANDOM
,img
qui est attribué selon le N
ème élément du tableau
files
, qui est ensuite appelé par le logiciel feh
.Normalement, feh
devrait afficher l’image au centre de l’écran…
ça bogue, puisque elle est affichée depuis le haut à gauche.
La boucle while
permet d’afficher un menu linéaire, sous la zone de saisie
de session, affichant : [ Sleep ] [ Restart ] [ Shutdown ]
.
Cliquer avec la souris sur l’une ou l’autre des actions permet de déclencher
l’action nommée.
Pour l’exécution correcte de ce script Xsetup_0
, il faudra installer par
le biais du gestionnaire de paquets, et feh
, et qiv
.
Le fichier /etc/X11/xenodm/GiveConsole
a pour propos de traiter des
instructions en sortie de xenodm.
Exemple personnalisé du fichier $HOME/.config/xenodm/GiveConsole
:
#!/bin/sh
# Assign ownership of the console to the invoking user
# $OpenBSD: GiveConsole,v 1.1 2016/10/23 08:30:37 matthieu Exp $
#
# By convention, both xconsole and xterm -C check that the
# console is owned by the invoking user and is readable before attaching
# the console output. This way a random user can invoke xterm -C without
# causing serious grief.
#
chown $USER /dev/console
if [ -c /dev/drm0 ]; then
chown $USER /dev/drm0
fi
/usr/X11R6/bin/sessreg -a -l $DISPLAY -u none -x /etc/X11/xenodm/Xservers $USER
if test -r /var/run/xclock.pid; then kill $(cat /var/run/xclock.pid); fi
pkill feh
pkill xmessage
Un mini-tutoriel concernant l’usage de l’outil signify !
Pour ceux qui ne connaissent pas, signify est un outil natif du projet OpenBSD, dont le but est de générer une signature cryptographique d’un fichier ou ensemble de fichiers.
Vous avez récupéré un fichier de clé publique, créé avec signify, ainsi
que le fichier de signature ; pour vérifier que les fichiers fournis
avec soient intègres, il vous faudra utiliser signify ainsi :
$ signify -C -p Nom_Projet.pub -x Nom_Projet.sig
Cette commande signifie de vérifier avec la clé publique du projet Untel, tous les fichiers écrites dans le fichier de signature.
Cette commande peut être légèrement abrégée :
$ signify -Cp Nom_Projet.pub -x Nom_Projet.sig
Maintenant, voyons comment créer un ensemble de fichiers de clé
privée/publique avec signify :
$ signify -G -p Nom_Projet.pub -s Nom_Projet.sec
L’invite de commande vous demandera d’écrire une passphrase et de la confirmer !
Ne pas oublier la passphrase ; et, mettez en sécurité le fichier de clé privée `*.sec`, en lieu sûr !Si pour des raisons quelconques, vous avez besoin de générer une
signature sans passphrase, exécutez signify ainsi :
$ signify -G -n -p Nom_Projet.pub -s Nom_Projet.sec
Nous savons donc vérifier un ensemble de fichiers grâce à un fichier de signature, créer un ensemble de clé privée/publique, voyons comment générer un fichier de signature !
$ signify -S -e -x Nom_Projet.sig -s Nom_Projet.sec
Profitons de la possibilité de coupler l’outil signify, avec une fonction de hachage cryptographique, telle sha512
!
find ./ -exec sha512 {} + > Nom_Projet.sha512
$ signify -S -s Nom_Projet.sec -m Nom_Projet.sha512 -e -x Nom_Projet.sig
cksum
en utilisant l’option -a
pour cibler l’algorithme sha512
(entres autres…) !Le terme “somme de contrôle” est communément accepté pour parler des condensats/hashes cryptos générés à partir d’une fonction de hash. Cet usage peut être considéré comme impropre par des spécialistes. Par exemple, pour explication :
Une somme de contrôle est utile pour détecter des modifications accidentelles des données, mais n’a pas vocation à assurer une protection contre les modifications intentionnelles. Plus précisément, elle ne peut en général pas assurer directement l’intégrité cryptographique des données. Pour éviter de telles modifications, il est possible d’utiliser une fonction de hachage adaptée, comme SHA-256, couplée à un élément secret (clé secrète), ce qui correspond au principe du HMAC. source
L’USB Thetering est le partage d’une connexion réseau, depuis votre smartphone avec votre station informatique.
Votre connexion réseau, telle celle d’internet, sur votre smartphone, peut soit venir du Wifi, soit d’une connexion 3G/4G.
Connectez votre smartphone à Internet, et vérifiez que vous pouvez bien surfez avec.
Connectez le smartphone par USB à votre station OpenBSD, puis vérifiez
aussitôt la connexion :
$ dmesg | tail -n1
ugen0 at uhub0 port 2 "MediaTek MT65xx Android Phone" rev 2.00/2.16 addr 2
Dans cet exemple, le téléphone est ici reconnu comme un Android Phone.
Selon votre version d’Android :
Le menu pour activer la fonction peut être sensiblement différent, selon la marque de votre téléphone, la version du système d’exploitation utilisé, et la langue utilisée sur votre smartphone.
(Celui de l’exemple est celui d’une ROM MIUI 8)
Puis, vérifiez aussitôt :
Code : shell
$ dmesg | tail -n3
urndis0 at uhub0 port 2 configuration 1 interface 0 "MediaTek MT65xx Android Phone" rev 2.00/2.16 addr 2
urndis0: using RNDIS, address f2:5d:d2:80:94:b5
ugen0 at uhub0 port 2 configuration 1 "MediaTek MT65xx Android Phone" rev 2.00/2.16 addr 2
Coup de chance, nous avons le pilote urndis… il se comporte comme un pilote réseau pour communiquer entre le smartphone - généralement des Android - et la station, par le biais du port USB.
ifconfig
:Code : shell
$ ifconfig urndis0
urndis0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500
lladdr f2:5d:d2:80:94:b5
index 70 priority 0 llprio 3
/etc/hostname.urndis0
’, pour y ajouter au moins
la valeur dhcp
, à minima…
Faites un chmod 0640 dessus !!!Puis demandons une adresse IP :
Code : shell
# dhclient urndis0
DHCPREQUEST on urndis0 to 255.255.255.255
DHCPNACK from 192.168.42.129 (06:45:e6:2f:3f:51)
DHCPDISCOVER on urndis0 - interval 1
DHCPDISCOVER on urndis0 - interval 1
DHCPDISCOVER on urndis0 - interval 2
DHCPOFFER from 192.168.42.129 (06:45:e6:2f:3f:51)
DHCPREQUEST on urndis0 to 255.255.255.255
DHCPACK from 192.168.42.129 (06:45:e6:2f:3f:51)
bound to 192.168.42.125 -- renewal in 21600 seconds.
$ ifconfig urndis0
urndis0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr f2:5d:d2:80:94:b5
index 70 priority 0 llprio 3
inet 192.168.42.125 netmask 0xffffff00 broadcast 192.168.42.255
dhcp
lors du montage du périphérique,
on modifie le fichier /etc/hotplug/attach
, ainsi :Code : cfg
3)
# network devices; requires hostname.$DEVNAME
sh /etc/netstart $DEVNAME
;;
Selon vos règles PF, si vous en avez, selon comme elles sont construites, il est certainement préférable de relancer PF !
Maintenant, testez votre connexion Internet depuis votre station OpenBSD. Et, zou, la patate… 😃
Le code ci-dessous compresse le fichier archive et le découpe par tranche
de 100 Mo, en ajoutant une extension incrémentée alphabétique…
(tel que : _aa
pour le premier fichier, _ab
pour le second, _ac
pour le troisième, etc…)
Pour découper une archive tar, utilisons le binaire split :
tar cz fichier | split -b 100m - archive_split.tgz_
Pour découper votre archive au format gzip :
gzip -c fichier | split -b 100m - archive_split.gz_
Dans un premier temps, il nous faut “concaténer” l’archive, nous utiliserons dans les deux cas l’outil cat, puis ensuite il faut la décompresser pour obtenir le(s) fichiers(s) de l’archive.
cat archive_split.tgz_* | tar xz
cat archive_split.gz_* | gunzip -c > fichier
Le code ci-dessous compresse le fichier archive et le découpe par tranche
de 100 Mo, en ajoutant une extension incrémentée alphabétique…
(tel que : _aa
pour le premier fichier, _ab
pour le second, _ac
pour le troisième, etc…)
Pour découper une archive tar, utilisons le binaire split :
tar cz fichier | split -b 100m - archive_split.tgz_
Pour découper votre archive au format gzip :
gzip -c fichier | split -b 100m - archive_split.gz_
Dans un premier temps, il nous faut “concaténer” l’archive, nous utiliserons dans les deux cas l’outil cat, puis ensuite il faut la décompresser pour obtenir le(s) fichiers(s) de l’archive.
cat archive_split.tgz_* | tar xz
cat archive_split.gz_* | gunzip -c > fichier
Dans vos logs d’erreur web, vous avez le message d’erreur suivant :
FastCGI sent in stderr: "PHP message: PHP Warning: Unknown: Unable to create temporary file, Check permissions in temporary files directory. in Unknown on line 0
Ou celui-ci, qui est sensiblement différent :
PHP Warning: File upload error - unable to create a temporary file in Unknown on line 0
Le problème est très simple: PHP ne peut pas créer les fichiers temporaires
dont il a besoin de créer, dans le répertoire temporaire indiqué dans votre
fichier de configuration /etc/php-fpm.d/$domain.conf
.
Ouvrez votre fichier de configuration php-fpm relatif à votre site web.
Vérifiez les informations suivantes :
Fichier : /etc/php-fpm.d/$domain.conf
|
|
Relevez les informations relatives à user
, group
, et env[TMP]
env
ait bien les droits utilisateurs liés à user:group
.php_admin_value[open_basedir]
est activée, ou l’option open_basedir
, veillez à ajouter le répertoire /tmp
parmi les répertoires autorisés !# chown user:group /var/www/tmp
php_admin_value[upload_tmp_dir]
pointe vers /tmp
. C’est normal, il pointe vers le répertoire temporaire dans le chroot web…
Si le chroot web est /var/www
, le répertoire temporaire relatif est bel est bien /tmp
.
Quoiqu’il en soit, vérifiez que celui-ci est exactement les mêmes droits utilisateurs nécessaire à PHP !C’est un ensemble de message d’erreurs php-fpm !
Elles signifient que vous utilisez la variable php_admin_value[open_basedir]
.
Vous avez un message ressemblant à celui-ci :
[error] 85001#0: *47 FastCGI sent in stderr: "PHP message: PHP Warning: is_dir(): open_basedir restriction in effect. File(/var/www/cache/) is not within the allowed path(s): (/htdocs/:/var/www/cache/:/logs/:/run/:/tmp/) in /htdocs/www/dc/master/inc/libs/clearbricks/net.http.feed/class.feed.reader.php on line 116" while reading response header from upstream, client: 88.136.16.221, server: www.stephane-huc.net, request: "GET /dc/master/admin/ HTTP/2.0", upstream: "fastcgi://unix:/run/php-fpm.sock:", host: "www.stephane-huc.net"
Vérifiez :
user
et group
écrits dans
le fichier /etc/php-fpm.d/$domain.conf
.Vous avez un message ressemblant à celui-ci :
[error] 85001#0: *47 FastCGI sent in stderr: "PHP message: PHP Warning: is_readable(): open_basedir restriction in effect. File(/var/www/cache/script.php) is not within the allowed path(s): (/htdocs/:/var/www/cache/:/logs/:/run/:/tmp/) in /htdocs/www/dc/master/inc/core/class.dc.update.php on line 75
Vérifiez :
user
et group
du fichier /etc/php-fpm.d/$domain.conf
.Vous avez un message ressemblant à celui-ci :
[error] 91433#0: *1 FastCGI sent in stderr: "PHP message: PHP Warning: require(): open_basedir restriction in effect. File(/htdocs/www/dc/master/inc/admin/prepend.php) is not within the allowed path(s): (/htdocs/www:/cache/:/logs/:/run/:/tmp/) in /htdocs/www/dc/master/admin/index.php on line 23 PHP message: PHP Fatal error: require(): Failed opening required '/htdocs/www/dc/master/admin/../inc/admin/prepend.php' (include_path='.:/pear/lib:/var/www/pear/lib') in /htdocs/www/dc/master/admin/index.php on line 23" while reading response header from upstream, client: 88.136.16.221, server: www.stephane-huc.net, request: "GET /dc/master/admin/ HTTP/2.0", upstream: "fastcgi://unix:/run/php-fpm.sock:", host: "www.stephane-huc.net"
Vérifiez :
user
et group
lié à php-fpm…array_key_exists()
: vérifie l’existence d’une clé dans un tableau !
Équivalent à la function PHP array_key_exists()
Code : bash
function array_key_exists() {
# equivalent to PHP array_key_exists
# call: array_key_exists key array
local key="$1" IFS=" "; shift; read -a array <<< "$@"
if [[ "${array[$key]}" ]]; then return 0; else return 1; fi
unset array key IFS
}
key
est la clé à rechercherhaystack
est le tableau dans lequel chercher0
pour la clé key
, si elle est trouvée dans le tableau haystack
; considérez cette valeur comme TRUE
1
: considérez cette valeur comme FALSE
Code : bash
declare -a color=("blue", "red", "green", "grey");
key=1
if array_key_exists "${key}" "${color[@]}"; then
echo "key: ${key} exists!"
else
echo "This key: ${key} not exists!"
fi
array_search()
: recherche dans un tableau la clé associée à une valeur
Équivalent à la function [PHP array_search
Code : bash
function array_search() {
# equivalent to PHP array_search
# call: array_search needle array
local needle="$1" IFS=" "; shift; read -a array <<< "$@"
for (( i=0; i < ${#array[*]}; i++ )); do
if [[ "${array[$i]}" == "${needle}" ]]; then echo "$i"; fi
done
return 1
unset array needle IFS
}
needle
est la valeur à rechercherhaystack
est le tableau dans lequel chercherneedle
, si elle est trouvée dans le tableau haystack
1
: considérez cette valeur comme FALSE
declare -a color=("blue", "red", "green", "grey");
echo "$(array_search "red" "${color[@]}")"
⇒ Accepter les connexions vers Internet (WAN ), en admettant que votre adresse ip fasse partie de la classe C, segment réseau de type 192.168.0.0 :
iptables -A OUTPUT -o eth0 -s 192.168.0.1 -m conntrack --ctstate ! INVALID -j ACCEPT
Il peut-être intéressant de la faire suivre de cette règle de rejet …
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
⇒ Si l’on est une station, refuser poliment les paquets demandant une connexion et venant d’Internet se dit ainsi :
iptables -A INPUT -i eth0 -s 0.0.0.0/0 -d 192.168.0.1 -m conntrack --ctstate NEW -j REJECT
Il peut-être intéressant de la faire précéder de cette règle iptables accepte de gèrer les connexions sortantes vers WAN …
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
L’extension multiport
d’iptables permet de spécifier une et une seule
règle pour cibler plusieurs services !
iptables -A INPUT -i eth0 -p TCP -m multiport --dports 20-22,80,443 -m conntrack --ctstate NEW -j ACCEPT
Au lieu d’écrire :
Code : sh
# autorise entree-sortie vers ssh, si est server ssh
iptables -A INPUT -i eth0 -s 192.168.0.0/24 -d 192.168.0.1 -m conntrack --ctstate ! INVALID -p TCP --dport 22 -j ACCEPT
iptables -A OUTPUT -o eth0 -s 192.168.0.1 -d 192.168.0.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -p TCP --sport 22 -j ACCEPT
# autorise entree-sortie vers DNS &lt;-&gt; LAN, si est server DNS
iptables -A INPUT -i eth0 -s 192.168.0.0/24 -d 192.168.0.1 -m conntrack --ctstate ! INVALID -p TCP --dport 53 -j ACCEPT
iptables -A OUTPUT -o eth0 -s 192.168.0.1 -d 192.168.0.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -p TCP --sport 53 -j ACCEPT
# autorise entree-sortie vers Cups &lt;-&gt; LAN, si est server Cups
iptables -A INPUT -i eth0 -s 192.168.0.0/24 -d 192.168.0.1 -m conntrack --ctstate ! INVALID -p TCP --dport 631 -j ACCEPT
iptables -A OUTPUT -o eth0 -s 192.168.0.1 -d 192.168.0.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -p TCP --sport 631 -j ACCEPT
Écrivez donc :
iptables -A INPUT -i eth0 -s 192.168.0.0/24 -d 192.168.0.1 -p TCP -m multiport --dports 22,53,631 -m conntrack --ctstate ! INVALID -j ACCEPT
iptables -A OUTPUT -o eth0 -s 192.168.0.1 -d 192.168.0.0/24 -p TCP -m multiport --sports 22,53,631 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
ip_conntrack
, et ip_conntrack_ftp
doivent être chargés !iptables -A OUTPUT -o eth0 -p tcp --sport 1024: -m conntrack --ctstate ! INVALID -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 1024: -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
Exemple de règles pour gèrer les connexions en mode FTP actif avec Iptables :
iptables -A OUTPUT -o eth0 -p tcp -m multiport --sports 20,21 -m conntrack --ctstate ! INVALID -j ACCEPT
iptables -A INPUT -i eth0 -p tcp -m multiport --dports 20,21 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
Une des attaques possible est de saturer votre interface réseau par un nombre conséquent de connexions ou tentatives de connexion dans un espace de temps très restreint.
Pour éviter de saturer l’interface réseau, on utilise une technique limitant le nombre de connexions au-delà desquelles toute autre tentative sera rejetée.
⇒ TCP Syn flood :
iptables -A INPUT -i eth0 -p tcp --syn -m limit --limit 3/s -j ACCEPT
⇒ UDP Syn flood :
iptables -A INPUT -i eth0 -p udp -m limit --limit 10/s -j ACCEPT
--syn
après le protocole udp
, sachez que ce flag n’existe pas pour le protocole udp.⇒ Ping flood :
iptables -A INPUT -i eth0 -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
iptables -A INPUT -i eth0 -p icmp --icmp-type echo-reply -m limit --limit 1/s -j ACCEPT
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
⇒ Règle simple, juste pour le protocole tcp :
iptables -A INPUT -i eth0 -d 192.168.0.1 -p tcp -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -S 192.168.0.1 -p tcp -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
⇒ Règle plus évoluée, pour les protocoles icmp, tcp et udp :
iptables -A INPUT -p tcp ! --syn -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp -m conntrack --ctstate RELATED -j ACCEPT
iptables -A INPUT -p udp -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A INPUT -p icmp -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
iptables -A OUTPUT -p tcp ! --syn -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -m conntrack --ctstate RELATED -j ACCEPT
iptables -A OUTPUT -p udp -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p icmp -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
Eh, oui, lorsqu’on utilise des comptes utilisateurs sur un ordinateur/serveur avec un “/home” chiffré… Adieu la connexion SSH avec les clés d’authentification !
Mais non… nous allons remédier à la situation.
Le plus simple est de créer un répertoire hors votre Home chiffré, tel
que $HOME/.ssh/$USER
. Ce dernier peut être absolument ailleurs, tel
que dans /etc/ssh
… pourvu qu’il soit lisible hors chiffrement du
répertoire Home.
Code :
# mkdir -p /home/.ssh/USER
# chown -R USER:USER /home/.ssh/USER
# chmod 0700 /home/.ssh/USER
Bien sûr vous remplacez la mention USER
par l’identifiant utilisateur
désiré.
Puis vous créez avec vos droits utilisateurs un fichier nommé
authorized_keys
où vous copiez votre clé d’authentification SSH, de
préférence ED25519.
N’oubliez pas de mettre des droits minimum dessus, tel que :
$ chmod 0600 /home/.ssh/USER/authorized_keys
Maintenant, il faut modifier le fichier de configuration du serveur SSH,
à savoir /etc/ssh/sshd_config
, pour modifier la ligne
AuthorizedKeysFiles
de telle manière :
# sed -i -e "s#AuthorizedKeysFile %h/.ssh/authorized_keys#AuthorizedKeysFile /home/.ssh/%u/authorized_keys#" /etc/ssh/sshd_config
Vérifiez les droits d’accès et d’appartenances utilisateurs !
Ou, par tout autre moyen de votre crû, avec des droits administrateurs, bien sûr !
Puis, relancez le service ssh ;-)
Et, voilà !
Permettre à l’interface locale de discuter est important !
⇒ Autorise la connexion sur l’interface locale :
iptables -A INPUT -i lo -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
iptables -A OUTPUT -o lo -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT
⇒ règle simpliste :
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
Il existe un type de scan de port, dit XMAS et NULL ; pour s’en protéger :
iptables -A INPUT -p tcp --tcp-flags FIN,URG,PSH FIN,URG,PSH -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
⇒ Règle simpliste :
iptables -A OUTPUT -o eth0 -p icmp -m conntrack --ctstate ! INVALID -j ACCEPT
iptables -A INPUT -i eth0 -p icmp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
⇒ Règles plus fines :
Code : sh
iptables -A INPUT -p icmp -m icmp --icmp-type0 -m conntrack --ctstate ESTABLISHED -j ACCEPT -m comment --comment "ICMP Echo reply"
iptables -A INPUT -p icmp -m icmp --icmp-type3/0 -m conntrack --ctstate RELATED -j ACCEPT -m comment --comment "ICMP Destination Net Unreachable"
iptables -A INPUT -p icmp -m icmp --icmp-type3/1 -m conntrack --ctstate RELATED -j ACCEPT -m comment --comment "ICMP Destination Host Unreachable"
iptables -A INPUT -p icmp -m icmp --icmp-type8 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT -m comment --comment "ICMP Echo mssg"
iptables -A INPUT -s adr_ip_gw -p icmp -m icmp --icmp-type9 -m conntrack --ctstate RELATED -j ACCEPT -m comment --comment "ICMP Router Advert"
iptables -A INPUT -s adr_ip_gw -p icmp -m icmp --icmp-type10 -m conntrack --ctstate NEW -j ACCEPT -m comment --comment "ICMP Router Select"
iptables -A INPUT -p icmp -m icmp --icmp-type11 -m conntrack --ctstate RELATED -j ACCEPT -m comment --comment "ICMP Time exceeded"
iptables -A INPUT -p icmp -m icmp --icmp-type12 -m conntrack --ctstate RELATED -j ACCEPT -m comment --comment "ICMP Param pb"
iptables -A INPUT -p icmp -m icmp --icmp-type13 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT -m comment --comment "ICMP Timestamp mssg"
iptables -A INPUT -p icmp -m icmp --icmp-type14 -m conntrack --ctstate ESTABLISHED -j ACCEPT -m comment --comment "ICMP Timestamp reply"
iptables -A INPUT -p icmp -m icmp --icmp-type17 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT -m comment --comment "ICMP Addr Mask mssg"
iptables -A INPUT -s adr_ip_gw -p icmp -m icmp --icmp-type18 -m conntrack --ctstate ESTABLISHED -j ACCEPT -m comment --comment "ICMP Addr Mask reply"
iptables -A INPUT -p icmp -m icmp --icmp-type30 -m conntrack --ctstate NEW,RELATED -j ACCEPT -m comment --comment "ICMP Traceroute"
iptables -A OUTPUT -p icmp -m icmp --icmp-type0 -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p icmp -m icmp --icmp-type3/0 -m conntrack --ctstate RELATED -j ACCEPT
iptables -A OUTPUT -p icmp -m icmp --icmp-type3/1 -m conntrack --ctstate RELATED -j ACCEPT
iptables -A OUTPUT -p icmp -m icmp --icmp-type8 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -d adr_ip_gw -p icmp -m icmp --icmp-type9 -m conntrack --ctstate RELATED -j ACCEPT
iptables -A OUTPUT -d adr_ip_gw -p icmp -m icmp --icmp-type10 -m conntrack --ctstate NEW -j ACCEPT
iptables -A OUTPUT -p icmp -m icmp --icmp-type11 -m conntrack --ctstate RELATED -j ACCEPT
iptables -A OUTPUT -p icmp -m icmp --icmp-type12 -m conntrack --ctstate RELATED -j ACCEPT
iptables -A OUTPUT -p icmp -m icmp --icmp-type13 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p icmp -m icmp --icmp-type14 -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p icmp -m icmp --icmp-type17 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -d adr_ip_gw -p icmp -m icmp --icmp-type18 -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p icmp -m icmp --icmp-type30 -m conntrack --ctstate NEW,RELATED -j ACCEPT
Je vous invite très fortement à lire ATTENTIVEMENT sur le filtrage d’ICMP sous Linux : Linux : firewall ICMP
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
La RFC 1918 nous fait comprendre que les adresses de type privé ne doivent pas être publié sur Internet. De fait, puisque nul ne doit contacter l’interface réseau internet, il est bon de dropper tout flux qui y correspond !
La RFC 5735 définit l’ensemble des réseaux dits spécifiques, qu’il est bon de ne pas retrouver sur Internet !
Code : sh
iptables -A INPUT -i eth0 -s 0.0.0.0/8 -j DROP
iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP # adr Class A privee
iptables -A INPUT -i eth0 -s 100.64.0.0/10 -j DROP # définit par la RFC 6598
iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j DROP # adr de Loopback
iptables -A INPUT -i eth0 -s 169.254.0.0/16 -j DROP # adr Link Local Network
iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP # adr Class B privee
iptables -A INPUT -i eth0 -s 192.0.0.0/24 -j DROP
iptables -A INPUT -i eth0 -s 192.0.2.0/24 -j DROP # adr TEST-NET
iptables -A INPUT -i eth0 -s 192.88.99.0/24 -j DROP
iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP # adr Class C Privee
iptables -A INPUT -i eth0 -s 198.18.0.0/15 -j DROP
iptables -A INPUT -i eth0 -s 198.51.100.0/24 -j DROP
iptables -A INPUT -i eth0 -s 203.0.113.0/24 -j DROP
iptables -A INPUT -i eth0 -s 224.0.0.1/4 -j DROP # adr Class D MultiCast
iptables -A INPUT -i eth0 -s 240.0.0.0/4 -j DROP # adr Class E Reservee
iptables -A INPUT -i eth0 -s 255.255.255.255 -j DROP # aucun flux ne doit être de source avec l'adressage de loopbak...
iptables -A OUTPUT -o eth0 -d 0.0.0.0/8 -j DROP
iptables -A OUTPUT -o eth0 -d 10.0.0.0/8 -j DROP # adr Class A privee
iptables -A OUTPUT -o eth0 -d 100.64.0.0/10 -j DROP # définit par la RFC 6598
iptables -A OUTPUT -o eth0 -d 127.0.0.0/8 -j DROP # adr de Loopback
iptables -A OUTPUT -o eth0 -d 169.254.0.0/16 -j DROP # adr Link Local Network
iptables -A OUTPUT -o eth0 -d 172.16.0.0/12 -j DROP # adr Class B privee
iptables -A OUTPUT -o eth0 -d 192.0.0.0/24 -j DROP
iptables -A OUTPUT -o eth0 -d 192.0.2.0/24 -j DROP # adr TEST-NET
iptables -A OUTPUT -o eth0 -d 192.88.99.0/24 -j DROP
iptables -A OUTPUT -o eth0 -d 192.168.0.0/16 -j DROP # adr Class C Privee
iptables -A OUTPUT -o eth0 -d 198.18.0.0/15 -j DROP
iptables -A OUTPUT -o eth0 -d 198.51.100.0/24 -j DROP
iptables -A OUTPUT -o eth0 -d 203.0.113.0/24 -j DROP
iptables -A OUTPUT -o eth0 -d 224.0.0.1/4 -j DROP # adr Class D MultiCast
iptables -A OUTPUT -o eth0 -d 240.0.0.0/4 -j DROP # adr Class E Reservee
iptables -A OUTPUT -o eth0 -d 255.255.255.255 ! -p icmp -j DROP # aucun flux ne doit être à destination avec l'adressage de loopbak, sauf sur le protocole ICMP...
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
Le projet Perishable Press 6G est un projet de règles de filtrage
pour le serveur Apache, version 2 de préférence, à utiliser dans le
fichier .htaccess
.
Personnellement, j’avoue préférer nginx.
Je rappelle que les règles .htaccess n’existent pas pour nginx, même si on peut recréer le principe, de manière différente !
Donc, j’ai eu l’idée de convertir ces règles de filtrage et autres blacklistages pour l’intégrer à l’usage que j’ai de nginx.
À moins que je ne me trompe, cela devrait donner ce qui suit ci-dessous :
Dans le fichier de configuration du domaine à gérer, contexte server
:
Code : nginx
# 6G Perishable Press: Queries String
# @ https://perishablepress.com/6g/
location ~* "(eval\()" { return 444; }
location ~* "(127\.0\.0\.1)" { return 444; }
location ~* "([a-z0-9]{2000})" { return 444; }
location ~* "(javascript\:)(.*)(\;)" { return 444; }
location ~* "(base64_encode)(.*)(\()" { return 444; }
location ~* "(GLOBALS|REQUEST)(=|\[|%)" { return 444; }
location ~* "(<|%3C).*script.*(>|%3)" { return 444; }
location ~* "(\|\.\.\.|\.\./|~|`|<|>|\|)" { return 444; }
location ~* "(boot\.ini|etc/passwd|self/environ)" { return 444; }
location ~* "(thumbs?(_editor|open)?|tim(thumb)?)\.php" { return 444; }
location ~* "(\'|\")(.*)(drop|insert|md5|select|union)" { return 444; }
Si jamais vous utilisez le plugin TimTumb, il vous faudra commenter la ligne suivante :
location ~* "(thumbs?(_editor|open)?|tim(thumb)?)\.php" { return 444; }
Toujours dans le contexte server
, utilisons la capacité native de nginx,
si la connexion n’est pas de type GET, ou HEAD, alors bloquons le flux :
Code : nginx
if ($request_method !~ ^(GET|HEAD)$ ) { return 444; }
Pour ceux qui utilisent un serveur de nuage informatique, tel que Nextcloud,
ajoutez au moins la méthode PUT
, tel que :
if ($request_method !~ ^(GET|HEAD|PUT)$ ) { return 444; }
Si vous avez dans votre site, des pages qui ont des formulaires qui envoient
les données par la requête POST, ajoutez la dans la déclaration ci-dessus,
tel que :
if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 444; }
Pour ce filtrage, utilisons la déclaration map
, dans le contexte http
du serveur :
Code : nginx
# @ https://perishablepress.com/6g/
map $http_referer $bad_referer {
default 0;
~*\{.*\: 1; # ShellShock
#~([a-z0-9]{2000}) 1;
~(?i)(semalt.com|todaperfeita) 1;
La règle ~([a-z0-9]{2000}) 1;
est mis en commentaire - je n’ai pas encore
trouvé comment faire pour l’inclure sans retour d’erreur !
Puis, rajouter dans le contexte server
ladite déclaration :
Code : nginx
if ($bad_referer) { return 444; }
Les filtres sur les requêtes sont toutes aussi simples que celles sur les
queries
… de type location
, dans le
contexte server
:
Code : nginx
# 6G Perishable Press : Request String
# @ https://perishablepress.com/6g/
location ~* "(https?|ftp|php):/" { return 444; }
location ~* "(=\\'|=\%27|/\\'/?)\." { return 444; }
location ~* "/(\$(\&)?|\*|\"|\.|,|&|&amp;?)/?$" { return 444; }
location ~* "(\{0\}|\(/\(|\.\.\.|\+\+\+|\\"\\")" { return 444; }
location ~* "(~|`|<|>|:|;|,|%|\|\s|\{|\}|\[|\]|\|)" { return 444; }
location ~* "/(=|\$&|_mm|(wp-)?config\.|cgi-|etc/passwd|muieblack)" { return 444; }
location ~* "(&pws=0|_vti_|\(null\)|\{\$itemURL\}|echo(.*)kae|etc/passwd|eval\(|self/environ)" { return 444; }
location ~* "\.(aspx?|bash|bak?|cfg|cgi|dll|exe|git|hg|ini|jsp|log|mdb|out|sql|svn|swp|tar|rar|rdf)$" { return 444; }
location ~* "/(^$|mobiquo|phpinfo|shell|sqlpatch|thumb|thumb_editor|thumbopen|timthumb|webshell)\.php" { return 444; }
Pour ceux qui utilisent un service CGI, supprimez la mention cgi-|
de la
ligne suivante :
location ~* "/(=|\$&|_mm|(wp-)?config\.|cgi-|etc/passwd|muieblack)" { return 444; }
Là encore, utilisons l’astuce de la déclaration map
, dans le contexte http
:
Code : nginx
# @ https://perishablepress.com/6g/
map $http_user_agent $bad_bot {
default 0;
~*\{.*\: 1; # ShellShock
#~(?i)([a-z0-9]{2000}) 1;
~(?i)(archive.org|binlar|casper|checkpriv|choppy|clshttp|cmsworld|diavol|dotbot|extract|feedfinder|flicky|g00g1e|harvest|heritrix|httrack|kmccrew|loader|miner|nikto|nutch|planetwork|postrank|purebot|pycurl|python|seekerspider|siclab|skygrid|sqlmap|sucker|turnit|vikspider|winhttp|xxxyy|youda|zmeu|zune) 2;
Puis écrivons dans le contexte server
:
Code : nginx
if ($bad_bot) { return 444; }
Et, voilà !
PS : Pensez à redémarrer le serveur nginx, après avoir lancé le test de la config !
Partager une connexion sous linux est assez simple…
⇒ Dans un premier temps, il faut autoriser la redirection d’IP, avec des droits administrateur :
# echo 1 > /proc/sys/net/ipv4/ip_forward
⇒ Ensuite autoriser la redirection avec iptables
Avec une adresse ip extérieur statique :
iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to 1.2.3.4
où
l’adresse IP 1.2.3.4
est à remplacer par votre réelle adresse IP extèrieure.
Avec une adresse ip extérieur dynamique :
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
⇒ Ajouter à votre fichier /etc/sysctl.conf
:
net.ipv4.ip_forward=1
iptables -A FORWARD -i eth0 -o ppp0 -s 192.168.0.0/24 -m conntrack --ctstate ! INVALID -j ACCEPT
iptables -A FORWARD -i ppp0 -o eth0 -d 192.168.0.0/24 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -o ppp0 -s 192.168.0.0/24 -j MASQUERADE
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
Sur une Debian GNU/Linux, ou une *Buntu, et autre dérivées :
apt install ssh
…
Quelle que soit la distribution Linux utilisé, le fichier de
configuration se trouve être /etc/ssh/sshd_config*
.
Sur OpenBSD, c’est installé dans le système de base !
SSH est très facile à utiliser :
ssh server.domaine.com
ou ssh adresse_ip
est la méthode de base.
Dans ce cas, si la connexion se fait, il vous sera demandé votre nom d’utilisateur sur ce serveur, et le mot de passe correspondant.
ssh votre_nom_user@server.domaine.com
ou
ssh -l votre_nom_user server.domaine.com
est la manière de spécifier
explicitement votre nom d’utilisateur.
Dans ce cas, dès la connexion établie, il ne vous sera demandé plus que le mot de passe correspondant à votre identifiant utilisateur.
Il suffit d’établir une connexion avec la commande à lancer :
ssh votre_nom_user@server.domaine.com date
Précisément, cette commande interroge le serveur pour connaître ses date et heure.
C’est la commande scp
, tout autant sécurisée, qui le permet aussi
simplement.
scp monfichier votre_nom_user@server.domaine.com:/~/
enverra le
fichier dans votre répertoire personnel sur le serveur en question.
scp votre_nom_user@server.domaine.com:/~/monfichier monfichier
ira
chercher sur le serveur votre fichier et le déposera dans votre
répertoire en cours.
Pour faire une copie récursive d’un répertoire :
ssh -r /votre_rep votre_nom_user@server.domaine.com:/~/
Le transfert de fichiers par ftp, de manière sécurisée, est aussi possible…
Utilisez la commande suivante : sftp votre_nom_user@server.domaine.com
Certains clients FTP graphique acceptent ce mode de connexion, il suffit de choisir le mode de connexion sftp over SSH2.
OpenSSH permet des méthodes diverses d’authentification, et ce en fonction de la politique de sécurité privilégiée.
PermitRootLogin
en lui donnant la valeur no.2
(version de protocole plus sécurisée)PasswdAuthentication
soit à yes
et que PermitEmptypasswords
soit à no
.PubkeyAuthentication
à yes
et supprimer le symbole dièze devant la ligne AutorizedKeysFile
.RSAAuthentication
, RhostsAuthentication
, RhostsRSAAuthentication
et HostbasedAuthentication
la valeur no
et d’ignorer IgnoreRhosts
par yes
, si elles sont présentes dans le fichier !AllowUsers
et AllowGroups
que l’on ajoutera au fichier de configuration.Une fois le fichier sshd_config
modifié, pensez donc à
(re)démarrer le service :
/etc/init.d/sshd restart
ou service ssh restart
L’usage de clé publique ayant été notifié dans le fichier de
configuration et aux utilisateurs,il est possible de les créer par la
commande suivante ssh-keygen
.
ssh-keygen -t rsa -b 2048
ATTENTION : Il est recommandé les deux choses suivantes :
Pour plus d’informations, veuillez lire mon autre article
Lors de la génération de celle-ci, il vous sera demandé de taper une passphrase que vous choisirez consciencieusement.
Dans un cas, comme dans l’autre, cela crée une clé privée et une clé
publique dans votre répertoire personnel $HOME/.ssh/
; pour les
clés RSA, ce sont les fichiers id_rsa et id_rsa.pub,
et réciproquement pour les autres clés.
Veillez à ne jamais fournir la clé privée, et ce sous aucun prétexte. Votre sécurité en dépend fortement !
Une fois, vos clés générées, copiez votre clé publique sur le serveur :
scp -p $HOME/.ssh/id_rsa.pub votre_nom_user@server.domaine.com:/~/.ssh/authorized_keys
Ensuite on va garder en mémoire la passphrase dans notre ordinateur afin
de ne pas être obligé de la taper à chaque fois :
eval ssh-agent ssh-add
Pour la dernière fois, il va vous être demandé de taper votre passphrase, faites-le.
Lors de vos prochaines connexions en SSH sur le serveur, il ne vous restera plus… qu’à travailler !
Pour créer un tunnel de connexion ssh, qui permette d’encapsuler
d’autres protocoles, il vous faut vous l’écrire ainsi :
ssh -L numero_port_encapsulé:adresse_ip_local:numero_port_routé adresse_ip_server
-L
indique l’exécution locale,-R
indique l’exécution à distance.Pour créer un tunnel graphique X-Windows, il faut d’abord vérifier que
l’option X11 Forwarding
soit à yes
dans le fichier
/etc/ssh/sshd_config
.
Cela étant fait, il ne vous reste plus qu’à vous connecter à votre hote
distant : ssh -X nom_machine.nom_domaine.tld
Il est possible de lancer en même temps une application :
ssh -X nom_machine.nom_domaine.tld nom_logiciel &
Ce mémo a été écrit la première fois, par mes soins, sur mon autre site “Mémoire Grise Libérée”.
⇒ Demander à iptables d’accepter tout le trafic de votre ip vers votre lan, en admettant que vos machines soient sur un réseau de classe C, dont le segment est 192.168.0.0 :
iptables -A OUTPUT -o eth0 -s 192.168.0.1 -d 192.168.0.0 / 24 -m conntrack --ctstate ! INVALID -j ACCEPT
iptables -A INPUT -i eth0 -s 192.168.0.0 / 24 -d 192.168.0.1 -m conntrack --ctstate ! INVALID -j ACCEPT
⇒ Accepter le flux de type broadcast :
iptables -A OUTPUT -o eth0 -s 192.168.0.1 -d 192.168.0.255 -m conntrack --ctstate ! INVALID -j ACCEPT
iptables -A INPUT -i eth0 -s 192.168.0.255 -d 192.168.0.1 -m conntrack --ctstate ! INVALID -j ACCEPT
⇒ Accepter le flux BootDHCP vers LAN :
iptables -A INPUT -i eth0 -p udp --sport bootpc --dport bootps -m conntrack --ctstate NEW -j ACCEPT
J’ai écrit ce mémo, pour la première fois, sur mon autre site : “Mémoire Grise Libérée”.
Ou, comment titrer : Améliorons l’intégrité du noyau en désactivant la gestion des modules !
En effet, pour améliorer l’intégrité du noyau, il est possible, même recommandé, de désactiver la gestion des modules ; cela a pour propos d’empêcher que quiconque ayant un accès machine puisse charger un module indésirable.
Gardez à l’esprit que si vous désactivez la gestion des modules, cela risque de vous poser des problèmes de gestion matérielle sur une station… Exemple : impossible d’utiliser des périphériques USB.
Préférez utiliser cela sur un serveur.
Vous êtes prévenus !
Le sous-système sysctl
nous permet d’activer ou de désactiver la gestion
des modules par la variable kernel.modules_disabled
.
0
permet la gestion des modules,1
désactive la gestion des modules !De même, il est possible, bien-sûr, de le gérer à-partir du fichier /etc/sysctl.conf
.
Votre système d’exploitation fonctionnera, certes, mais seulement en partie ! Bref, il faut avouer : c’est assez ennuyeux, voire ennuyant…
L’astuce est de configurer le fichier /etc/rc.local
- qui est appelé
en dernier au chargement du système, du moins sur Debian et *Buntu - en incluant la commande suivante :
sysctl -w kernel.modules_disabled=1
mais de laisser la valeur de cette variable à 0
dans le fichier de configuration
de sysctl !
Ainsi le système au démarrage chargera tous les modules nécessaires à son bon fonctionnement, et ensuite, interdira tout autre chargement de modules non autorisé !
Tout bon linuxien sait que le partitionnement système se gère à partir du
fichier /etc/fstab
…
Modifions la configuration par défaut, qui utilise le drapeau defaults
concernant l’option de montage, pour être plus restrictif…
ce qui aura pour avantage de compliquer la vie si jamais votre station ou serveur étaient infectés !
Concernant le partitionnement lié à /boot
, /opt
, /usr
, il est
intéressant de les monter en lecture seule et d’interdire les fichiers
périphériques nommés device, pour un serveur -
sur une station, cela posera des difficultés ergonomiques indéniables.
Ce qui donnerait à minima :
UUID=97aabf8d-fa78-4176-b681-888370fbc186 /boot ext4 defaults,nodev,ro 0 2
UUID=20c0ddea-2db4-4ee5-982f-71b8df26c2fb /opt ext4 defaults,nodev,ro 0 2
UUID=d84f16a8-d107-49d7-992d-bd9e78488ffd /usr ext4 defaults,nodev,ro 0 2
defaults
, soit rw,suid,dev,exec,auto,nouser,async
,
on peut donc écrire les options defaults,nodev,ro
par async,auto,exec,nodev,nouser,ro,suid
!ro
sur les partitionnements /boot
et sur /usr
posent quelques petits soucis./opt
, pour les rares fois, où c’est vraiment nécessaire, on
verra plus bas comment permettre l'écriture
, si besoin.⇒ /boot
: besoin d’un accès en écriture, lors du démarrage, pour l’environnement
lié à grub, et surtout du binaire grub-editenv
… qui ne peut écrire
de fait ; résultat, il faut réécrire le fichier /etc/fstab
avec
l’option rw
.
Ouvrez le fichier /etc/rc.local
- du moins, pour Debian, *Buntu,
et assimilés - et écrivez dedans :
mount -f -o remount,ro /boot
⇒ /usr
: besoin d’un accès en écriture, lors de mises-à-jour système,
principalement. Vous aurez le droit à la complainte suivante lors de
l’exécution de l’invocation post du gestionnaire de paquets (apt,
dpkg, etc.) :
mount: /usr: point de montage actif.
E: Problem executing scripts DPkg::Post-Invoke 'mount -o remount,ro /usr'
E: Sub-process returned an error code
Ce n’est absolument rien de grave ; il vous avertit juste qu’il n’est
pas capable de remonter /usr
en lecture seule. À vous de voir si vous
voulez vraiment mettre /usr
en lecture seule, et que ce message d’erreur
ne vous ennuie pas ; pour ne pas être embetter, mieux vaut laisser en rw
.
Pour résoudre les problèmes ci-dessus, soit vous éditez le fichier /etc/apt/apt.conf
-
s’il existe - soit vous créez un fichier, tel que /etc/apt/apt.conf.d/00apt
,
et écrivez le code suivant :
DPkg::Pre-Invoke {"mount -o remount,rw /boot";"mount -o remount,rw /opt"};
DPkg::Post-Invoke {"mount -o remount,ro /boot";"mount -o remount,ro /opt"};
Ainsi les gestionnaires apt, dpkg doivent remonter les partitionnements en question en écriture avant de faire la mise-à-jour système, et de le remettre en lecture seulement, après…
Pour info, la documentation de l’ANSSI en Octobre 2015, à-propos de configurer Linux de manière sécurisée, informe que :
/boot
devrait avoir les options nosuid,nodev,noexec
- il est même
recommandé l’usage de l’option noauto
de manière optionnelle, car
cela sous-tend qu’il faut comprendre les incidences et la gestion
générée d’ajouter cette dernière option !/opt
devrait avoir au moins les options nosuid,nodev
/usr
devrait avoir l’option, à minima, nodev
Il peut arriver que certains logiciels refusent de fonctionner. Réflexe : exécutez-le depuis un terminal, et vérifiez son chemin d’exécution.
/opt
: google-chrome nécessite pour sa sandbox l’usage de l’option suid
.Occupons nous du partitionnement lié à /tmp
, et déclarons l’option la
plus importante, dans ce cas noexec
, parce que nous ne voulons pas que
n’importe qui se serve de ce répertoire pour lancer n’importe quoi :
UUID=1a7a999d-1e26-45f7-96c0-7d381887350d /tmp ext4 defaults,nodev,noexec,nosuid 0 2
Le problème principal est le même que pour les options sur les partitionnements
/boot
, et /usr
, en mettant l’option noexec
, lors des mises-à-jours
systèmes ou de l’installation d’un nouveau logiciel, cela ne pourra pas
s’exécuter correctement !
Il faut pour cela rajouter dans les invocations pre et post en
demandant de remonter le partitionnement /tmp
avec les droits exec
,
puis à les enlever après le traitement.
DPkg::Pre-Invoke {"mount -o remount,rw /boot";"mount -o remount,rw /opt";"mount -o remount,exec /tmp"};
DPkg::Post-Invoke {"mount -o remount,ro /boot";"mount -o remount,ro /opt";"mount -o remount,noexec /tmp"};
La documentation ANSSI sur la configuration Linux recommande les options
nosuid,nodev,noexec
pour la partition /tmp
…
Et les partitions /var
, /var/log
, /var/tmp
?
/var
: On peut rajouter les options grpquota,nodev,usrquota
…UUID=e47dcfed-0d0a-486f-8f1c-63f9e8132590 /var ext4 defaults,grpquota,nodev,usrquota 0 2
Quant au répertoire /var/tmp
, il est intéressant de le supprimer, puis
de le lier vers le répertoire ou la partition /tmp
, qui sera ainsi bien gérée.
rm -rf /var/tmp
ln -s /tmp /var/tmp
La documentation ANSSI sur la configuration Linux recommande les options
nosuid,nodev,noexec
pour toutes les partitions /var
, /var/log
,
/var/tmp
…
noexec
sur la partition /var
, qui empêchera la création de répertoires et fichiers
temporaires lors des mises-à-jours, par exemple !Il est de bon ton, en terme de sécurité système, d’empêcher l’usage de dev pour la racine système :
UUID=7b8b0d04-7d60-44dd-98f3-6134065a42c3 / ext4 errors=remount-ro,nodev 0 1
Cette partition, dont le but actuel, est de “cloisonner” des services serveurs, tels que web, base de données, a aussi sa propre recommandation de la part de l’ANSSI :
nosuid,nodev
et de manière optionnelle, si vous savez gèrer,
les options noexec,ro
… il est clair que l’option ro
pose son lot de problèmes, ne serait-ce
que pour certains sites web qui ont besoin au moins d’un répertoire où écrire…
à moins que vous redirigez ce genre d’écritures !L’ANSSI recommande les options nosuid,nodev,noexec
…
~/bin
qui, dans les distributions telles que Debian, Ubuntu, (et assimilées),
est inclus dans la variable d’environnement PATH
, puisque l’option noexec
vous empêchera d’exécuter tout binaire, même vos personnels !shm est l’accronyme de shared memory ; en doux français : mémoire partagée.
Sécuriser le point de montage correspondant est intéressant, afin d’empêcher l’attaque contre certains services par ce biais, tel que celui d’un serveur web, par exemple.
Si vous avez le répertoire /run/shm
, configurez le fichier /etc/fstab
, ainsi :
tmpfs /run/shm tmpfs defaults,nodev,noexec,nosuid 0 0
Si vous n’avez que /dev/shm
, qui normalement ne pointe pas vers /run/shm
,
modifiez /etc/fstab
en remplaçant /run/shm
, par /dev/shm
.
Bon, comme vous avez certainement dû le comprendre, pour remonter dynamiquement un partitionnement, sans avoir à redémarrer le système, on utilise la commande suivante - avec les droits administrateurs, bien sûr - :
# mount -o remount,options /nom_partition
Et si vous avez le droit à une erreur, telle que /partitionnement busy
,
préférez redémarrer la machine !
Un exemple de fichier /etc/apt/apt.conf.d/00apt
modifié selon les recommandations
ci-dessus :
Fichier : /etc/apt/apt.conf.d/00apt
|
|
Un exemple de fichier /etc/fstab
modifié selon les recommandations ci-dessus :
Fichier : /etc/fstab
|
|
Si Korben nous informe du comment bloquer certaines attaques pour et par le serveur web Nginx - sa manière de le faire n’est pas forcément des meilleures !
Utilisons le contexte location
, et écrivons-les ainsi :
Code : nginx
## Block Queries
location ~ "(\"|%22).*(<|>|%3)" { return 403; }
location ~ "(javascript\:).*(\;)" { return 403; }
location ~ "(\|\.\./|`|=\'$|=%27$)" { return 403; }
location ~ "(\;|\'|\"|%22).*(union|select|concat|insert|drop|update|md5|benchmark|or|and|if)" { return 403; }
location ~ "(<|%3C).*script.*(>|%3)" { return 403; }
location ~ "[a-zA-Z0-9_]=http://" { return 403; }
location ~ "[a-zA-Z0-9_]=(\.\.//?)+" { return 403; }
location ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+" { return 403; }
location ~* ".*(asp|bs)$" { return 403; }
location ~* ".*(admin|cgi|manager|pma|user|wp|wordpress).*" { return 403; }
location ~ "^base64_(en|de)code\(.*\)|localhost|mosconfig" { return 403; }
Au lieu de retourner une erreur 403, informant que la requête est valide, mais refusée par le serveur, préférez retourner une erreur 444 - où le serveur refuse d’envoyer toute information, et ferme la connexion directement !
c’est cela aussi le pouvoir tant réputé de nginx ;-)
2020 : Cette manière de faire est obsolète… veuillez plutôt consulter mon article
Apt : Ajouter une clé GPG
!!!
Un petit script bash pour aider à résoudre simplement l’erreur gpg liée à la mise-à-jour des dépôts debian, ubuntu…
Ce script, très simple, permet de lancer la suite de commande gpg nécessaire à ajouter pour que les dépôts ne retournent pas cette erreur :
Citation :
W: GPG error: ftp://ftp.domain.org testing Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 010203040A0B0C0D W: There is no public key available for the following key IDs: 010203040A0B0C0D
La solution :
Fichier : gpg-apt-add.sh
|
|
Le propos de cet article est d’aider à comprendre ce qu’il faut configurer pour obtenir une configuration sécurisée de votre client SSH.
Cela nécessite que votre version du client OpenSSH soit supérieure à la version 6.5 !
Côté client, le plus simple est de modifier votre fichier de
configuration, dans votre home personnel, ~/.ssh/config
…
Cet article n’aborde que la partie concernant le client ; pour la partie serveur, merci de lire mon autre article : OpenSSH : Durcir la configuration du serveur SSH
Les algorithmes de Chiffrement à autoriser :
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
Néanmoins, sachez que dans certains cas, tels que Filezilla, Putty,
il vous faudra certainement ajouter l’un des trois paramètres suivants :
aes256-ctr,aes192-ctr,aes128-ctr
Si le serveur sur lequel vous cherchez à vous connecter est dropbear,
il vous sera nécessaire d’ajouter : aes256-ctr
- à définir dans une
configuration personnalisée…
À vérifier au cas par cas… regardez donc le log d’authentification sur votre serveur !
Les algorithmes des clés d’échange à privilègier sont :
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
Les recommandations actuelles pour les algorithmes des clés d’hôte sont :
HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com
Perso, je n’utilise QUE : HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-ed25519
ssh-rsa
- à définir dans une
configuration personnalisée…Les algorithmes des Code d’Authentification de Messages à définir sont :
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
Perso, je n’utilise plus QUE : MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-512
hmac-sha2-256
- à définir dans une
configuration personnalisée…Voici un exemple de configuration sécurisée minimal :
Fichier : ~/.ssh/config
|
|
Selon le manpage officiel, les configurations personnalisées à certains
hôtes doivent être écrites avant la configuration générale Host *
!
Les créations suivantes sont à faire côté client, bien sûr !
ssh-keygen -o -p -f id_rsa -a 64
-f
spécifie le fichier de clé privée à utiliser.-o
est celle qui utilise le durcissement PKBDF.-a
définit le nombre de tours “de moulinettes” que va effectuer la génération.16
.
Vous pouvez lui demander 1000
tours, néanmoins pour les paranoïaques
la valeur de 64
semble préférable ET suffisante.-o
; en effet,
la génération des clés Ed25519 utilise toujours ce format par défaut !ssh-keygen -t ed25519 -f fichier_id -a nb_tours
Tel que, par exemple :
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -a 64
ssh-keygen -t rsa -b nb_bits -f fichier_id -o -a nb_tours
Tel que, pour l’exemple :
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -o -a 64
Si vous avez paramétré l’option LoginGraceTime
sur le serveur, pensez à
augmenter sa valeur, sinon vous aurez le droit à ne pas
pouvoir vous connecter, sans aucun message d’erreur dans le log
d’authentification.
En effet, selon le nombre de tours que vous avez paramétrés pour la génération de votre clé, ou sa mise-à-jour, le déchiffrement et la réponse du serveur prendra plus de temps, peut-être plus que le temps d’ouverture, de la fenêtre de connexion, autorisé.
Je mets à disposition mon script shell de génération de clés, basé sur lesdites informations…
Vous avez le message d’erreur en titre, avec Filezilla :
SFTP Connection closed by server with exitcode 10
Ouvrez le Gestionnaire de Sites, Onglet “Paramètres de transfert”, cliquez
sur la case à cocher [ ] Limiter le nombre de connexions simultanées
pour la paramétrer à 1
*.
Validez et connectez-vous à nouveau !
* ou selon votre configuration SSH, voire MySecureShell - Option LimitConnectionByUser
Une petite astuce relative à nginx, afin de bloquer l’exécution de scripts, dans les répertoires où vous ne désirez pas qu’ils s’exécutent, tels que ASP, PHP, Shell, etc :
Code : nginx
location ~* /(repertoire1|repertoire2|repertoire_xyz|image|css|js)/.*.(asp|cgi|jsp|php|pl|py|sh)$ {
return 403;
}
Bloquer un UA n’est pas bien difficile avec nginx !
Utilisons le module map
dans le contexte http
, tel que :
Code : nginx
map $http_user_agent $bad_bot {
default 0;
~(?i)(""|Curl|Wget) 1;
}
Dans le fichier de configuration, lié à votre domaine, rajouter :
if ($bad_bot) { return 403; }
Shellshock est une faille de sécurité présente dans le shell Bash, découverte en Septembre 2014. Normalement, cette faille a été corrigée dans Bash ; il est hautement recommandé d’avoir la version la plus récente.
L’explication ci-dessous explique comment empêcher l’accès depuis le serveur web nginx.
Dans votre contexte http
, utilisez la déclaration map
, telle que :
Code : nginx
map $http_user_agent $bad_bot {
default 0;
~*\{.*\:\; 1;
}
map $http_referer $bad_referer {
default 0;
~*\{.*\:\; 1;
}
C’est l’expression régulière *\{.*\:\;
qui fait son travail ;
à savoir qu’on peut légèrement la raccourcir, et cela fonctionne,
apparemment, aussi : *\{.*\:
Ensuite, vous utilisez les conditions suivantes pour fermer la connexion, sans autre forme de procédé :
if ($bad_bot) { return 444; }
if ($bad_referer) { return 444; }
Si ces conditions ne sont pas acceptées dans le contexte http
,
déclarez-les dans le contexte server
;-)
Si vous souhaitez ne pas logger ces attaques, il faut créer de nouvelles
map
, telle que :
Puis soit dans le contexte http
, soit dans le contexte server
,
il vous faut cibler votre journal d’accès, tel que :
access_log /path/to/access.log combined if=$loggable;
Tout petit mémo relatif à nginx, ou comment faire pour qu’apparaisse le listing d’un répertoire, avec nginx ?
Il faut utiliser l’option autoindex on;
!
Code : sh
Index of /apt/
../
archive.canonical/ 25-Jan-2016 18:18 -
archive.ubuntu/ 25-Jan-2016 18:18 -
epson/ 06-Feb-2016 23:04 -
extra.linuxmint/ 25-Jan-2016 18:55 -
libreoffice/ 12-Feb-2016 23:40 -
packages.linuxmint/ 25-Jan-2016 19:50 -
security.ubuntu/ 25-Jan-2016 18:18 -
sil/ 13-Feb-2016 23:35 -
wine/ 12-Feb-2016 23:40 -
README 03-Mar-2016 03:51 1694
L’objet de ce post est simplement un mémo, à savoir comment accéder à un partitionnement RAID, non chiffré, et cela grâce à un LiveCD !
mdadm --assemble --scan
*
cela aura pour effet de monter les différents partitionnements que
la commande sera capable de reconnaître.* Ces opérations se font toujours en appelant les droits administrateurs ! Autrement vous n’y aurez qu’un accès en lecture…
Nommé Durcir Linux : utiliser dnscrypt est un bien grand mot… en fait, nous n’allons pas durcir directement Linux, mais nous allons utiliser un petit outil, bien pratique, dont le but est de chiffrer les communications DNS !
DNSCrypt est un outil, à l’origine développé par OpenDNS, qui maintenant a sa vie propre, au-travers du site : dnscrypt.org.
Revenons en au but de ce petit outil, à savoir d’authentifier les communications DNS, entre votre client logiciel DNS, et les serveurs DNS que vous utilisez pour pouvoir surfer sur Internet. Il utilise des signatures cryptographiques pour communiquer. Il interroge des serveurs DNS publics, compatible avec l’outil.
Il peut-être actif conjointement à votre serveur DNS cache local. pour cela, je vous renvoie à la documentation officielle
Bien comprendre que cela ne protège pas des failles dues à DNS. dnscrypt authentifie le trafic DNS, avec un serveur DNS compatible, et ainsi empêche qu’un serveur malintentionné se fasse passer pour un serveur authentique.
dnscrypt n’est pas non plus un service VPN, et n’a pas l’intention de fournir de tels services, vous ne pouvez pas faire passer tous vos flux TCP/IP, ni UDP, à l’intérieur… Seules les requêtes DNS, sur les ports 53 et 443, en UDP.
Soyez avertis aussi que les serveurs DNS compatibles peuvent très bien journaliser votre trafic !
Il fonctionne sur les protocoles IPv4 et IPv6.
Du côté de Debian, et assimilés, le client existe dans les dépôts officiels, pour toutes les versions de Debian, de stable à Sid.
Du côté des *Buntu, il existe les ppa suivants :
à vous de les ajouter, puis de les installer.
Sinon, vous attendez la future LTS [[http://packages.ubuntu.com/search?suite=xenial&searchon=names&keywords=dnscrypt|Xenial]], ou vous mettez-à-jour vers [[http://packages.ubuntu.com/search?suite=wily&searchon=names&keywords=dnscrypt|Willy]] !
Le fichier de configuration principal est situé dans /etc/default/dnscrypt-proxy
.
Vous y retrouverez différentes options faciles à comprendre !
Pensez à bien modifier votre configuration dans l’outil Network Manager, et à paramétrer votre onglet [ Paramètres IPv4 ] en modifiant :
enregistrez !
Si vous n’utilisez pas Network Manager, modifiez directement votre fichier
/etc/network/interfaces
, en ajouter la mention :
dns-nameservers 127.0.0.2
dans ce cas, pensez à redémarrer votre réseau !
Oui, c’est bien l’adresse localhost 127.0.0.2
…
car l’outil dnscrypt-proxy
travaille en relation avec dnsmasq
, qui
lui fonctionne, par défaut, sur l’adresse localhost normale.
Celui de Xu Zhen, ce sera l’adresse localhost ‘127.0.0.1’.
À ce propos, si vous changez l’option liée à l’utilisateur en changeant son nom, soit… c’est votre droit - mais pensez à supprimer celui créé par l’installateur, et à créer le vôtre dans les mêmes conditions, tel que :
# adduser --system --quiet --home /run/dnscrypt --shell /bin/false --group --disabled-password --disabled-login votre_user_dnscrypt
Cela est d’ailleurs indiqué dans le fichier de configuration !
Vous êtes libre de changer aussi son répertoire maison ; pensez à vérifier la création dudit répertoire, et à supprimer celui par défaut !
Toutes les options que renferme le manpage lié à l’outil
sont utilisables dans le fichier de configuration :
$ man dnscrypt
Il suffit dans ce cas d’enlever les 2 symboles --
qui les précédent.
À ce propos, si vous avez la bonne idée d’utiliser l’option logfile
,
telle que logfile=/var/log/dnscypt-proxy.log
et si vous utilisez apparmor
aussi,
il faudra changer le profil apparmor lié à l’outil, pour y ajouter la ligne suivante :
/var/log/dnscypt-proxy.log rw,
Vous trouverez une liste des différents serveurs DNS compatibles, leurs noms,
leurs adresses IP, leurs clés d’authentification, etc…
dans le fichier /usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv
.
Vous pouvez changer ces informations dans le fichier de configuration.
Rkhunter émet cet avis : Warning: Suspicious file types found in /dev: /dev/.udev/rules.d/root.rules: ASCII text
Normalement, en effet aucun fichier text ne devrait se trouver dans le
répertoire des fichiers périphériques, nommé dev
!
Mais si dans votre cas, votre installation système est fraîche, toute neuve, pas de panique… en effet, depuis assez récemment, quelques distributions, telle que Ubuntu, le font !
Si le contenu du fichier en question est très similaire à ceci :
SUBSYSTEM=="block", ENV{MAJOR}=="252", ENV{MINOR}=="0", SYMLINK+="root"
Cela semble normal ! Et, donc être un fameux faux positif de rkhunter !
⇒ modifions le fichier /etc/rkhunter.conf
, pour ajouter la ligne suivante,
dans la bonne section :
ALLOWDEVFILE="/dev/.udev/rules.d/root.rules"
Puis recharger la base de données, avec l’option --propupd
de rkhunter,
et lancez un nouveau test !
Si malheureusement ce n’est pas le cas… une petite réinstallation système ?!
Rkhunter émet cet avis : Warning: Hidden directory found: /dev/.static, ou Warning: Hidden directory found: /dev/.udev
Si votre installation système est toute fraîche, n’ayez pas peur, vous êtes “tombé” sur un des fameux faux positif de ce binaire !
Modifiez donc les variables ALLOWHIDDENFILE
correspondante, dans le
fichier /etc/rkhunter.conf
!
ALLOWHIDDENFILE="/dev/.static"
Recharger la base de donnée, grâce à l’option --propupd
, et relancez le test.
Sinon, si ce n’est pas le cas, malheureusement… il vous faudra envisager le pire !
Rkhunter émet cet avis : Warning: Hidden file found: /dev/.initramfs: symbolic link to /run/initramfs’ !
Si votre installation système est toute fraîche, n’ayez pas peur, vous êtes “tombé” sur un des fameux faux positif de ce binaire !
Modifions le fichier /etc/rkhunter.conf
, pour ajouter :
ALLOWHIDDENFILE="/dev/.initramfs"
Recharger la base de donnée, grâce à l’option --propupd
, et relancez le test.
Sinon, si ce n’est pas le cas, malheureusement… il vous faudra envisager le pire !
Vous avez un message Error 404, sur une des pages visitées.
Et les logs du server web nginx vous avertissent de ce message :
2016/02/13 11:35:52 [crit] 995#0: *48 open() "/srv/www/site.web/www/" failed (13: Permission denied), (…)
Modifiez les droits en écriture à la racine de votre site !
Par exemple :
# chmod 0705 /srv/www/site.web/www
Même pas besoin de redémarrer nginx !
Dans la continuité de mon article précédent
Durcir Linux : modifier le partitionnement
il est une commande intéressante à utiliser : chattr
Cet outil permet de modifier les attributs de fichiers, répertoires.
Il existe une option qui est fortement pratique : l’option i
- dont le
but est de rendre figé, immuable l’état d’un fichier, ou répertoire et
d’interdire toute modification ultérieure, même par l’administrateur système,
généralement nommé root
.
Les répertoires à protéger, tout particulièrement, sont :
/bin
,/boot
,/etc
,/usr
,/root
,/sbin
,/initrd
, /lib
, /lib64
, /vmlinuz
⇒ Pour protéger/figer/rendre immuable, un petit coup de commande :
chattr -R +i /bin /boot /etc /usr /root /sbin /lib* /initrd* /vmlinuz* 2> /dev/null
chattr -R -i /etc/adjtime /etc/blkid.tab /etc/mtab /etc/network/run /etc/udev/rules.d 2> /dev/null
⇒ Pour enlever l’option i
sur lesdits répertoires et fichiers, en question,
il suffit d’écrire la commande ainsi :
chattr -R -i /boot /usr /bin /sbin /lib* /root /vmlinuz* /initrd* /etc 2> /dev/null
Tout outil nécessitant une modification système, comme par exemple visudo, ou les outils de gestion de paquets, tels que ceux ci-dessous, impose la gymnastique de rendre muable avant leur usage, et d’avoir le réflexe de figer en suivant !
N’oubliez pas que si le système vous refuse l’action, c’est que vous avez probablement figer l’état de différents binaires. ;-)
Ces commandes peuvent être insérées dans un script, pour vous faciliter
la vie, et mieux, aussi vous devriez les intégrer à votre script de gestion
apt
.
Si jamais vous avez la bonne idée d’abuser de cette commande, veuillez comprendre absolument qu’avec les outils apt, dpkg, synaptic, - et très certainement, tout outil gérant l’installation logicielle -, il vous faudra :
-i
;+i
en suivant…Vous êtes avertis, autrement vous seriez surpris par quelques dysfonctionnements.
Dans le fichier /etc/apt/apt.conf.d/00apt
, ajouter :
DPkg::Pre-Invoke{
"/repertoire/chattr_sys 0";
(…)
}
DPkg::Post-Invoke {
(…)
"/repertoire/chattr_sys 1";
}
Fichier : chattr_sys
|
|
Vous pouvez retrouver la dernière version de ce script sur mon gitlab !
$ man chattr
Ou cette fois-ci, comment titrer : Filtrer le protocole ICMPv6 sous Linux - l’équivalent du protocole ICMP mais pour IPv6
Il y a quelques heures, j’ai écrit cet autre mémo … maintenant, je retranscris à-propos des mesures de filtrage à mettre en place autour de ce protocole qu’est ICMPv6.
Je ne vais pas faire un rappel de ce pourquoi existe ce protocole, ni du fait que mal utilisé, il peut-être dangereux ; et, bien sûr, malheureusement, il y aura toujours des gens pour mal l’utiliser !
Par prudence, il est recommandable de filtrer tous les codes expérimentaux, tels que 100, 101, 200, et 201, ainsi que les codes réservés pour le futur, à savoir les codes 127 et 255.
Il est recommandé de bloquer les codes suivants :
Les recommandations sont de limiter, en entrée et en sortie de machine, tous les codes de type :
Les recommandations suivantes sont de limiter en entrée seulement, tous les codes suivants :
Concernant les codes suivants, il est précisé, dans leur RFC correspondante, leur format de message :
tous les codes dits MLD
donc 130, 131, 132 et 143 - et MLDv2 doivent être
envoyés depuis une adresse dont la source est un lien local IPv6,
avec un hop limit
à 1
tous les codes dits ND
de 133
à 137 doivent être envoyés avec un hop-limit
à 255
-
définis par la RFC 4861
.
Quelques précisions concernant ces codes :
le code 133 - Router Solicitation - doit être envoyé par une source ayant forcément une adresse IP assignée, ou depuis une adresse non spécifiée si l’interface réseau n’a pas encore d’adresse IP assignée, vers tout routeur.
le code 134 - Router Advertisement - doit ABSOLUMENT être envoyé par un routeur, émettant un avis de routeur périodique, ou une réponse à une sollicitation de routeur, à destination de tout nœud multicast ou à l’adresse source invoquant le routeur.
le code 135 - Neighbor Solicitation - doit être envoyé par une source ayant forcément une adresse IP assignée, ou depuis une adresse non spécifiée si l’interface réseau n’a pas encore d’adresse IP assignée, vers tout nœud multicast.
le code 136 - Neighbor Advertisement - doit ABSOLUMENT être envoyé par une adresse IP assignée, vers l’adresse source invoquant le code 135, ou vers tout nœud multicast, s’il n’y a pas d’adresse assignée.
le code 137 - Redirect Message - doit ABSOLUMENT être envoyé par une adresse IP assignée, lien local IPv6, d’un routeur vers l’adresse source qui a demandé la redirection du message.
les codes dits NIQ
- donc
139 - ICMP Node Information Query - et 140 -
ICMP Node Information Response -
doivent refuser toutes requêtes venant d’adresses IPv6 dites globales
et devraient appliquer l’emploi de l’option limit
.
À savoir qu’il y a d’autres mesures de sécurité, plus complexes…
RFC 4620
les codes dits ND ID - donc 141 - Inverse Neighbor Discovery Solicitation Message - et 142 - Inverse Neighbor Discovery Advertisement Message -, tous deux doivent avoir pour source une adresse IP assignée - codes définis par la RFC 3122 :
les codes dits SEND
- donc
148 - Certification Path Solicitation Message - et 149 -
Certification Path Advertisement Message - doivent être envoyés
avec un hop-limit
à 255
- c’est la RFC 3971
qui définit ces codes.
les codes dits MRD
- donc
151 à 153, définis par la RFC 4286
,
doivent être envoyés depuis une addresse assignée, lien local IPv6,
et avoir un hop-limit
à 255
.
En mode paranoïaque, cela donne ce genre de règles :
##ip6tables -A INPUT -p icmpv6 -m conntrack --ctstate INVALID -j DROP
ip6tables -A INPUT -p icmpv6 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
ip6tables -A INPUT -p icmpv6 -m limit --limit 3/s --limit-burst 7 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -m conntrack --ctstate NEW -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -m conntrack --ctstate NEW -j ACCEPT
ip6tables -A INPUT -s fe80::/64 -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j ACCEPT # Type: 134
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbour-solicitation -m hl --hl-eq 255 -j ACCEPT # Type: 135
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbour-advertisement -m hl --hl-eq 255 -j ACCEPT # Type: 136
ip6tables -A INPUT -p icmpv6 -j DROP
##ip6tables -A OUTPUT -p icmpv6 -m conntrack --ctstate INVALID -j DROP
ip6tables -A OUTPUT -p icmpv6 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type echo-request -m conntrack --ctstate NEW -j ACCEPT
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type echo-reply -m conntrack --ctstate NEW -j ACCEPT
ip6tables -A OUTPUT -d ff02::/16 -p icmpv6 --icmpv6-type router-solicitation -j ACCEPT # Type: 133
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type neighbour-solicitation -j ACCEPT # Type: 135
ip6tables -A OUTPUT -p icmpv6 --icmpv6-type neighbour-advertisement -j ACCEPT # Type: 136
ip6tables -A OUTPUT -d ff02::/16 -p icmpv6 --icmpv6-type 143/0 -j ACCEPT # Type: 143/0
ip6tables -A OUTPUT -p icmpv6 -j DROP
Voici, pour l’exemple, basé sur la compréhension des recommandations IETF,
des règles ICMP filtrées, limitées ; puis de rejeter tous les autres codes,
avec le message icmp6-adm-prohibited
.
# INPUT RULES
ip6tables -N INPUT_ICMPV6
##ip6tables -A INPUT_ICMPV6 -p icmpv6 -m conntrack --ctstate INVALID -j DROP
ip6tables -A INPUT_ICMPV6 -p icmpv6 -m limit --limit 3/s --limit-burst 7 -j ACCEPT
ip6tables -A INPUT_ICMPV6 -p icmpv6 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 1 -m conntrack --ctstate NEW -j ACCEPT # destination-unreachable; Must Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 2/0 -m conntrack --ctstate NEW -j ACCEPT # packet too big; Must Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 3/0 -m conntrack --ctstate NEW -j ACCEPT # time exceeded; Must Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 3/1 -m conntrack --ctstate NEW -j ACCEPT # time exceeded; Should Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 4/0 -m conntrack --ctstate NEW -j ACCEPT # parameter pb: Erroneous header field encountered; Should Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 4/1 -m conntrack --ctstate NEW -j ACCEPT # parameter pb: Unrecognized Next Header Type encountered; Must Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 4/2 -m conntrack --ctstate NEW -j ACCEPT # parameter pb: Unrecognized IPv6 option encountered; Must Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 100 -j DROP # private experimentation
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 101 -j DROP # private experimentation
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 127 -j DROP # error messages ICMPv6
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 128/0 -m conntrack --ctstate NEW -j ACCEPT # ping tool: echo request message; Must Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 129/0 -m conntrack --ctstate NEW -j ACCEPT # ping tool: echo reply message; Must Not Be Dropped
# link-local multicast receive notification mssg (need link-local src address, with hop-limit: 1)
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 130/0 -s fe80::/64 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 131/0 -s fe80::/64 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 132/0 -s fe80::/64 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
# address configuration and routeur selection mssg (received with hop limit = 255)
##ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 133/0 -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped (only RELATED,ESTABLISHED,UNTRACKED)
ip6tables -A INPUT_ICMPV6 -s fe80::/64 -p icmpv6 --icmpv6-type 134/0 -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped (only RELATED,ESTABLISHED,UNTRACKED)
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 135/0 -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped (only RELATED,ESTABLISHED,UNTRACKED)
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 136/0 -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped (only RELATED,ESTABLISHED,UNTRACKED)
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 137/0 -j DROP # Will Be Dropped Anyway
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 138/0 -j DROP # Will Be Dropped Anyway
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 139/0 -j DROP # Should Be Dropped Unless a Good Case Can Be Made
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 140/0 -j DROP # Should Be Dropped Unless a Good Case Can Be Made
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 141/0 -d ff02::1 -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped (only RELATED,ESTABLISHED,UNTRACKED)
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 142/0 -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped (only RELATED,ESTABLISHED,UNTRACKED)
# link-local multicast receive notification mssg (need link-local src address, with hop-limit: 1)
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 143 -s fe80::/64 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
# needed for mobylity
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 144/0 -j DROP # Will Be Dropped Anyway
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 145/0 -j DROP # Will Be Dropped Anyway
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 146/0 -j DROP # Will Be Dropped Anyway
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 147 -j DROP # Will Be Dropped Anyway
# SEND certificate path notification mssg (received with hop limit = 255)
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 148 -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped (only RELATED,ESTABLISHED,UNTRACKED)
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 149 -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped (only RELATED,ESTABLISHED,UNTRACKED)
# multicast routeur discovery mssg (need link-local src address and hop limit = 1)
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 151 -s fe80::/64 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 152 -s fe80::/64 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 153 -s fe80::/64 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
#
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 200 -j DROP # private experimentation
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 201 -j DROP # private experimentation
ip6tables -A INPUT_ICMPV6 -p icmpv6 --icmpv6-type 255 -j DROP # error messages ICMPv6
# all others are dropped
#ip6tables -A INPUT_ICMPV6 -p icmpv6 ! --icmpv6-type -j DROP or -j REJECT --reject-with icmp6-adm-prohibited ⇐ this type seems not correctly supported!
ip6tables -A INPUT_ICMPV6 -p icmpv6 -j REJECT --reject-with no-route
# OUTPUT RULES
ip6tables -N OUTPUT_ICMPV6
##ip6tables -A OUTPUT_ICMPV6 -p icmpv6 -m conntrack --ctstate INVALID -j DROP
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 1 -m conntrack --ctstate NEW -m limit --limit 3/s --limit-burst 7 -j ACCEPT # destination-unreachable; Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 2/0 -m conntrack --ctstate NEW -j ACCEPT # packet too big; Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 3/0 -m conntrack --ctstate NEW -j ACCEPT # time exceeded; Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 3/1 -m conntrack --ctstate NEW -j ACCEPT # time exceeded; Should Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 4/0 -m conntrack --ctstate NEW -m limit --limit 3/s --limit-burst 7 -j ACCEPT # parameter pb: Erroneous header field encountered; Should Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 4/1 -m conntrack --ctstate NEW -m limit --limit 3/s --limit-burst 7 -j ACCEPT # parameter pb: Unrecognized Next Header Type encountered; Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 4/2 -m conntrack --ctstate NEW -m limit --limit 3/s --limit-burst 7 -j ACCEPT # parameter pb: Unrecognized IPv6 option encountered; Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 100 -j DROP # private experimentation
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 101 -j DROP # private experimentation
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 127 -j DROP # error messages ICMPv6
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 128/0 -m conntrack --ctstate NEW -j ACCEPT # ping tool: echo request message; Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 129/0 -m conntrack --ctstate NEW -j ACCEPT # ping tool: echo reply message; Must Not Be Dropped
# link-local multicast receive notification mssg (need link-local src address, with hop-limit: 1)
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 130/0 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 131/0 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 132/0 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
# address configuration and routeur selection mssg (received with hop limit = 255)
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 133/0 -d ff02::/16 -m conntrack --ctstate NEW -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped
##ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 134/0 -d fe80::/64 -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 135/0 -m conntrack --ctstate NEW -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 136/0 -m conntrack --ctstate NEW -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 137/0 -j DROP # Will Be Dropped Anyway
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 138/0 -j DROP # Will Be Dropped Anyway
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 139/0 -j DROP # Should Be Dropped Unless a Good Case Can Be Made
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 140/0 -j DROP # Should Be Dropped Unless a Good Case Can Be Made
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 141/0 -d ff02::1 -m conntrack --ctstate NEW -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 142/0 -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped
# link-local multicast receive notification mssg (need link-local src address, with hop-limit: 1)
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 143 -d ff02::/16 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
# needed for mobylity: except if the context requires it, then it will be necessary to limit them
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 144/0 -j DROP # Will Be Dropped Anyway
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 145/0 -j DROP # Will Be Dropped Anyway
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 146/0 -j DROP # Will Be Dropped Anyway
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 147 -j DROP # Will Be Dropped Anyway
# SEND certificate path notification mssg (received with hop limit = 255)
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 148 -m conntrack --ctstate NEW -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 149 -m conntrack --ctstate NEW -m hl --hl-eq 255 -j ACCEPT # Must Not Be Dropped
# multicast routeur discovery mssg (need link-local src address and hop limit = 1)
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 151 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 152 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 153 -m conntrack --ctstate NEW -m hl --hl-eq 1 -j ACCEPT # Must Not Be Dropped
#
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 200 -j DROP # private experimentation
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 201 -j DROP # private experimentation
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 --icmpv6-type 255 -j DROP # error messages ICMPv6
# all others are dropped
#ip6tables -A OUTPUT_ICMPV6 -p icmpv6 ! --icmpv6-type -j DROP or -j REJECT --reject-with icmp6-adm-prohibited # ⇐ this type seems not correctly supported!
ip6tables -A OUTPUT_ICMPV6 -p icmpv6 -j REJECT --reject-with no-route
Je ne vais pas reprendre le petit laïus sur IETF , ou IANA, mais simplement rappeler de bonnes lectures à faire.
Si jamais, vous avez d’autres “tuyaux” du même acabit, n’hésitez pas m’envoyer un commentaire par mail.
les différents paramètres ICMPv6
la RFC 4890
la RFC 5927
GNU Linux Magazine : Netfilter et le filtrage du protocole IPv6
Ou comment titrer : Filtrer le protocole ICMP sous Linux.
Certains déclament qu’il faut absolument tout bloquer, terminer les commandes
telles traceroute
, ping
… basta, et qu’on me fiche la paix !
D’autres disent, oui, mais c’est quand même bien pratique d’utiliser de telles commandes, sauf que…
Le but évident d’ICMP est de rapporter les messages d’erreurs, d’informations des états, de contrôle, liés à la communication IP d’un réseau, dont Internet, donc, relatifs à la délivrance des paquets IP.
Ce but intéressant a ses défauts : puisque par ce biais-là, toute personne qui utilise le protocole ICMP peut “cartographier” l’ensemble de votre réseau, un moindre mal en somme, voire à chercher à attaquer celui-là, par certaines attaques connues, telles que le déni de service Smurf, comme le fameux “Ping de la Mort” ou tout autre DOS existant. Certaines attaques permettent aussi de s’attaquer au protocole TCP, tel que le service HTTP (attaque SlowLoris), et d’autres…
Froid dans le dos ? Y’a de quoi…
Dans cet article, nous allons apprendre à gérer correctement ICMP, tout en tenant compte des recommandations faite par des organismes reconnus, tel l’IETF, l’IANA, au-travers de différentes RFC, qui seront toutes nommées.
Les codes ci-dessous sont reconnus pour être dépréciés, dangereux, et donc à ne plus utiliser :
N’hésitons même pas, les messages correspondant doivent ABSOLUMENT être refusés !
L’IANA, dans sa référence à la RFC 6918 considère que les codes suivants sont dépréciés et donc à filtrer - toute discrétion est laissé libre à l’administrateur de choisir son mode de filtrage - :
6/0 - Alternate Host Address
15 - Information Request
16 - Information Reply
17 - Address Mask Request
18 - Address Mask Reply
30 - Traceroute
31 - Datagram Conversion Error
32 - Mobile Host Redirect
33 - IPv6 Where-Are-You
34 - IPv6 I-Am-Here
35 - Mobile Registration Request
36 - Mobile Registration Reply
37 - Domain Name Request
38 - Domain Name Reply
39 - SKIP
À vous de choisir, si vous les détruisez… alors, mode parano ?!
Quoiqu’il en soit, si vous décidez de filtrer le code 30, n’oubliez pas que l’utilitaire traceroute est capable de fonctionner sur les protocoles UDP:53, TCP:80, voire d’imiter le code ICMP:8/0 !
Les recommandations sont de limiter, en entrée et en sortie de machine :
traceroute
, ainsi que le code 30/0 d’ailleurs)Pour limiter, dans le contexte d’une machine Linux, on utilisera l’option
match limit
avec iptables, tout simplement…
En mode parano, vous pouvez très bien ouvrir :
iptables -A INPUT -p icmp --icmp-type echo-reply -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -m limit --limit 3/s --limit-burst 7 -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type echo-request -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -m limit --limit 3/s --limit-burst 7 -j ACCEPT
iptables -A INPUT -p icmp -j DROP
iptables -A OUTPUT -p icmp -j DROP
Voici, pour l’exemple, basé sur la compréhension des recommandations IETF,
des règles ICMP filtrées, limitées ; puis de rejeter tous les autres codes,
avec le message icmp-host-prohibited
.
Code : sh
/sbin/iptables -A INPUT -i ethX -p icmp -m limit --limit 3/s --limit-burst 7 -j icmp4in
/sbin/iptables -A icmp4in -p icmp -m conntrack --ctstate INVALID -j DROP
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 0 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Echo reply"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 3/0 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Destination Net Unreachable"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 3/1 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Destination Host Unreachable"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 3/3 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Destination Port Unreachable"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 3/4 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP PathMTU Discovery"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 3/6 -j DROP
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 3/8 -j DROP
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 4 -j DROP
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 5 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Redirect mssg"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 8/0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Echo mssg"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 9/0 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Router Advertisement Message"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 10/0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Router Solicitation Message"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 11 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Time exceeded"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 12 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Param pb"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 13/0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Timestamp Message"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 14/0 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Timestamp Reply Message"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 15 -j DROP
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 16 -j DROP
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 17/0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Address Mask Request"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 18/0 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Address Mask Reply"
/sbin/iptables -A icmp4in -p icmp -m icmp --icmp-type 30 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT -m comment --comment "ICMP Traceroute"
# REJECT Others
/sbin/iptables -A icmp4in -p icmp -j REJECT --reject-with icmp-host-prohibited
/sbin/iptables -A OUTPUT -o ethX -p icmp -m limit --limit 3/s --limit-burst 7 -j icmp4out
/sbin/iptables -A icmp4out -p icmp -m conntrack --ctstate INVALID -j DROP
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 0 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 3/0 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 3/1 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 3/3 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 3/4 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 3/6 -j DROP
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 3/7 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 3/8 -j DROP
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 4/0 -j DROP
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 5 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 8/0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 9/0 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 10/0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 11 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 12 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 13/0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 14/0 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 15 -j DROP
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 16 -j DROP
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 17/0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 18/0 -m conntrack --ctstate RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -m icmp --icmp-type 30 -m conntrack --ctstate NEW,RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
/sbin/iptables -A icmp4out -p icmp -j REJECT --reject-with icmp-host-prohibited
L’IETF est un organisme connu, reconnu qui écrit beaucoup de documents techniques, dont le propos est d’améliorer la technicité, la sécurité des usages liés à Internet.
Et, bien-sûr certains documents existants insistent sur le fait de filtrer ICMP, voire ICMPv6 - relatif à IPv6, tels que :
Ces documents tous intéressants, certains sont vieux, d’autres récents, ont pour propos de réfléchir sérieusement à la sécurité à mettre en place autour du protocole ICMP.
Le document de travail relatif au filtrage d’ICMP aborde l’ensemble des protocoles IPv4 et IPv6 et explique quelles sont les attaques possibles, et donnent des recommandations utiles, qui vont du refus du paquet à la limitation des autres.
Clairement certains codes de messages qui sont absolument à bloquer, refuser, tels que le code ICMP 4/0 alias “Source Quench” qui est explicitement déprécié, à ne plus utiliser, mais ce n’est pas le seul !
Chkrootkit émet cette alerte : Searching for Suckit rootkit… Warning: /sbin/init INFECTED !
Déjà, si votre installation est fraîche, ne paniquez pas ; de toute façon, cela ne sert jamais à rien !
Déjà, si j’ai bien compris, il y a de grandes probabilités pour que ce soit un faux positif, qui traîne depuis longtemps - cf : le bogue #454566 -, et qui semble être résolu avec la version 0.50.
Mais avant de courir pour mettre-à-jour votre version, analysons ce qui peut l’être !
Ensuite, si j’ai bien compris quand la machine est infectée par ce rootkit
Suckit, elle place la chaîne HOME dans le répertoire /sbin/init
.
⇒ Une première analyse commence avec la commande suivante :
$ ls -li /sbin/init /sbin/telinit
130357 -rwxr-xr-x 1 root root 265848 juil. 18 2014 /sbin/init
130426 -rwxr-xr-x 1 root root 104728 juil. 18 2014 /sbin/telinit
Si vous ressortez le même résultat, c’est déjà bon signe…
⇒ Continuons l’analyse et vérifions la présence de chaîne HOME :
$ strings /sbin/init | grep -E HOME
Normalement, il ne devrait RIEN avoir dans ce répertoire !
Mais dans le cas de distribution récente, telle que depuis Ubuntu (et assimilée) Trusty,
vous aurez exactement cette sortie, qui semble tout autant normale :
$ strings /sbin/init | egrep HOME
XDG_CACHE_HOME
XDG_CONFIG_HOME
Pas de panique : apparemment, ce sont des spécifications liées au standard FreeDesktop…
⇒ Continuons l’analyse, avec la commande :
# cat /proc/1/maps | grep -E "init."
Normalement, aucun retour ne devrait être fait !
⇒ Vérifions la somme md5 du binaire init, puis comparons-la avec l’officielle :
$ md5sum /sbin/init
249b19aaa268143c3a0b3d6aa9faa070 /sbin/init
$ grep "sbin/init$" /var/lib/dpkg/info/upstart.md5sums
249b19aaa268143c3a0b3d6aa9faa070 sbin/init
Si les sommes sont similaires, c’est un autre bon signe…
L’autre moyen - à préférer - est de :
sha256sum
, voire sha512sum
!⇒ Histoire d’être ABSOLUMENT sûr que vous avez bien à faire à
ce fameux faux positif, exécutez la suite de commande, ci-dessous :
$ cd /sbin
$ ls -l init
-rwxr-xr-x 1 root root 265848 juil. 18 2014 init
Si vous voyez bien 1
, c’est bon !
⇒ finissons-en avec :
$ ln /sbin/init /sbin/init2
$ ls -l init
-rwxr-xr-x 2 root root 265848 juil. 18 2014 init
Si vous lisez bien 2
, et non pas 1
, c’est que vous êtes bon !
Félicitations !!!
Pensez à supprimer le lien init2
.
Une autre manière de vérifier est d’exécuter rkhunter :
rkhunter --checkall --report-warnings-only
Si, à la fin de l’analyse, vous n’avez rien - ce qui devrait être le cas, après avoir vérifié comme précédemment - c’est que c’est vraiment tout bon !
Si c’est possible, mettez-à-jour la version de chkrootkit vers la v0.50, minimum !
rkhunter peut parfois poser problème avec ce message d’alerte suivant : Warning: The command ‘/usr/bin/unhide.rb’ has been replaced by a script: /usr/bin/unhide.rb: Ruby script, ASCII text
⇒ La première chose à s’assurer que le binaire en question n’a pas été trafiqué, pour cela, utilisons le binaire debsums, tel que : Bien-sûr, si vous ne l’avez pas installé, faites-le… mais c’est dommage.
# debsums unhide.rb
/usr/bin/unhide.rb OK
/usr/share/doc/unhide.rb/changelog.Debian.gz OK
/usr/share/doc/unhide.rb/copyright OK
/usr/share/lintian/overrides/unhide.rb OK
/usr/share/man/man8/unhide.rb.8.gz OK
⇒ Maintenant, par acquis de conscience, faites ceci :
$ cp /usr/bin/unhide.rb $HOME
# apt purge unhide.rb
# apt install unhide.rb
$ diff /usr/sbin/unhide.rb ~/unhide.rb
Si diff ne retourne aucune information, c’est que les deux fichiers en question sont identiques ! (à moins d’avoir eu la malchance d’avoir eu le binaire diff lui même modifié…)
Si tout semble ‘OK’, c’est que l’on a faire face au fameux faux positif de rkhunter concernant ce binaire ! ce qui devrait être le cas dans une installation fraîchement exécutée !
⇒ Contrôlons les sommes de contrôle différemment :
$ md5sum /usr/bin/unhide.rb
b1642389370e283c580de371b61ec3cb /usr/bin/unhide.rb
$ grep "usr/bin/unhide.rb" /var/lib/dpkg/info/unhide.rb.md5sums
b1642389370e283c580de371b61ec3cb usr/bin/unhide.rb
⇒ L’autre manière est de :
sha256sum
, voire sha512sum
! - c’est même préférableSi les sommes sont identiques, c’est tout bon !
Pensez à supprimer le fichier ~/unhide.rb
que vous avez créé lors de la
copie, précédemment !
Puisque tout semble bon, modifions le fichier /etc/rkhunter.conf
, pour
modifier cette variable : PKGMGR=DPKG
Recharger la base de donnée de rkhunter, avec l’option --propupd
, et
lancez à nouveau le test.
Normalement, l’utilitaire unhide.rb
devrait correctement être pris en charge…
Si jamais, ce n’était pas le cas :
#SCRIPTWHITELIST=/usr/bin/unhide.rb
- mais gardez à l’esprit que ce n’est pas préférable/recommandable.Si malgré tout, cela n’est pas bon, envisager sérieusement une réinstallation de votre Linux !!!
Ce script a pour but d’aider très simplement à convertir, mais surtout d’optimiser des images jpg, des images png, afin de gagner en poids de l’image, pour l’intégration de celles-ci dans les sites web. Et donc de réduire le coût de la bande passante !
Ce script bash de conversion et d’optimisation d’images jpeg et png, fonctionne très simplement. Il y a trois options possibles :
jpg2jpg
dont le but est d’optimiser une image jpeg après une conversion à une qualité, ayant le ratio 70%.
Le gain est conséquent, de l’ordre du facteur 3 !jpg2png
permet de convertir l’image jpeg en image png, puis d’optimiser ladite image png.
Attention, explosion du poids !png2png
génère l’optimisation d’image png.Pour se servir de ce script de conversion et d’optimisation d’image jpeg et/ou d’image png, vous devez veillez à avoir les outils suivants :
mogrify
.libjpeg
qui fournit l’outil d’optimisation jpeg : jpegtran
.pngnq
gvfs-bin
qui fournit l’outil gvfs-info
.Bien évidemment, vous devez veiller à ce que vos images à traiter soient de qualité originale, des images ‘sources’ !
Fichier : convert_image
|
|
Il ne reste plus qu’à l’utiliser ainsi :
$ chmod 0700 convert_image $ ./convert_image /name_dir/ option
Rkhunter émet cet avis : Warning: File ‘/sbin/xyz’ has the immutable-bit set. et, il le fait sur plusieurs fichiers !
Ahahhh, petit malin, je vous y prend, vous avez utilisez l’ outil chattr avec l'option `-I` , n’est-ce pas ?! Tant mieux… sinon, vous avez peut-être un petit problème !
Le fichier de configuration /etc/rkhunter.conf
renferme une option
à-priori utile : IMMUTABLE_SET=0
!
Sauf qu’une fois activée, lors d’une vérification, ce sont les quelques binaires
qui ne peuvent avoir l’option immutable
, qui vont recevoir ladite complainte.
C’est un peu l’histoire du serpent qui se mort la queue, n’est-ce pas !
Puisque vous utilisez l’option I
du binaire chattr
, modifiez le fichier
crontab
relatif à rkhunter…
Le fichier /etc/default/rkhunter
nous informe de ceci :
$ cat /etc/default/rkhunter
# Defaults for rkhunter automatic tasks
# sourced by /etc/cron.*/rkhunter and /etc/apt/apt.conf.d/90rkhunter
#
# This is a POSIX shell fragment
#
(…)
Nous savons que lors de l’installation, il se crée un fichier de cron,
dans /etc/crond.daily/rkhunter
- vérifiez votre cas - ouvrons-le pour
le modifier ainsi :
Fichier : /etc/crond.daily/rkhunter
|
|
Résultat, lors de la future vérification planifiée de l’outil rkhunter,
il exécutera votre script lié à l’usage de chattr… en désactivant d’abord,
l’option immutable
, puis fera son boulot, et pour finir réactivera l’option.
Si c’est vous qui l’exécutez, pensez d’abord à désactiver… puis à réactiver votre protection !
Votre outil apt(-get) vous restitue le message suivant, lors d’une mise-à-jour :
Citation :
E: Malformed Description-md5 line; doesn't have the required length !
L’astuce est la suivante - à faire en mode console, avec vos droits admins, bien sûr - :
Code : bash
# apt-get clean
# cd /var/lib/apt
# mv lists lists.old
# mkdir -p lists/partial
# apt-get clean
# apt-get update
Ou, comment titrer autrement que : De meilleures pratiques GPG/PGP !
Je ne parlerais pas de comment créer une clé GPG pour communiquer de manière chiffrée ; il existe de très bons guides/tutoriels qui le font très bien, et vraiment mieux que ce que je ne pourrais le faire :
Pour pouvoir utiliser correctement gpg, il faut installer non seulement
cet outil, mais vous avez besoin d’autres outils, tels que :
gnupg gnupg-curl hopenpgp-tools parcimonie openssl
Certains de ces outils ne sont disponibles que sous Linux…
tels hopenpgp-tools
, parcimonie
.
Vous ne les trouverez pas nativement sous OpenBSD, ni en package, ni en ports !
Du fait d’installer l’outil parcimonie
, il est IMPÉRATIF de ne plus utiliser l’option
--refresh-keys
de GPG…
parcimonie le fera de la manière convenable et surtout sécurisé !
keys.openpgp.org
.Hormis le fait d’avoir IMPÉRATIVEMENT son outil GPG/PGP à jour,
afin d’éviter les failles de sécurité, il est recommandé de ne plus utiliser dans aucun fichier toutes les options keyserver-*
.
La seule option keyserver
à utiliser, doit l’être dans le fichier ~/.gnupg/dirmngr.conf
,
tel que :
keyserver hkps://keys.openpgp.org
La configuration sous Unix/Linux se fait dans votre dossier personnel : ~/.gnupg/gpg.conf
Ajouter ces options :
Code :
keyid-format 0xlong
with-fingerprint
Pour améliorer la qualité des clés GPG, il nous faut rajouter les options suivantes :
Code :
cert-digest-algo SHA512
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
personal-digest-preferences SHA512
Pour finir, voici d’autres options à utiliser, elles aussi, nécessaires :
Code :
keyserver-options include-revoked
keyserver-options no-try-dns-srv
list-options show-uid-validity
verify-options show-uid-validity
use-agent
auto-key-locate local
auto-key-locate keyserver
fixed-list-mode
utf8-strings
Je vous renvoie à la documentation du manpage pour que vous compreniez la raison de chacune.
Autrement-dit, les IMPÉRATIFS à ABSOLUMENT tenir compte sont :
Donc, nous l’avons compris, il est nécessaire/préférable d’utiliser l’outil GPG avec les empreintes de clés.
Ce sont les mêmes commandes optionnelles à gpg, mais au lieu de renseigner l’email, l’identifiant de clé, on utilisera l’empreinte d’une clé …
gpg --recv-key 'fingerprint'
- simple ou double quotes, c’est pareilgpg --fingerprint 'fingerprint'
gpg --sign-key 'fingerprint'
gpg --lsign-key 'fingerprint'
- ATTENTION : si vous signez localement, vous ne pourrez plus exporter votre signature !gpg --with-fingerprint keyfile
gpg --output email@domain.tld.rev.asc --gen-revoke 'fingerprint'
Ok, nous avons vu comment utiliser openssl, parcimonie, les outils gpg
pour nous assurer de faire les choses proprement, mais tu n’as pas
parlé du paquet hopenpgp-tools
! En effet ;-)
En fait, dans ce paquet-là, il est fourni au moins deux outils que sont
hkt
et hokey
… assemblés, ils permettent en mode console d’avoir
la pertinence qu’une clé GPG est bonne à partir de son empreinte - et
ils sont très facile à utiliser, tel que :
hkt export-pubkeys 'fingerprint' | hokey lint
Les tests corrects sont affichés en vert . Tout problème avec la clé vérifiée est affiché en rouge ! Il faut alors IMPÉRATIVEMENT se méfier d’une telle clé, voire la régénérer si c’est la vôtre, après avoir configuré votre fichier de configuration personnelle, avec les recommandations ci-dessus !
Vous retrouverez mon script de gestion de clé GPG sur mon espace git… Du moins, j’espère bien qu’il soit POSIX…
./mng_gpg help
./mng_gpg fingerprint 'gpg:fingerprint'
Pour information, cet outil a aussi besoin de l’outil shred
…
Et, vous avez bien compris, tout comme moi d’ailleurs… on fait une
recherche par … mail, ID, empreinte !
Ahhh, les joies de SSH, n’est-ce pas ?!
Il y a plusieurs raisons possibles à ce genre de déconnexions intempestives, et fortement désagréables, et aucunes de particulières.
De fait, il existe trois options SSH à configurer qui permettent
d’améliorer sensiblement la tenue de la connexion, dont une
TCPKeepAlive yes
qui peut être paramétrée côté serveur et
côté client !
Ouvrez votre fichier /etc/ssh/sshd_config
, et rajoutez ces deux options
:
ClientAliveInterval
: est le nombre de secondes pendant lequel le serveur va attendre avant d’envoyer un paquet null au client - le but étant de garder la connexion vivante.ClientAliveCountMax
: est la limite donnée à un client pendant lequel il est autorisé à ne pas donner de réponse, sans se faire déconnecter - sa valeur par défaut est : 3
Ouvrez votre fichier ~/.ssh/config
, et ajoutez ces deux options
correspondantes :
ServerAliveInterval
: est le nombre de secondes pendant lequel le client va attendre avant d’envoyer un paquet null au serveur - le but étant toujours de garder vivante la connexion.ServerAliveCountMax
: valeur par défaut est de : 3
Ces options ont pour propos de maintenir la connexion en vie ; le processus est le suivant :
ClientAliveInterval
et ServerAliveInterval
est arrivé à son terme, un signal “<span lang="en">
hello-are-you-there</span>
” est envoyé…ClientAliveCountMax
et ServerAliveCountMax
est le nombre de fois où ce signal “hello” va être envoyé.Le calcul est très simple : ClientAliveInterval
x ClientAliveCountMax
secondes, côté serveur, et réciproquement pour les options “Server”, côté client.
0
ses options les désactivent !Cela devrait améliorer la situation, mais ne la résout pas forcément !
Très utile avec l’usage du fameux projet SSLH - le multiplexeur de connexion HTTPS/SS(H|L)/VPN, etc…
S’il y a bien un mode qui en fait baver, c’est l’option ChrootDirectory pour le serveur SSH !
En effet, vous avez défini des utilisateurs qui ont le droit d’utiliser
Une règle, telle que la suivante devrait permettre d’agir ainsi, dans
le fichier de config /etc/ssh/sshd_config
:
Code :
Match group sshusers
ForceCommand internal-sftp
ChrootDirectory /chroot/%u
$HOME
, par exemple ; dans ces cas, adaptez,
adaptez, adaptez…
et vérifiez que votre utilisateur fasse bien
partie du groupe ssh dédié, que vous aurez précédemment créé -
il se nommera certainement autrement que celui nommé dans cet exemple ‘sshusers’ :)Mais, voilà, à chaque tentative de connexions, le serveur SSH vous jette et vous avertit de l’erreur suivante :
Citation :
Feb 12 19:56:30 server sshd[64689]: Accepted password for user from 192.168.xxx.yyy port 40829 ssh2 Feb 12 19:56:30 server sshd[64691]: fatal: bad ownership or modes for chroot directory "/chroot/user"
Ce qui bloque, ce sont les droits d’accès, vers le répertoire prison !
Il faut impérativement que les droits soient attribués à `root`, et en accès `0755` …
Puis ensuite créer le répertoire utilisateur, et attribuer les droits à l’utilisateur en question
Code :
# avec les droits administrateurs:
chmod 0755 /chroot
chown root:root /chroot
mkdir /chroot/user_id
chmod 0705 /chroot/user_id
chown user_id:user_id /chroot/user_id
Si vous aviez déjà créé les répertoires en question, vérifiez les droits d’accès et d’appartenances utilisateurs !
Voilà, à partir de ce moment-là, vous devriez pouvoir réussir enfin la connexion ssh.
Le serveur web nginx affiche une “belle page blanche” avec la mention Error 502: Bad Gateway !
Vérifiez :
Les fichiers de configuration sont :
/etc/nginx/nginx.conf
ou /etc/nginx/sites-available/*votre_domaine*.conf
vérifiez votre déclaration liée à la configuration des fichiers PHP :
Code : nginx
location ~ \.php$ {
(...)
fastcgi_pass unix:/var/run/votre_domaine.sock;
(...)
}
status
, si nécessaire…Code : nginx
location /status {
(...)
fastcgi_pass unix:/var/run/votre_domaine.sock;
(...)
}
/etc/php5/fpm/pool.d/*www*.conf
,
ou /etc/php5/fpm/pool.d/*votre_domaine*.conf
vérifier la correspondance avec votre socket PHP :
listen = /var/run/votre_domaine.sock
Il peut être utile de vérifier les déclarations suivantes, aussi :
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
Les déclarations listen.owner
et listen.group
sont impérativement liées
à l’utilisateur et au groupe du service nginx, généralement www-data
.
À changer, selon votre configuration…
Puis, redémarrez vos serveurs nginx, et php(x?)-fpm… les deux !
Suite à mes précédentes réflexions à-propos du Bon usage sécurisé de GPG , finalement je me décide pour un article de ce genre : Guide des bonnes pratiques pour la création de clés GPG.
De fait, il ne suffit pas de se dire, “je vais créer ma clé à coup de
--gen-key
, et puis zou…”, ou d’utiliser une interface graphique
pour le faire, telle qu’Enigmail ou GPA, c’est un processus un peu
plus long, d’autant si l’on veut le faire correctement !
Ce guide s’inspire très fortement de celui d’Alex Cabal…
Pour Enigmail, il faut ouvrir la fenêtre de gestion de clés, puis cliquer sur le menu ‘Générer > Nouvelle clé’…
Il ne reste plus qu’à choisir le courriel concerné, de créer une passphrase, et de la répéter ; dans l’onglet ‘Expiration’, veillez à la durée : pas plus de 2 ans !
Puis dans l’onglet ‘Avancé’, vérifier la taille de la clé : 4096, le type de la clé ‘RSA’… vous n’avez plus qu’à cliquer sur le bouton [ Générer la clef ], et à laisser faire le temps de la génération…
Avec GPA, c’est sensiblement pareil, à la différence que c’est le menu ‘Clefs’ > ‘Nouvelle clef’ qui permet de le faire…
Choisissez l’algorithme de chiffrement : RSA - (RSA (sign only) nous servira plus tard…) -, la taille de clé - il est très probable qu’il ne soit pas possible de chiffrer avec une clé plus forte que 3072 - puis remplissez les champs ‘Nom’, et ‘Courriel’ seulement, et finissez par cliquez dans la case à cocher ‘Expires’, pour choisir une date de 2 ans, maximum.
Il y a deux options pour créer une clé, l’une permettant de faire plus finement en demandant plus de choses que l’autre, à savoir :
--gen-key
, version abrégée de l’option --generate-key
,--full-gen-key
, version abrégée de l’option --full-generate-key
.Utilisons l’option --gen-key
:
Code : sh
$ gpg --gen-key
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection? **1**
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) **4096**
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) **2y**
Is this correct? (y/N) **y**
You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and E-mail Address in this form:
"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"
Real name: **Nom Prenom**
E-mail address: **email@domain.tld**
Comment:
You selected this USER-ID:
"Nom Prenom <email@domain.tld>"
Change (N)ame, (C)omment, (E)-mail or (O)kay/(Q)uit? **O**
You need a Passphrase to protect your secret key.
**demande votre passphrase**
gpg: key ******** marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
pub 4096R/******* 2013-03-13
Key fingerprint = **** **** **** **** **** **** **** **** **** ****
uid Nom Prenom <email@domain.tld>
sub 4096R/******** 2013-03-13
Veillez à utiliser une photo qui soit de taille légère !
Enigmail : il faut ouvrir la fenêtre de gestion de clés, menu “Édition” > “Ajouter une photo” après avoir sélectionné la clé.
GPA semble ne pas en être capable !
C’est l’option --edit-key
qui sera utilisée puis l’option addphoto
, telles que :
Code : sh
$ gpg --edit-key email@domain.tld
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
sub 4096R/******** created: 2013-03-13 expires: never usage: E
[ultimate] (1). Nom Prenom <email@domain.tld>
gpg> addphoto
Pick an image to use for your photo ID. The image must be a JPEG file.
Remember that the image is stored within your public key. If you use a
very large picture, your key will become very large as well!
Keeping the image close to 240x288 is a good size to use.
Enter JPEG filename for photo ID: /repertoire_vers_photo/photo.jpg
Is this photo correct (y/N/q)? y
You need a passphrase to unlock the secret key for
user: "Nom Prenom <email@domain.tld>"
4096-bit RSA key, ID ********, created 2013-03-13
**demande votre passphrase**
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
sub 4096R/******** created: 2013-03-13 expires: never usage: E
[ultimate] (1). Nom Prenom <email@domain.tld>
[ unknown] (2) [jpeg image of size 5324]
gpg> save
Paramétrer les hash préférés sont de bon aloi !
Enigmail semble ne pas en être capable !
GPA semble ne pas en être capable !
C’est encore l’option --edit-key
qui sera utilisée mais avec
l’option setpref
, telles que :
Code : sh
$ gpg --edit-key email@domain.tld
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
sub 4096R/******** created: 2013-03-13 expires: never usage: E
[ultimate] (1). Nom Prenom <email@domain.tld>
[ultimate] (2) [jpeg image of size 5324]
gpg> setpref SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed
Set preference list to:
Cypher: AES256, AES192, AES, CAST5, 3DES
Digest: SHA512, SHA384, SHA256, SHA224, SHA1
Compression: ZLIB, BZIP2, ZIP, Uncompressed
Features: MDC, Keyserver no-modify
Really update the preferences? (y/N) y
You need a passphrase to unlock the secret key for
user: "Nom Prenom <email@domain.tld>"
4096-bit RSA key, ID ********, created 2013-03-13
**demande votre passphrase**
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
sub 4096R/******** created: 2013-03-13 expires: never usage: E
[ultimate] (1). Nom Prenom <email@domain.tld>
[ unknown] (2) [jpeg image of size 5324]
gpg> save
Cette étape est vraiment importante ; elle sert à créer une sous-clé qui ne servira qu’à signer de nouveaux messages et autres documents…
Si vous vous passez des deux étapes précédentes, ne vous passez pas de celle-ci ; vous comprendrez plus bas le pourquoi !
Les recommandations de création de cette sous-clé sont ABSOLUMENT les mêmes que pour la création de la clé principale !
Quoi ? vous avez déjà oublié : RSA + 4096 bits - avec la différence qu’on utilisera le choix ‘RSA (sign only)’, et pas besoin de paramétrer une période de validité…
Enigmail semble ne pas en être capable !
GPA semble ne pas être capable de générer de clés dont la taille soit de 4096 bits, sinon, c’est menu “Clefs” > “Nouvelle clé” ; choisir l’algorithme ‘RSA (sign only)’, remplir les champs ‘Nom’, ‘Courriel’ - sur ce dernier, remplir l’adresse mail correspondante, et ne pas cochez la case ‘Expirer’ puis validez !
C’est toujours l’option --edit-key
qui sera utilisée mais cette
fois-ci avec l’option addkey
, telles que :
Code : sh
$ gpg --edit-key email@domain.tld
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
sub 4096R/******** created: 2013-03-13 expires: never usage: E
[ultimate] (1). Nom Prenom <email@domain.tld>
[ultimate] (2) [jpeg image of size 5324]
gpg> addkey
Key is protected.
You need a passphrase to unlock the secret key for
user: "Nom Prenom <email@domain.tld>"
4096-bit RSA key, ID ********, created 2013-03-13
**demande votre passphrase**
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
Your selection? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
sub 4096R/******** created: 2013-03-13 expires: never usage: E
sub 4096R/******** created: 2013-03-13 expires: never
[ultimate] (1). Nom Prenom <email@domain.tld>
[ unknown] (2) [jpeg image of size 5324]
gpg> save
La création du certificat de révocation est une étape à faire ABSOLUMENT !
En effet, celui-ci vous sera nécessaire pour révoquer votre clé GPG, ou la sous-clé de signature, si jamais vous avez perdu celle-ci, et/ou qu’elle soit volée, et/ou qu’elle soit compromise !
Il vous importe de placer ce certificat de révocation dans un endroit sûr !
Enigmail : Clic droit sur la clé, menu contextuel “Créer et enregistrer un certificat de révocation”.
GPA semble ne pas en être capable !
C’est assez simple, pour une fois :
$ gpg --output email@domain.tld.rev.asc --gen-revoke email@domain.tld
L’export de vos clés fait partie du processus nécessaire. Bien entendu, il vous incombe de mettre en lieu sûr ces fichiers, IMPÉRATIVEMENT la clé privée qui en résulte !
Enigmail : clic droit sur la clé, menu contextuel “Exporter les clés vers un fichier”
GPA : Menu ‘Clefs’ > ‘Exporter des clefs’
2ème possibilité : clic droit sur la clé en question, puis dans le menu contextuel, choisir ‘Exporter des clefs’…
$ gpg --export-secret-keys --armor email@domain.tld > email@domain.tld.private_key.asc
$ gpg --export --armor email@domain.tld > email@domain.tld.public_key.asc
Transformez les clés que nous avons créées, dites clés primaires en clés portables ou mode “protégé”, est un autre processus IMPORTANT !
Ce processus est un peu long, non-prévu dans le fonctionnement interne de GPG, peut faire peur - et donner des suées,…
Il a pour propos d’extraire les sous-clés, de les détruire du porte-clé, de les importer correctement !
ATTENTION : Une fois, en mode “protégé”, les clés ne sont plus éditables, ni modifiables… vous aurez le droit au final à l’erreur “gpg: des parties de la clef secrète ne sont pas disponibles “, et rien de ce que vous aurez pu faire, demandé, exécuté dans la modification de la clé ne sera acté, validé !
De même, vous ne pourrez pas signer une autre clé avec !
Ne cherchez pas ; ce processus n’est pas du tout géré !
Tout d’abord un aperçu de la clé, pour comparaison :
celui-ci n’est absolument pas nécessaire - juste pour aider à remarquer la légére différence, avant ce processus et après !
Code : sh
$ gpg --list-secret-keys
/home/$USER/.gnupg/secring.gpg
-----------------------------
sec 4096R/******** 2013-03-13
uid Nom Prenom <email@domain.tld>
ssb 4096R/******** 2013-03-13
ssb 4096R/******** 2013-03-13
Maintenant, le processus de transformation - que vous devez exécutez :
Code : sh
$ gpg --export-secret-subkeys email@domain.tld > ~/.gnupg/email@domain.tld.subkeys
$ gpg --delete-secret-keys email@domain.tld
$ gpg --import ~/.gnupg/email@domain.tld.subkeys
$ shred --remove ~/.gnupg/email@domain.tld.subkeys
Comparons :
Code : sh
$ gpg --list-secret-keys
/home/$USER/.gnupg/secring.gpg
-----------------------------
sec# 4096R/******** 2013-03-13
uid Nom Prenom <email@domain.tld>
ssb 4096R/******** 2013-03-13
ssb 4096R/******** 2013-03-13
En fait la différence visible/visuelle est très légère : sur la ligne
commençant par le mot sec
, celui-ci est suivi du symbole #
…
La présence du symbole dièze signifie que la sous-clé de signature ne fait pas partie du trousseau de clé !
Si le symbole dièze n'est pas présent, c'est qu'il y a eu un problème dans la phase de ce processus… refaites-le !
Voilà, vous avez suivi toutes ces étapes - c’est très bien. Elles vous garantissent d’avoir fait correctement les choses ;-)
Allez n’hésitez pas à partagez, publiez votre clé publique - informez de l’empreinte relative à votre clé publique - privilégiez le contact réel, physique lors de cet échange…
Enigmail : Menu “Serveur de clefs” > “Envoyer les clés publiques”.
2ème possibilité : clic droit sur la clé, menu contextuel “Envoyer les clés publiques vers un serveur de clefs”
GPA : Menu ‘Serveur’ > ‘Envoyer des clefs’.
2ème possibilité : clic droit sur la clé, puis dans le menu contextuel, choisissez ‘Envoyer des clefs’ ; confirmez votre choix, si cela vous est demandé en cliquant sur le bouton [Oui].
Utilisez donc l’option --send-keys "fingerprint
, tel que :
$ gpg --send-keys "fingerprint"
Si vous avez paramétré correctement votre
fichier personnel ~/.gnupg/gpg.conf
comme je vous l’ai démontré dans
mon
GPG : Du bon usage sécurisé
, alors vous n’aurez même pas besoin de spécifier le serveur, et en plus, cela se fera de manière sécurisée !
Je renvoie très fortement vers les bonnes lectures en question :
Vous retrouverez mon script de gestion de clé GPG sur mon espace git Du moins, j’espère bien qu’il soit POSIX
./mng_gpg help
./mng_gpg create
Pour information, cet outil a aussi besoin de l’outil shred
…
Jeff Starr de PersishablePress vient de publier son plugin de sécurité pour WP, nommé Blackhole for BadBots.
L’idée de départ intéressante est, dû au fait que les robots scrutateurs
du web ne respectent pas tous la déclaration du fichier robots.txt
…
C’est d’ailleurs pour cette raison qu’ils sont appelés “BadBots” ou “mauvais robots”.
Puisque ces mauvais robots ne respectent rien, on va les piéger, puis bloquer leurs adresses IP !
Commençons par télécharger la dernière mouture des scripts PHP : https://perishablepress.com/blackhole-bad-bots/#blackhole-download
Une fois l’archive décompressée, ouvrez le script index.php
, et remplissez/modifiez
correctement les valeurs des variables $from
, $recip
…
enregistrez la modification.
Pensez à modifiez l’url de contact, en lignes 206 et 229 ; et, idem pour
le script blackhole.php
en ligne 56.
Dans votre site, créez un répertoire blackhole
, dans lequel vous déposerez
les fichiers blackhole, précédemment téléchargés -
bien sûr, pas besoin du fichier .htaccess
Mettez des droits 0600 sur le fichier blackhole.dat
, si votre serveur
permet cette gestion fine…
Ensuite, modifiez vos scripts PHP de cette manière - oui, là, c’est un peu la contrainte ! :
include(realpath(getenv('DOCUMENT_ROOT')) .'/blackhole/blackhole.php');
<a rel="nofollow" style="display:none;" href="http://votre-ndd.tld/blackhole/">NE PAS Suivre ce lien où vous serez bannis - interdits d'accès - à ce site !</a>
robots.txt
:
Disallow: /blackhole/
Maintenant, modifions le fichier de configuration de votre serveur nginx
pour ajouter cette déclaration location
:
Code : nginx
location /blackhole/blackhole.dat {
satisfy any;
deny all;
}
Puis, pensez à tester votre configuration nginx, et redémarrez votre serveur !
Vous obtiendrez ainsi une belle erreur 404, si le fichier est appelé…
À partir de maintenant, quand un mauvais robot, ou quelqu’un cherchera à
pointer sur le répertoire blackhole
, et/ou un de ses fichiers, il sera
blacklisté, puis quand il reviendra, il ne lui sera pas permis d’avoir
accès au site web…
Le script vous enverra un mail ; si vous ne voulez pas en recevoir, éditez
le script index.php
, et mettez en commentaire PHP la ligne 226, commençant ainsi :
//mail($recip, $subject, $message, 'From: '. $from);
Il existe d’autres options modifiables ; là, je vous renvoie au site PerishablePress !
Version modifiée
Retrouvez la version modifiée sur mon espace git, ainsi que l’archive ZIP correspondante !
L’auteur est informé ; j’espère qu’il intégrera mes modifications ;-)
Enfin, cela fait presque deux ans, à une ou deux semaines près, que j’ai créé ma précédente clé GPG … il va falloir la renouveler, n’est-ce pas !
Il y a deux manières de faire cela :
Repousser la date d’expiration est très simple, il faut éditer la clé en utilisant son empreinte, bien-sûr : Et oui, pour rappel, on édite sa clé à partir de son empreinte gpg, et non pas sa clé gpg ou l’email correspondant !
$ gpg --edit-key "CBC8 A5AB C6A6 2F2C C414 E869 DA43 05B9 BE07 311F"
gpg (GnuPG) 2.2.27; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
La clef secrète est disponible.
sec ed25519/0xDA4305B9BE07311F
créé : 2020-01-30 expirée : 2022-01-29 utilisation : SC
confiance : ultime validité : expirée
ssb cv25519/0x9BA14C4E01678087
créé : 2020-01-30 expirée : 2022-01-29 utilisation : E
ssb ed25519/0xBA82BCDF5858BA77
créé : 2020-01-30 expirée : jamais utilisation : S
[ expirée ] (1). Stéphane HUC <consult@huc.fr.eu.org>
[ expirée ] (2) Stéphane HUC <consult@stephane-huc.net>
gpg>
Utilisons l’option expire
, tel que :
gpg> expire
Modification de la date d'expiration de la clef principale.
Veuillez indiquer le temps pendant lequel cette clef devrait être valable.
0 = la clef n'expire pas
<n> = la clef expire dans n jours
<n>w = la clef expire dans n semaines
<n>m = la clef expire dans n mois
<n>y = la clef expire dans n ans
Pendant combien de temps la clef est-elle valable ? (0) 1y
La clef expire le jeu. 23 mars 2023 09:56:03 CET
Est-ce correct ? (o/N) o
sec ed25519/0xDA4305B9BE07311F
créé : 2020-01-30 expire : 2023-03-23 utilisation : SC
confiance : ultime validité : ultime
ssb cv25519/0x9BA14C4E01678087
créé : 2020-01-30 expirée : 2022-01-29 utilisation : E
ssb ed25519/0xBA82BCDF5858BA77
créé : 2020-01-30 expire : jamais utilisation : S
[ ultime ] (1). Stéphane HUC <consult@huc.fr.eu.org>
[ ultime ] (2) Stéphane HUC <consult@stephane-huc.net>
gpg: Attention : votre sous-clef de chiffrement expire bientôt.
gpg: Vous pourriez modifier aussi sa date d’expiration.
gpg>
Ainsi que l’affiche l’avertissement, il est nécessaire de modifier aussi
les dates d’expirations de vos sous-clés, si vous en avez, en utilisant
l’option key
, tel que :
gpg> key 0xBA82BCDF5858BA77
sec ed25519/0xDA4305B9BE07311F
créé : 2020-01-30 expire : 2023-03-23 utilisation : SC
confiance : ultime validité : ultime
ssb* cv25519/0x9BA14C4E01678087
créé : 2020-01-30 expire : 2023-03-23 utilisation : E
ssb* ed25519/0xBA82BCDF5858BA77
créé : 2020-01-30 expire : jamais utilisation : S
[ ultime ] (1). Stéphane HUC <consult@huc.fr.eu.org>
[ ultime ] (2) Stéphane HUC <consult@stephane-huc.net>
gpg> expire
Are you sure you want to change the expiration time for multiple subkeys? (y/N) y
Veuillez indiquer le temps pendant lequel cette clef devrait être valable.
0 = la clef n'expire pas
<n> = la clef expire dans n jours
<n>w = la clef expire dans n semaines
<n>m = la clef expire dans n mois
<n>y = la clef expire dans n ans
Pendant combien de temps la clef est-elle valable ? (0) 1y
La clef expire le jeu. 23 mars 2023 09:57:39 CET
Est-ce correct ? (o/N) o
sec ed25519/0xDA4305B9BE07311F
créé : 2020-01-30 expire : 2023-03-23 utilisation : SC
confiance : ultime validité : ultime
ssb* cv25519/0x9BA14C4E01678087
créé : 2020-01-30 expire : 2023-03-23 utilisation : E
ssb* ed25519/0xBA82BCDF5858BA77
créé : 2020-01-30 expire : 2023-03-23 utilisation : S
[ ultime ] (1). Stéphane HUC <consult@huc.fr.eu.org>
[ ultime ] (2) Stéphane HUC <consult@stephane-huc.net>
gpg>
Faire de même pour tout autre sous-clé…
N’oubliez surtout pas d’enregister vos modifications grâce à l’option save
:
gpg> save
$
ce qui vous renverra sous votre invite shell.
Pour finir, n’oubliez pas de l’envoyer au serveur :
$ gpg --send-key "fingerprint"
.
Sauf si votre serveur est keys.OpenPGP.org, faites alors :
$ gpg --export "fingerprint" | curl -T - https://keys.openpgp.org
Normallement, vous aurez un message de réussite, tel que :
Key successfully uploaded. Proceed with verification here:
https://keys.openpgp.org/upload/***
Cliquez sur le lien ou copiez-le dans votre navigateur, et confirmez l’ajout comme il vous sera demandé par le biais du site.
Comme j’aime bien faire les choses, qu’il s’est passé près de deux ans, entre temps - voire plus -, je me penche à nouveau sur la lecture de cet article : “Guide bonnes pratiques de création GPG ”.
Une fois que vous avez créé la nouvelle, suivez ces étapes très simples :
$ gpg --default-key "fingerprint clé qui sert à signer" --sign-key "fingerprint clé à signer"
$ gpg --send-key "fingerprint"
Pour une raison ou l’autre, il vous est impératif de révoquer votre clé… alors révoquons !
Les raisons :
L’acte de révocation est un acte simple, à partir du moment où vous avez bel et bien votre fichier de révocation relatif à la clé en question !
Dans le cas où votre clé arrive à expiration, il est toujours temps de (re?)générer un certificat de révocation… je vous renvoie à la lecture de mon article : “Guide bonnes pratiques de création GPG ” au chapitre “Création du certificat de révocation” ! ;-)
Pour importer le certificat de révocation, on s’y prend ainsi :
$ gpg --import ~/.gnupg/email@domain.tld.rev.asc
Maintenant il faut l’éditer, puis utiliser l’option revkey
:
Si vous révoquez votre clé parce que :
Key has been compromised
’Key is no longer used
’.Key is superseded
’.No reason specified
’.Code :
$ gpg --edit-key email@domain.tld
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
sub 4096R/******** created: 2013-03-13 expires: never usage: E
sub 4096R/******** created: 2013-03-13 expires: never usage: S
[ultimate] (1). Nom Prenom <email@domain.tld>
[ultimate] (2) [jpeg image of size 5324]
gpg> revkey
Do you really want to revoke the selected subkeys? (y/N) **y**
Please select the reason for the revocation:
0 = No reason specified
1 = Key has been compromised
2 = Key is superseded
3 = Key is no longer used
Q = Cancel
Your decision? **votre choix**
Enter an optional description; end it with an empty line:
>
Reason for revocation: Key is no longer used
(No description given)
Is this okay? (y/N) y
You need a passphrase to unlock the secret key for
user: "Nom Prenom <email@domain.tld>"
4096-bit RSA key, ID ********, created 2013-03-13
**demande votre passhphrase**
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
This key was revoked on 2013-03-13 by RSA key ******** Nom Prenom
sub 4096R/******** created: 2013-03-13 expires: never usage: E
This key was revoked on 2013-03-13 by RSA key ******** Nom Prenom
sub 4096R/********* created: 2013-03-13 expires: never usage: S
[ultimate] (1). Nom Prenom <email@domain.tld>
[ultimate] (2) [jpeg image of size 5324]
gpg> save
Dans mon mémoriel “Guide bonnes pratiques de création GPG ” (cf : le chapitre “Transformons nos clés”), nous avons abordé le point de la transformation des clés “primaires”… juste avant j’avais rappelé la nécessité d’exporter vos clés. J’espère que vous l’avez bel et bien fait !
Nous allons utiliser les fichiers exportés des clés publiques et privés, afin de révoquer les sous-clés relatives…
$ gpg --import ~/.gnupg/email@domain.tld.public_key.asc ~/.gnupg/email@domain.tld.private_key.asc
Bien-sûr, si ces fichiers de clés sont dans un autre chemin, indiquez le bon répertoire, et le bon nom de fichier. ;-)
Maintenant, nous révoquons nos sous-clés :
Code :
$ gpg --edit-key email@domain.tld
gpg (GnuPG) 1.4.11; Copyright (C) 2010 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
sub 4096R/******** created: 2013-03-13 expires: never usage: E
sub 4096R/******** created: 2013-03-13 expires: never usage: S
[ultimate] (1). Nom Prenom <email@domain.tld>
[ultimate] (2) [jpeg image of size 5324]
gpg> key1
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
sub 4096R/******** created: 2013-03-13 expires: never usage: E
sub 4096R/******** created: 2013-03-13 expires: never usage: S
[ultimate] (1). Nom Prenom <email@domain.tld>
[ultimate] (2) [jpeg image of size 5324]
gpg> key2
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
sub 4096R/******** created: 2013-03-13 expires: never usage: E
sub 4096R/******** created: 2013-03-13 expires: never usage: S
[ultimate] (1). Nom Prenom <email@domain.tld>
[ultimate] (2) [jpeg image of size 5324]
gpg> revkey
Do you really want to revoke the selected subkeys? (y/N) y
Please select the reason for the revocation:
0 = No reason specified
1 = Key has been compromised
2 = Key is superseded
3 = Key is no longer used
Q = Cancel
Your decision? 1
Enter an optional description; end it with an empty line:
>
Reason for revocation: Key is no longer used
(No description given)
Is this okay? (y/N) y
You need a passphrase to unlock the secret key for
user: "Nom Prenom <email@domain.tld>"
4096-bit RSA key, ID ********, created 2013-03-13
**demande votre passhphrase**
You need a passphrase to unlock the secret key for
user: "Nom Prenom <email@domain.tld>"
4096-bit RSA key, ID ********, created 2013-03-13
**demande votre passhphrase une deuxième fois**
pub 4096R/******** created: 2013-03-13 expires: never usage: SC
trust: ultimate validity: ultimate
This key was revoked on 2013-03-13 by RSA key ******** Nom Prenom
sub 4096R/******** created: 2013-03-13 expires: never usage: E
This key was revoked on 2013-03-13 by RSA key ******** Nom Prenom
sub 4096R/********* created: 2013-03-13 expires: never usage: S
[ultimate] (1). Nom Prenom <email@domain.tld>
[ultimate] (2) [jpeg image of size 5324]
gpg> save
Ne pas oublier la phase importante qu’est celle d’annoncer au monde entier que votre clé ou vos sous-clés sont révoquées, en la publiant sur un des serveurs SKS.
Là, je vous renvoie à la lecture de mon Guide bonnes pratiques de création GPG , sus-nommé, au chapitre “Partagez votre clé publique !”
Je rappelle de bonnes lectures, qui m’ont inspiré, bien-sûr ce mémo :
Dans le coin, nous avons plus ou moins entendu parler, et nous l’utilisons plus ou moins, comme service SSL, je veux bien sûr parler de LetsEncrypt et de ses certificats.
Maintenant, il est possible de les “monitorer”, et pour cela, c’est LetsMonitor.org.
La première chose à faire est de s’enregistrer. Ensuite, lors de la première connexion, l’interface demande de créer un “contact”. Il est possible d’en créer plusieurs… Profitez-en pour tester si l’alerte fonctionne, en appuyant sur le bouton [ Test ] situé sur la même ligne, et dans la colonne “Action”.
Ensuite, il faut créer son premier moniteur : cliquez sur le lien “Certificates”, et renseignez le nom du Moniteur, celui du domaine relatif, et n’oubliez pas de lui attribuer un des contacts précédemment créé.
Le suivi se fait en cliquant sur le lien “Dashboard”. Et, profitez du verdict visuel… qui vous indique le nombre de jours restant, et par code couleurs :
Voilà, c’est très facile à configurer… et vous recevrez en temps opportun l’alerte nécessaire, selon le médium désiré, par courriel, ou SMS !
J’en profite pour rappeler que le robot de création s’appelle dorénavant certbot…
Un très petit mémo pour ceux qui ont cette erreur PHP :
Code : shell
php-fpm7.1[24419]: Cannot adopt OID in NET-SNMP-AGENT-MIB: nsNotifyShutdown ::= { netSnmpNotifications 2 }
php-fpm7.1[24419]: Cannot adopt OID in NET-SNMP-AGENT-MIB: nsNotifyRestart ::= { netSnmpNotifications 3 }
php-fpm7.1[24419]: Cannot adopt OID in UCD-SNMP-MIB: laErrMessage ::= { laEntry 101 }
php-fpm7.1[24419]: Cannot adopt OID in UCD-SNMP-MIB: laErrorFlag ::= { laEntry 100 }
Soit vous enlevez les modules SNMP de PHP, ce qui pour Debian, ou Ubuntu donne :
apt purge $(dpkg -l | awk '/php(.*)-snmp/ { print $2 }')
Soit vous installez le package relatif à SNMP :
apt install snmp
Voici un petit truc et astuce, si dans vos log, vous avez le message d’erreur suivant :
InnoDB: Error: page 3 log sequence number 43384293 is in the future! Your database may be corrupt or you may have copied the InnoDB tablespace but not the InnoDB log files
Commencez par vérifier que vos bases sont dans un état correct avec
l’outil myslqcheck
.
Le moyen le plus facile est :
Voici un autre petit truc et astuce, si dans vos log, vous avez le message d’erreur suivant :
[Warning] InnoDB: Cannot open table mysql/gtid_slave_pos from the internal data dictionary of InnoDB though the .frm file for the table exists. See http://dev.mysql.com/doc/refman/5.6/en/ ... oting.html for how you can resolve the problem.
Ce message d’erreur peut-être à-propos des tables :
mysql/gtid_slave_pos
mysql/innodb_index_stats
mysql/innodb_table_stats
D’autres tables peuvent être concernées !
Sachez que c’est une erreur qui arrive, généralement, après une mise-à-jour du serveur !
La meilleure manière de le résoudre est :
mysql_upgrade
avec l’option --force
par le compte administrateur de MySQL/MariaDB, tel que :
# mysql_upgrade --force -u admin_db -p
Mais qu’est donc l’IOMMU ? Input/Output Memory Management Unit en français, Unité de Gestion des Entrées/Sorties en Mémoire
C’est une sorte de pare-feu matériel, pour les ports PCI, et VGA.
Hormis le fait de posséder l’une des architectures sus-nommées, il vous faut avoir à minima un kernel Linux 2.6…
activez l’option dans le BIOS de votre machine !
Vous pouvez forcer son usage, ce qui est recommandé, en éditant votre fichier :
/etc/defaut/grub
/boot/grub/menu.lst
iommu=force
sur la ligne GRUB_CMDLINE_LINUX
…Mettez à jour grub
!
⇒ Un très bon document a été écrit pour le SSTIC en 2010, à ce propos en disant de celle-ci :
Ce document nommé “Analyse de l’efficacité du service fourni par une IOMMU” décrit comment cette unité de gestion matérielle interagit avec le système GNU/Linux, et comment malheureusement il est possible de la “leurrer” pour mener des attaques réseaux, par exemple, à partir d’une interface Firewire, mais aussi mène à réfléchir sur son bon usage.
=> Un autre document démontrant une attaque possible par le biais d’une interface FPGA sur PCI-E.
=> Une troisième source d’informations intéressantes : Le “NP Linux Configuration” !
Chkrootkit émet cette alerte : Searching for Linux/Ebury - Operation Windigo ssh… Possible Linux/Ebury - Operation Windigo installetd
Déjà, si votre installation est fraîche, ne paniquez pas ; de toute façon, cela ne sert jamais à rien !
Ne paniquez pas si vous venez de mettre-à-jour vers Ubuntu - cela touche les versions 15.10, 16.04 LTS - ( et toutes les distributions basées dessus, telle que Linux Mint) ; et, idem si vous avez eu la bêtise de passer de votre version stable de Debian à une Testing, ou si vous avez fait des màj sur votre Sid !
En effet ce rootkit Ebury, qui sévit depuis 2014, modifie la librairie “libkeyutils”
pour ajouter une option -G
au binaire SSH, et/ou remplace les binaires
liés au projet OpenSSH, tels que ssh, ssh-add, etc…
ce qui permet la prise de contrôle à distance et surtout le vol de données.
SAUF que depuis la version 6.8 d’OpenSSH, l’option ‘-G’ existe !
(c’est même un alias de l’option -T
)
Ce qui fausse le résultat de détection de chkrootkit !
De même la commande suivante fausse le résultat si vous avez une version supérieure ou égale à la 6.8 d’OpenSSH :
$ ssh -G 2>&1 | grep -e illegal -e unknown > /dev/null && echo “System clean” || echo “System infected”
De plus, sachez qu’il existe une déclaration de bogue de faux positif :
Alors comment savoir si c’est un faux positif ou non !?
Commençons par analysez votre mémoire partagée SHM, par le biais de la
commande # ipcs -m
… avec des droits admin.
Code : sh
# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch
(...)
0x000010e0 465272836 root 666 3282312 0
Code : sh
# ipcs -m -p
------ Shared Memory Creator/Last-op PIDs --------
shmid owner cpid lpid
(...)
465272836 root 15029 17377
Vérifier qu’un tel processus fonctionne - remplacez par le numéro de pid
que vous avez trouvé - en interrogeant ps
:
Code : sh
# ps aux | grep 15029
root 11531 0.0 0.0 103284 828 pts/0 S+ 16:40 0:00 grep 15029
root 15029 0.0 0.0 66300 1204 ? Ss Jan26 0:00 /usr/sbin/sshd
Le processus en question étant identifié comme ssh, c’est un très bel indicateur de compromission !
Pas la peine d’aller plus loin, si c’est malheureusement votre cas… 😟 😧
libkeyutils.so
dans le répertoire /lib
:
# find /lib* -type f -name libkeyutils.so* -exec ls -la {} \;
-rw-r--r-- 1 root root 14256 Dec 10 2015 /lib/x86_64-linux-gnu/libkeyutils.so.1.5
/lib
, appelée libns2.so
:
# find /lib* -type f -name libns2.so
Sur un système sain, la commande ne retourne rien !L’usage du binaire netstat nous permet de nous assurer d’un flux non désiré :
# netstat -nap | grep "@/proc/udevd"
Sur un système sain, vous n’aurez absolument aucun retour !
L’autre binaire qui permet de s’assurer d’un flux sain, est l’usage de
la commande tcpdump -p
… qui peut vous dévoiler des informations, telles que :
“msg:”Linux/Ebury SSH backdoor data exfiltration…”
néanmoins, cela n’est malheureusement pas probant, puisque les récentes
versions du rootkit tendent à cacher ce genre d’informations !
Si votre système est bel et bien sain, malgré le message de l’outil chkrootkit, tant mieux. Il va vous falloir attendre que le binaire soit corrigé, vous avez donc bel et bien affaire au faux positif. En attendant, continuez de vérifier…
Dans le cas contraire, la seule recommandation valable est la réinstallation complète du système. Profitez-en pour vérifiez que vos stations ne soient pas infectées !
Une fois fait, ne réutilisez pas les mêmes mots-de-passe, changez toutes vos clés SSH, et profitez pour en créer correctement des clés SSH fortes …
Si vous avez besoin/voulez plus d’informations sur ce rootkit, il y a deux lectures très intéressantes, en anglais - les informations que je vous restitue en sont tirées - :
Pour information, à ce jour, les outils rkhunter et clamav ne seraient pas capables de le détecter…
Un petit mémo concernant la complainte de Lynis : Purge old/removed packages (x found) with aptitude purge or dpkg –purge command. This will cleanup old configuration files, cron jobs and startup scripts. [ PKGS-7346 ]
C’est sa manière de dire qu’il reste des traces de configurations de paquets/binaires qui ont été désinstallés.
Sur Debian, Ubuntu, et assimilées - cela vous permet de vous assurer des paquets qui ont été supprimés, dont il reste les fichiers de configuration - :
$ dpkg --get-selections | awk '/deinstall/ { print $1 }'
Sur Debian, Ubuntu, et consorts :
⇒ avec apt :
# apt purge $(dpkg --get-selections | awk '/deinstall/ { print $1 }')
⇒ avec dpkg :
# dpkg --purge $(dpkg --get-selections | awk '/deinstall/ { print $1 }')
Mémo à-propos de la suggestion de Lynis : Default umask in /etc/init.d/rc could be more strict like 027 [ AUTH-9328 ]
En effet le Guide de Recommandations d’un Système GNU/Linux de l’ANSSI, au chapitre 6.1.5 Umask, nous rappelle à juste titre que :
0022
est considérée très permissive,umask
système régit par le fichier /etc/init.d/rc
doit
être positionné sur 0027
, ce qui fige les droits permissifs, tels
que lecture autorisée pour l’utilisateur et son groupe, et modifiable
uniquement par son créateur.Il faut modérer le fait que pour toutes les distributions systemd, tels que sont maintenant la plupart des Debian, et Ubuntu, il faut modifier le masque système dans le propre fichier de configuration du service à configurer.
# sed -i -e "s#umask 022#umask 027#" /etc/init.d/rc
Tant qu’à faire, profitons-en pour modifier la valeur du umask
utilisateurs
qui doit être paramétré à 077
!
/etc/profile
./etc/login.defs
.Sur une Debian, *Buntu (et assimilée), avec des droits administrateurs :
# apt install rkhunter
Très classiquement, il faut éditer le fichier /etc/rkhunter.conf
,
toujours avec les droits administrateurs, pour changer quelques informations.
MAIL-ON-WARNING=yourmail@yourdomain.com
MAIL-ON-WARNING="yourmail@yourdomain.com"
PKGMGR=DPKG
L’autre fichier à éditer est le fichier /etc/default/rkhunter
:
CRON_DAILY_RUN="true"
, et
REPORT_EMAIL="yourmail@yourdomain.net"
Ceci étant fait, voici les différentes possibilités de l’utiliser :
-c
, --check
ou --checkall
- ces
deux dernières options sont dépendantes de la version de rkhunter !--update
./etc/rkhunter.conf
, utilisez l’option --propupd
.man rkhunter
dans votre terminal console,
vous en apprendra beaucoup plus…Retrouvez ci-dessous la traduction EN → FR de l’article dispary “How to install LibertyBSD or OpenBSD on a libreboot system”, écrit sur le site ‘Libreboot.org’.
NOTE : Ce guide a été écrit pour OpenBSD par la personne qui a contribué, mais le projet libreboot recommande LibertyBSD. LibertyBSD est une version d’OpenBSD sans logiciel propriétaire dans les dépôts ( OpenBSD distribue les micro-programmes blob pour les périphériques à l’intérieur du noyau ). Allez sur le site web de LibertyBSD
À FAIRE : testez sur LibertyBSD en priorité dans ce guide.
Cette section relate la préparation, le démarrage et l’installation
d’OpenBSD sur votre système libreboot, n’utilisant rien de plus qu’une
clé USB (et dd
). Cette procédure a été testée seulement sur un Lenovo
ThinkPad x200.
Cette section est seulement en rapport avec GRUB. Pour depthcharge (utilisé sur les périphériques CrOS dans libreboot), les instructions doivent encore être écrites dans la documentation de libreboot.
install60.fs est l’image d’installation d’OpenBSD 6.0. Adaptez le nom du fichier selon que vous utilisez une version différente d’OpenBSD ou LibertyBSD.
Si vous avez téléchargé votre ISO d’un système LibertyBSD ou OpenBSD, voici comment créer un périphérique USB de LibertyBSD/OpenBSD démarrable :
Connectez le périphérique USB. Vérifiez dmesg :
$ dmesg | tail
Vérifiez pour confirmer quelle unité de disque est utilisée, par exemple,
si vous pensez que cela est sd3
:
$ disklabel sd3
Vérifiez qu’il n’a pas été monté automatiquement. Si cela était le cas, démontez-le. Par exemple :
$ doas umount /dev/sd3i
dmesg
vous dit quel est le périphérique. Écrasez le lecteur, en
écrivant l’installeur d’OpenBSD avec dd
. Par exemple :
$ doas dd if=install60.fs of=/dev/rsdXc bs=1M; sync
Vous devriez maintenant être capable de démarrer l’installeur depuis votre périphérique USB. Continuez la lecture, pour information afin de savoir comment faire.
Cette page sur le site web de NetBSD montre comment créer un périphérique USB NetBSD démarrable depuis NetBSD lui-même. Vous devriez utiliser la méthode dd documentée ici. Ceci fonctionne aussi avec l’image d’OpenBSD.
Cette page sur le site web de FreeBSD montre comment créer un périphérique USB démarrable pour installer FreeBSD. Utilisez dd sur cette page. Vous pouvez aussi utiliser les mêmes instructions avec une image ISO d’OpenBSD.
Si vous avez téléchargé votre ISO sur un système GNU/Linux, voici comment créer le périphérique USB démarrable d’OpenBSD :
Connectez le périphérique USB. Vérifiez dmesg :
$ dmesg
Vérifiez lsblk
pour confirmer quel lecteur est utilisé :
$ lsblk
Vérifiez qu’il n’a pas été monté automatiquement. Si cela était, démontez-le. Par exemple :
$ sudo umount /dev/sdX\*
# umount /dev/sdX\*
dmesg
vous dit quel est le périphérique. Écrasez le lecteur, en
écrivant l’installeur d’OpenBSD avec dd
. Par exemple :
$ sudo dd if=install60.fs of=/dev/sdX bs=8M; sync
# dd if=install60.fs of=/dev/sdX bs=8M; sync
Vous devriez maintenant être capable de démarrer l’installeur depuis votre périphérique USB. Continuez la lecture, pour information afin de savoir comment faire.
Pressez la touche <kbd>c</kbd>
dans GRUB
pour accéder à la ligne de
commande :
grub> kopenbsd (usb0,openbsd1)/6.0/amd64/bsd.rd
grub> boot
Cela démarrera l’installeur d’OpenBSD. Suivez le processus normal pour installer OpenBSD.
Cela ne fonctionne pas. Vous pouvez modifier la procédure ci-dessus (celle de l’installation sans chiffrement) pour installer OpenBSD en utilisant le chiffrement de disque dur, et cela semble fonctionner, excepté que démarrer une installation d’OpenBSD + FDE en utilisant libreboot+Grub2 n’est pas clair. Si pour vous cela fonctionne, veuillez nous le faire savoir.
Si démarrer en mode texte (le mode framebuffer pourrait également fonctionner aussi), il est possible de charger le chargeur de démarrage d’OpenBSD ou de LibertyBSD depuis le secteur MBR sur le périphérique de stockage interne. De cette manière, il serait possible de démarrer avec une installation d’OpenBSD ou de LibertyBSD chiffrée. Veuillez nous faire savoir ( les détails de contact sont sur la page d’accueil de libreboot ) si vous arrivez à le faire fonctionner ainsi.
Alternativement, ce serait une bonne chose de porter OpenBSD à ce qu’il prenne en charge nativement coreboot, ou de porter la libpayload (la bibliothèque de chargement dans coreboot ; c’est une bibliothèque C basique et quelques fonctions pour certaines opérations, tel que text/bitmap). Cela serait idéal, parce qu’il serait possible de démarrer vraiment une installation d’OpenBSD ou de LibertyBSD pleinement chiffrée, en mettant tout dans la puce flash.
Alternativement, modifier GRUB pour supporter le démarrage d’installations d’OpenBSD pleinement chiffrées serait possible, mais probablement pas faisable ; c’est une base de code étrangère au projet OpenBSD, pas bien intégrée, d’autant que le chargeur de démarrage d’OpenBSD est déjà fonctionnel.
Pressez la touche c dans GRUB
pour accéder à la ligne de
commande :
grub> kopenbsd -r sd0a (ahci0,openbsd1)/bsd
grub> boot
OpenBSD devrait démarrer. Excellent !
Si vous ne voulez pas utiliser la ligne de commande GRUB et de taper une commande au démarrage d’OpenBSD à chaque fois, vous pouvez créer une configuration GRUB qui tiendra compte de votre installation d’OpenBSD et qui sera utilisée automatiquement par libreboot.
Sur votre partition racine d’OpenBSD, créez le répertoire /grub
et
ajoutez-le au fichier libreboot_grub.cfg
. Ajoutez ces lignes à
l’intérieur de libreboot_grub.cfg
:
default=0 timeout=3 menuentry "OpenBSD" {
kopenbsd -r sd0a (ahci0,openbsd1)/bsd
}
Lors de votre prochain démarrage, vous verrez le menu du vieux Grub pendant quelques secondes, puis vous verrez le nouveau menu avec seulement OpenBSD dans la liste. Après 3 secondes OpenBSD démarrera, ou vous pouvez le sélectionner en appuyant sur la touche ENTRÉE pour démarrer.
La plupart de ces problèmes arrivent par l’usage de libreboot avec le mode texte de coreboot en lieu et place du mode framebuffer de coreboot. Ce mode est utile pour le démarrage de charge utile tel que memtest86+ qui ont besoin du mode texte, mais pour OpenBSD, cela est problématique lors de la bascule vers le mode framebuffer, car non supporté.
Dans la plupart des cas, vous devriez utiliser les images ROM vesafb.
Exemple de nom de fichier : libreboot_ukdvorak_vesafb.rom
.
trouvé
Vos noms et numéros de périphériques (tels que usb0, usb1, sd0, sd1, wd0, ahci0, hd0, etc…) peuvent différer. Utilisez la complétion TAB.
Copyright © 2016 Scott Bonds scott@ggr.com Copyright © 2016 Leah Rowe info@minifree.org Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License Version 1.3 or any later version published by the Free Software Foundation with no Invariant Sections, no Front Cover Texts, and no Back Cover Texts. A copy of this license is found in ../fdl-1.3.html
J’ai écrit historiquement cette traduction sur le wiki de la communauté “OpenBSD Pour Tous”.
Petit script pour avoir une icône dans la barre de notifications et régler le volume sonore. Il est destiné aux environnements minimalistes comme fluxbox, et ne dépend donc de rien en particulier sauf python et gi.
Il est tout vilain, n’hésitez pas à l’améliorer ;)
#!/usr/local/bin/python3
import os
import sys
from gi import require_version
require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk
name="Volume"
def get_lvl():
cmd = "mixerctl -n outputs.master"
result = os.popen(cmd)
result = result.readline().split(",")[0]
lvl= int(int(result)/255*100)
return lvl
def get_mute():
cmd = "mixerctl -n outputs.master.mute"
result = os.popen(cmd)
result = result.readline().strip()
return(result)
class Menu:
def destroy(self, widget, data=None):
Gtk.main_quit()
def set_icon(self):
if get_mute() == "on":
self.tray.set_from_icon_name("stock_volume-mute")
else:
lvl = get_lvl()
if lvl == 0:
self.tray.set_from_icon_name("stock_volume-0")
elif lvl < 20:
self.tray.set_from_icon_name("stock_volume-min")
elif lvl < 70:
self.tray.set_from_icon_name("stock_volume-med")
elif lvl > 70:
self.tray.set_from_icon_name("stock_volume-max")
def __init__(self):
get_mute()
self.tray = Gtk.StatusIcon()
self.set_icon()
self.tray.connect('popup-menu', self.on_right_click)
self.tray.connect('activate', self.on_left_click)
self.tray.connect('scroll_event', self.on_scroll)
self.tray.set_tooltip_text('Volume : {}%'.format(get_lvl()))
def on_scroll(self, widget, event):
if event.direction == Gdk.ScrollDirection.DOWN:
os.system("mixerctl outputs.master=-10")
elif event.direction == Gdk.ScrollDirection.UP:
os.system("mixerctl outputs.master=+10")
self.set_icon()
def on_left_click(self, event):
os.system("mixerctl outputs.master.mute=toggle")
self.set_icon()
def on_right_click(self, icon, button, time):
# Quit-menu item
self.menu = Gtk.Menu()
box = Gtk.Box()
box.set_spacing(10)
img = Gtk.Image()
img.set_from_stock(Gtk.STOCK_CANCEL, Gtk.IconSize.MENU)
label = Gtk.Label("Quit")
box.add(img)
box.add(label)
quit = Gtk.MenuItem()
quit.add(box)
quit.connect("activate", Gtk.main_quit)
self.menu.append(quit)
self.menu.show_all()
self.menu.popup(None, None, None, self.tray, button, time)
def main(self):
Gtk.main()
if __name__ == "__main__":
app = Menu()
app.main()
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Je ne parlerais pas de l’installation d’OpenBSD en soit. Je fais fonctionner ce portable sous OpenBSD depuis mes débuts avec la 5.9 !
Cet Alienware AW13 est la première génération.
Certaines modifications systèmes sont nécessaires.
/etc/sysctl.conf
Sous OpenBSD 6.4 & 6.5, il y a un problème avec l’horloge matérielle, ce qui a pour conséquence que la saisie de caractères se retrouve démultiplier en session X.
Pour le régler, il faut ajouter au fichier /etc/sysctl.conf
:
kern.timecounter.hardware=acpihpet0
/etc/wsconsctl.conf
display.vblank=on
mouse.tp.tapping=1
vblank
./etc/X11/xorg.conf
Il y a un soucis de “tearing”, problème d’accélération graphique avec le GPU Intel, c-à-d des saccades.
Il est donc nécessaire de créer le fichier /etc/X11/xorg.conf
et de le
remplir ainsi :
Section "Device"
Identifier "intel"
Driver "intel"
Option "HotPlug" "true"
Option "TearFree" "true" #false by default (avoid tearing)
EndSection
TearFree
qui règle le problème.HotPlug
prend en charge les périphériques qui se montent à
chaud…OpenBSD 6.6 (GENERIC.MP) #372: Sat Oct 12 10:56:27 MDT 2019
deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 8487260160 (8094MB)
avail mem = 8217325568 (7836MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.8 @ 0xec580 (74 entries)
bios0: vendor Alienware version "A08" date 01/25/2018
bios0: Alienware Alienware 13
acpi0 at bios0: ACPI 5.0
acpi0: sleep states S0 S3 S4 S5
acpi0: tables DSDT FACP APIC FPDT FIDT MCFG HPET SSDT UEFI SSDT ASF! SLIC SSDT SSDT SSDT SSDT CSRT SSDT
acpi0: wakeup devices PEG0(S4) PEGP(S4) PEG1(S4) PEGP(S4) PEG2(S4) PEGP(S4) RP01(S4) PXSX(S4) RP02(S4) PXSX(S4) RP03(S4) PXSX(S4) RP04(S4) PXSX(S4) RP05(S4) PEGP(S4) [...]
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz, 799.46 MHz, 06-45-01
cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,TSC_ADJUST,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,MD_CLEAR,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,MELTDOWN
cpu0: 256KB 64b/line 8-way L2 cache
cpu0: smt 0, core 0, package 0
mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges
cpu0: apic clock running at 99MHz
cpu0: mwait min=64, max=64, C-substates=0.2.1.2.4.1.1.1, IBE
cpu1 at mainbus0: apid 2 (application processor)
cpu1: Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz, 799.32 MHz, 06-45-01
cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,TSC_ADJUST,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,MD_CLEAR,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,MELTDOWN
cpu1: 256KB 64b/line 8-way L2 cache
cpu1: smt 0, core 1, package 0
cpu2 at mainbus0: apid 1 (application processor)
cpu2: Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz, 799.31 MHz, 06-45-01
cpu2: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,TSC_ADJUST,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,MD_CLEAR,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,MELTDOWN
cpu2: 256KB 64b/line 8-way L2 cache
cpu2: smt 1, core 0, package 0
cpu3 at mainbus0: apid 3 (application processor)
cpu3: Intel(R) Core(TM) i5-4210U CPU @ 1.70GHz, 799.31 MHz, 06-45-01
cpu3: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,FMA3,CX16,xTPR,PDCM,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,ABM,PERF,ITSC,FSGSBASE,TSC_ADJUST,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,MD_CLEAR,IBRS,IBPB,STIBP,L1DF,SSBD,SENSOR,ARAT,XSAVEOPT,MELTDOWN
cpu3: 256KB 64b/line 8-way L2 cache
cpu3: smt 1, core 1, package 0
ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 20, 40 pins
acpimadt0: bogus nmi for apid 0
acpimadt0: bogus nmi for apid 2
acpimadt0: bogus nmi for apid 1
acpimadt0: bogus nmi for apid 3
acpimcfg0 at acpi0
acpimcfg0: addr 0xf8000000, bus 0-63
acpihpet0 at acpi0: 14318179 Hz
acpiprt0 at acpi0: bus 0 (PCI0)
acpiprt1 at acpi0: bus -1 (PEG0)
acpiprt2 at acpi0: bus -1 (PEG1)
acpiprt3 at acpi0: bus -1 (PEG2)
acpiprt4 at acpi0: bus -1 (RP01)
acpiprt5 at acpi0: bus -1 (RP02)
acpiprt6 at acpi0: bus 1 (RP03)
acpiprt7 at acpi0: bus 2 (RP04)
acpiprt8 at acpi0: bus 3 (RP05)
acpiprt9 at acpi0: bus -1 (RP06)
acpiprt10 at acpi0: bus -1 (RP07)
acpiprt11 at acpi0: bus -1 (RP08)
acpiec0 at acpi0: not present
acpiec1 at acpi0
acpicpu0 at acpi0: C2(200@148 mwait.1@0x33), C1(1000@1 mwait.1)
acpicpu1 at acpi0: C2(200@148 mwait.1@0x33), C1(1000@1 mwait.1)
acpicpu2 at acpi0: C2(200@148 mwait.1@0x33), C1(1000@1 mwait.1)
acpicpu3 at acpi0: C2(200@148 mwait.1@0x33), C1(1000@1 mwait.1)
acpipwrres0 at acpi0: PG00, resource for PEG0
acpipwrres1 at acpi0: PG01, resource for PEG1
acpipwrres2 at acpi0: PG02, resource for PEG2
acpipwrres3 at acpi0: PC05, resource for RP05
acpitz0 at acpi0: critical temperature is 105 degC
acpitz1 at acpi0: critical temperature is 105 degC
acpipci0 at acpi0 PCI0: 0x00000000 0x00000011 0x00000001
acpicmos0 at acpi0
"INT3403" at acpi0 not configured
acpibat0 at acpi0: BAT1 model "PABAS0241231" serial 0x75d1 type Li-Ion oem "TOSHIBA"
acpiac0 at acpi0: AC unit online
acpibtn0 at acpi0: LID0
"INT33C7" at acpi0 not configured
"INTL9C60" at acpi0 not configured
dwiic0 at acpi0 I2C1 addr 0xfe105000/0x1000 irq 7
iic0 at dwiic0
ihidev0 at iic0 addr 0x2cdwiic0: timed out reading remaining 29
, failed fetching initial HID descriptor
"SMO8810" at acpi0 not configured
"INT3402" at acpi0 not configured
"PNP0C14" at acpi0 not configured
acpibtn1 at acpi0: PWRB
"PNP0C14" at acpi0 not configured
"DELLABCE" at acpi0 not configured
"PNP0C32" at acpi0 not configured
"PNP0C32" at acpi0 not configured
"PNP0C32" at acpi0 not configured
"CPL0002" at acpi0 not configured
"INT3400" at acpi0 not configured
acpivideo0 at acpi0: GFX0
acpivout0 at acpivideo0: DD1F
cpu0: using VERW MDS workaround (except on vmm entry)
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel Core 4G Host" rev 0x0b
inteldrm0 at pci0 dev 2 function 0 "Intel HD Graphics" rev 0x0b
drm0 at inteldrm0
inteldrm0: msi
azalia0 at pci0 dev 3 function 0 "Intel Core 4G HD Audio" rev 0x0b: msi
azalia0: No codecs found
"Intel Core 4G Thermal" rev 0x0b at pci0 dev 4 function 0 not configured
xhci0 at pci0 dev 20 function 0 "Intel 8 Series xHCI" rev 0x04: msi, xHCI 1.0
usb0 at xhci0: USB revision 3.0
uhub0 at usb0 configuration 1 interface 0 "Intel xHCI root hub" rev 3.00/1.00 addr 1
"Intel 8 Series MEI" rev 0x04 at pci0 dev 22 function 0 not configured
azalia1 at pci0 dev 27 function 0 "Intel 8 Series HD Audio" rev 0x04: msi
azalia1: codecs: Realtek/0x0255
audio0 at azalia1
ppb0 at pci0 dev 28 function 0 "Intel 8 Series PCIE" rev 0xe4: msi
pci1 at ppb0 bus 1
vendor "Atheros", unknown product 0x003e (class network subclass miscellaneous, rev 0x20) at pci1 dev 0 function 0 not configured
ppb1 at pci0 dev 28 function 3 "Intel 8 Series PCIE" rev 0xe4: msi
pci2 at ppb1 bus 2
alc0 at pci2 dev 0 function 0 "Attansic Technology E2200" rev 0x10: msi, address 34:e6:d7:1b:7f:14
atphy0 at alc0 phy 0: AR8035 10/100/1000 PHY, rev. 9
ppb2 at pci0 dev 28 function 4 "Intel 8 Series PCIE" rev 0xe4: msi
pci3 at ppb2 bus 3
vendor "NVIDIA", unknown product 0x1392 (class display subclass 3D, rev 0xa2) at pci3 dev 0 function 0 not configured
ehci0 at pci0 dev 29 function 0 "Intel 8 Series USB" rev 0x04: apic 2 int 23
usb1 at ehci0: USB revision 2.0
uhub1 at usb1 configuration 1 interface 0 "Intel EHCI root hub" rev 2.00/1.00 addr 1
pcib0 at pci0 dev 31 function 0 "Intel 8 Series LPC" rev 0x04
ahci0 at pci0 dev 31 function 2 "Intel 8 Series AHCI" rev 0x04: msi, AHCI 1.3
ahci0: port 0: 6.0Gb/s
scsibus1 at ahci0: 32 targets
sd0 at scsibus1 targ 0 lun 0: <ATA, ST500LT012-1DG14, 0001> naa.5000c5009d2436d7
sd0: 476940MB, 512 bytes/sector, 976773168 sectors
ichiic0 at pci0 dev 31 function 3 "Intel 8 Series SMBus" rev 0x04: apic 2 int 18
iic1 at ichiic0
iic1: addr 0x29 07=ff 0f=33 10=08 11=05 12=8f 13=54 14=a0 15=31 16=28 17=1f 18=22 19=b9 1a=60 1b=65 1c=c0 1e=20 20=7f 22=40 25=40 27=ff 29=f3 2b=ff 2d=45 2f=20 30=95 31=26 32=0e 33=10 87=ff 8f=33 90=08 91=05 92=8f 93=54 94=a0 95=31 96=28 97=1f 98=22 99=b9 9a=60 9b=65 9c=c0 9e=20 a0=7f a2=40 a5=40 a7=df a9=f1 ab=fc ad=3e af=20 b0=95 b1=25 b2=0e b3=10 words 00=0000 01=0000 02=0000 03=0000 04=0000 05=0000 06=0000 07=ffff
spdmem0 at iic1 addr 0x50: 4GB DDR3 SDRAM PC3-12800 SO-DIMM
spdmem1 at iic1 addr 0x52: 4GB DDR3 SDRAM PC3-12800 SO-DIMM
isa0 at pcib0
isadma0 at isa0
pckbc0 at isa0 port 0x60/5 irq 1 irq 12
pckbd0 at pckbc0 (kbd slot)
wskbd0 at pckbd0: console keyboard
pms0 at pckbc0 (aux slot)
wsmouse0 at pms0 mux 0
pms0: Synaptics clickpad, firmware 8.1, 0x1e2b1 0x840300
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
vmm0 at mainbus0: VMX/EPT
uhidev0 at uhub0 port 1 configuration 1 interface 0 "E-Signal USB Gaming Mouse" rev 2.00/1.42 addr 2
uhidev0: iclass 3/1
ums0 at uhidev0: 5 buttons, Z and W dir
wsmouse1 at ums0 mux 0
uhidev1 at uhub0 port 1 configuration 1 interface 1 "E-Signal USB Gaming Mouse" rev 2.00/1.42 addr 2
uhidev1: iclass 3/0, 6 report ids
ukbd0 at uhidev1 reportid 1: 8 variable keys, 6 key codes
wskbd1 at ukbd0 mux 1
uhid0 at uhidev1 reportid 2: input=1, output=0, feature=0
uhid1 at uhidev1 reportid 3: input=2, output=0, feature=0
uhid2 at uhidev1 reportid 6: input=3, output=0, feature=0
uhidev2 at uhub0 port 1 configuration 1 interface 2 "E-Signal USB Gaming Mouse" rev 2.00/1.42 addr 2
uhidev2: iclass 3/0
uhid3 at uhidev2: input=32, output=32, feature=8
uvideo0 at uhub0 port 6 configuration 1 interface 0 "CN036P597248751HABEMA00 Integrated_Webcam_FHD" rev 2.00/47.18 addr 3
video0 at uvideo0
uhidev3 at uhub0 port 7 configuration 1 interface 0 "Alienware AW13" rev 0.02/0.00 addr 4
uhidev3: iclass 3/0, 2 report ids
uhid4 at uhidev3 reportid 1: input=8, output=0, feature=0
uhid5 at uhidev3 reportid 2: input=0, output=8, feature=0
uhub2 at uhub1 port 1 configuration 1 interface 0 "Intel Rate Matching Hub" rev 2.00/0.04 addr 2
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
scsibus3 at softraid0: 256 targets
root on sd0a (25417e6d803941c6.a) swap on sd0b dump on sd0b
[drm] ACPI BIOS requests an excessive sleep of 2000 ms, using 1500 ms instead
inteldrm0: 1920x1080, 32bpp
wsdisplay0 at inteldrm0 mux 1: console (std, vt100 emulation), using wskbd0
wskbd1: connecting to wsdisplay0
wsdisplay0: screen 1-5 added (std, vt100 emulation)
$ sysctl hw.sensors
hw.sensors.cpu0.temp0=48.00 degC
hw.sensors.acpitz0.temp0=27.80 degC (zone temperature)
hw.sensors.acpitz1.temp0=29.80 degC (zone temperature)
hw.sensors.acpibat0.volt0=14.80 VDC (voltage)
hw.sensors.acpibat0.volt1=17.02 VDC (current voltage)
hw.sensors.acpibat0.current0=65.53 A (rate)
hw.sensors.acpibat0.amphour0=3.06 Ah (last full capacity)
hw.sensors.acpibat0.amphour1=0.30 Ah (warning capacity)
hw.sensors.acpibat0.amphour2=0.09 Ah (low capacity)
hw.sensors.acpibat0.amphour3=3.06 Ah (remaining capacity), OK
hw.sensors.acpibat0.amphour4=3.54 Ah (design capacity)
hw.sensors.acpibat0.raw0=0 (battery full), OK
hw.sensors.acpibat0.raw1=0 (discharge cycles)
hw.sensors.acpiac0.indicator0=On (power supply)
hw.sensors.acpibtn0.indicator0=On (lid open)
Testée sur OpenBSD stable : 6.0 ⇒ 6.6 !
La partie impression fonctionne très bien…
Indiquez à Cups d’installer le fichier ppd relatif à la version BX525WD ou BX535WD.
Si vous avez installer le paquet gutenprint, vous aurez le choix entre sa version et celle de foomatic.
Choisissez le protocole lpd
, c’est celui qui fonctionne le mieux…
Tel que : lpd://adr_ip/PASSTHRU
Si Avahi est installé, elle est vu par le biais du protocole DNS-SD, voire mDNS, elle s’installe, mais après lors d’impression, cups n’arrive pas à discuter avec…
Pensez à redémarrer le service CUPS !
Après avoir installer
les paquets : sane-backends xsane
, il vous faudra :
/etc/sane.d/dll.conf
pour ajouter : epkowa./etc/sane.d/epkowa.conf
, et modifiez-le :
Une fois modifié, vous pourrez exécuter xsane
.
Exemple du fichier epkowa.conf
:
# epkowa.conf -- sample configuration for the EPKOWA SANE backend
# Copyright (C) 2004, 2008, 2009 Olaf Meeuwissen
#
# See sane-epkowa(5), sane-usb(5) and sane-scsi(5) for details.
# Detect all devices supported by the backend.
# If you don't have a SCSI device, you can comment out the "scsi"
# keyword. Similarly for the other keywords.
#
usb
scsi
# For any USB scanner not known to the backend (yet), you may, at your
# own peril(!!), force the backend to recognise and use it via libusb.
# You can do so by the following configuration command:
#
# usb <USB vendor ID> <USB product ID>
#
# SEIKO EPSON's USB vendor ID is '0x04b8' (without quotes). In order
# to find the USB product ID, use lsusb(1).
# A sample configuration for the Epson Perfection 1650 (Epson GT-8200),
# which has a product ID of 0x0110, would look as follows:
#
#usb 0x04b8 0x0110
# For SCSI devices not detected, you can add an entry like:
#
# scsi EPSON GT-20000
#
# where the GT-20000 bit corresponds to the SCSI model information as
# shown in the output of dmesg(1) or in the /var/log/kern.log file.
# Network attached devices may be made to work by first installing the
# (non-free) iscan-network-nt package and then adding configuration lines
# as per information below.
#
# For each network attached device, you must add an entry as follows:
#
# net <IP-address|hostname> [port-number]
#
# Ask your network administrator for the device's IP address or check
# for yourself on the panel (if it has one). The port-number is very
# optional and defaults to 1865.
# Note that network attached devices are not queried unless configured
# in this file.
#
# Examples:
#
#net 192.16.136.2 1865
#net 10.0.0.1
#net scanner.mydomain.com
# Some backend behaviour can be customized by using the option keyword
# followed by an option name, as shown below.
#
# option <option-name>
#
# Currently available options:
#
# Makes the automatic document feeder the default document source
#option prefer-adf
Un petit apercu du support du Dell XPS M1330 sous OpenBSD
OpenBSD 6.0 (GENERIC.MP) #2319: Tue Jul 26 13:00:43 MDT 2016
deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 4276531200 (4078MB)
avail mem = 4142448640 (3950MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.4 @ 0xf71d0 (44 entries)
bios0: vendor Dell Inc. version "A15" date 12/26/2008
bios0: Dell Inc. XPS M1330
acpi0 at bios0: rev 2
acpi0: sleep states S0 S3 S4 S5
acpi0: tables DSDT FACP HPET APIC MCFG SLIC BOOT SSDT
acpi0: wakeup devices PCI0(S5) PCIE(S4) USB1(S0) USB2(S0) USB3(S0) USB4(S0) USB5(S0) EHC2(S0) EHCI(S0) AZAL(S3) RP01(S3) RP02(S3) RP03(S3) RP04(S3) RP05(S3) RP06(S5) [...]
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpihpet0 at acpi0: 14318179 Hz
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Core(TM)2 Duo CPU T5800 @ 2.00GHz, 965.53 MHz
cpu0: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,DTES64,MWAIT,DS-CPL,EST,TM2,SSSE3,CX16,xTPR,PDCM,NXE,LONG,LAHF,PERF,SENSOR
cpu0: 2MB 64b/line 8-way L2 cache
cpu0: smt 0, core 0, package 0
mtrr: Pentium Pro MTRR support, 8 var ranges, 88 fixed ranges
cpu0: apic clock running at 199MHz
cpu0: mwait min=64, max=64, C-substates=0.2.2.2.2, IBE
cpu1 at mainbus0: apid 1 (application processor)
cpu1: Intel(R) Core(TM)2 Duo CPU T5800 @ 2.00GHz, 927.61 MHz
cpu1: FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,DTES64,MWAIT,DS-CPL,EST,TM2,SSSE3,CX16,xTPR,PDCM,NXE,LONG,LAHF,PERF,SENSOR
cpu1: 2MB 64b/line 8-way L2 cache
cpu1: smt 0, core 1, package 0
ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 20, 24 pins
acpimcfg0 at acpi0 addr 0xf8000000, bus 0-63
acpiprt0 at acpi0: bus 3 (PCIE)
acpiprt1 at acpi0: bus 1 (AGP_)
acpiprt2 at acpi0: bus 11 (RP01)
acpiprt3 at acpi0: bus 12 (RP02)
acpiprt4 at acpi0: bus -1 (RP03)
acpiprt5 at acpi0: bus 13 (RP04)
acpiprt6 at acpi0: bus -1 (RP05)
acpiprt7 at acpi0: bus 9 (RP06)
acpiprt8 at acpi0: bus 0 (PCI0)
acpicpu0 at acpi0: !C3(100@57 mwait.3@0x30), !C2(500@1 mwait.1@0x10), C1(1000@1 mwait.1), PSS
acpicpu1 at acpi0: !C3(100@57 mwait.3@0x30), !C2(500@1 mwait.1@0x10), C1(1000@1 mwait.1), PSS
acpitz0 at acpi0: critical temperature is 87 degC
"PNP0F13" at acpi0 not configured
"PNP0303" at acpi0 not configured
acpibtn0 at acpi0: LID_
acpibtn1 at acpi0: PBTN
acpibtn2 at acpi0: SBTN
acpiac0 at acpi0: AC unit online
acpibat0 at acpi0: BAT0 not present
"PNP0C32" at acpi0 not configured
"*pnp0c14" at acpi0 not configured
acpivideo0 at acpi0: VID_
acpivout0 at acpivideo0: LCD_
acpivideo1 at acpi0: VID_
acpivout at acpivideo1 not configured
acpivideo2 at acpi0: VID2
cpu0: Enhanced SpeedStep 965 MHz: speeds: 2000, 1600, 1200, 800 MHz
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel GM965 Host" rev 0x0c
ppb0 at pci0 dev 1 function 0 "Intel GM965 PCIE" rev 0x0c: msi
pci1 at ppb0 bus 1
vga1 at pci1 dev 0 function 0 "NVIDIA GeForce 8400M GS" rev 0xa1
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
uhci0 at pci0 dev 26 function 0 "Intel 82801H USB" rev 0x02: apic 2 int 20
uhci1 at pci0 dev 26 function 1 "Intel 82801H USB" rev 0x02: apic 2 int 21
ehci0 at pci0 dev 26 function 7 "Intel 82801H USB" rev 0x02: apic 2 int 22
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 "Intel EHCI root hub" rev 2.00/1.00 addr 1
azalia0 at pci0 dev 27 function 0 "Intel 82801H HD Audio" rev 0x02: msi
azalia0: codecs: Sigmatel STAC9228X
audio0 at azalia0
ppb1 at pci0 dev 28 function 0 "Intel 82801H PCIE" rev 0x02: msi
pci2 at ppb1 bus 11
ppb2 at pci0 dev 28 function 1 "Intel 82801H PCIE" rev 0x02: msi
pci3 at ppb2 bus 12
"Broadcom BCM4321" rev 0x03 at pci3 dev 0 function 0 not configured
ppb3 at pci0 dev 28 function 3 "Intel 82801H PCIE" rev 0x02: msi
pci4 at ppb3 bus 13
ppb4 at pci0 dev 28 function 5 "Intel 82801H PCIE" rev 0x02: msi
pci5 at ppb4 bus 9
bge0 at pci5 dev 0 function 0 "Broadcom BCM5906M" rev 0x02, BCM5906 A2 (0xc002): msi, address 00:1d:09:37:6d:1b
brgphy0 at bge0 phy 1: BCM5906 10/100baseTX PHY, rev. 0
uhci2 at pci0 dev 29 function 0 "Intel 82801H USB" rev 0x02: apic 2 int 20
uhci3 at pci0 dev 29 function 1 "Intel 82801H USB" rev 0x02: apic 2 int 21
uhci4 at pci0 dev 29 function 2 "Intel 82801H USB" rev 0x02: apic 2 int 22
ehci1 at pci0 dev 29 function 7 "Intel 82801H USB" rev 0x02: apic 2 int 20
usb1 at ehci1: USB revision 2.0
uhub1 at usb1 "Intel EHCI root hub" rev 2.00/1.00 addr 1
ppb5 at pci0 dev 30 function 0 "Intel 82801BAM Hub-to-PCI" rev 0xf2
pci6 at ppb5 bus 3
"Ricoh 5C832 Firewire" rev 0x05 at pci6 dev 1 function 0 not configured
sdhc0 at pci6 dev 1 function 1 "Ricoh 5C822 SD/MMC" rev 0x22: apic 2 int 18
sdhc0: SDHC 1.0, 33 MHz base clock
sdmmc0 at sdhc0: 4-bit, sd high-speed, mmc high-speed
"Ricoh 5C843 MMC" rev 0x12 at pci6 dev 1 function 2 not configured
"Ricoh 5C592 Memory Stick" rev 0x12 at pci6 dev 1 function 3 not configured
"Ricoh 5C852 xD" rev 0x12 at pci6 dev 1 function 4 not configured
pcib0 at pci0 dev 31 function 0 "Intel 82801HBM LPC" rev 0x02
pciide0 at pci0 dev 31 function 1 "Intel 82801HBM IDE" rev 0x02: DMA, channel 0 configured to compatibility, channel 1 configured to compatibility
atapiscsi0 at pciide0 channel 0 drive 0
scsibus1 at atapiscsi0: 2 targets
cd0 at scsibus1 targ 0 lun 0: <HL-DT-ST, DVD+-RW GSA-S10N, A103> ATAPI 5/cdrom removable
cd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
pciide0: channel 1 ignored (disabled)
ahci0 at pci0 dev 31 function 2 "Intel 82801HBM AHCI" rev 0x02: msi, AHCI 1.1
ahci0: port 0: 3.0Gb/s
ahci0: PHY offline on port 2
scsibus2 at ahci0: 32 targets
sd0 at scsibus2 targ 0 lun 0: <ATA, TOSHIBA MQ01ABF0, AM0G> SCSI3 0/direct fixed naa.5000039523783257
sd0: 476940MB, 512 bytes/sector, 976773168 sectors
ichiic0 at pci0 dev 31 function 3 "Intel 82801H SMBus" rev 0x02: apic 2 int 17
iic0 at ichiic0
spdmem0 at iic0 addr 0x50: 2GB DDR2 SDRAM non-parity PC2-6400CL6 SO-DIMM
spdmem1 at iic0 addr 0x52: 2GB DDR2 SDRAM non-parity PC2-5300CL5 SO-DIMM
usb2 at uhci0: USB revision 1.0
uhub2 at usb2 "Intel UHCI root hub" rev 1.00/1.00 addr 1
usb3 at uhci1: USB revision 1.0
uhub3 at usb3 "Intel UHCI root hub" rev 1.00/1.00 addr 1
usb4 at uhci2: USB revision 1.0
uhub4 at usb4 "Intel UHCI root hub" rev 1.00/1.00 addr 1
usb5 at uhci3: USB revision 1.0
uhub5 at usb5 "Intel UHCI root hub" rev 1.00/1.00 addr 1
usb6 at uhci4: USB revision 1.0
uhub6 at usb6 "Intel UHCI root hub" rev 1.00/1.00 addr 1
isa0 at pcib0
isadma0 at isa0
pckbc0 at isa0 port 0x60/5 irq 1 irq 12
pckbd0 at pckbc0 (kbd slot)
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pms0 at pckbc0 (aux slot)
wsmouse0 at pms0 mux 0
pms0: Synaptics touchpad, firmware 6.3
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
uvideo0 at uhub1 port 6 configuration 1 interface 0 "OmniVision Technologies, Inc. -2640-07.07.20.3 Laptop Integrated Webcam" rev 2.00/1.00 addr 2
video0 at uvideo0
ugen0 at uhub6 port 1 "STMicroelectronics Biometric Coprocessor" rev 1.00/0.01 addr 2
vscsi0 at root
scsibus3 at vscsi0: 256 targets
softraid0 at root
scsibus4 at softraid0: 256 targets
root on sd0a (7d76cb4c2570dde6.a) swap on sd0b dump on sd0b
hw.sensors.cpu0.temp0=69.00 degC
hw.sensors.acpitz0.temp0=54.50 degC (zone temperature)
hw.sensors.acpibtn0.indicator0=On (lid open)
hw.sensors.acpiac0.indicator0=On (power supply)
[Firefox]https://www.mozilla.org/firefox/) est un navigateur web conforme aux normes, pleinement équipé, construit sur la base du code de Mozilla par des centaines de contributeurs dans le monde. Il est extensible à travers des centaines d’extensions, contributions d’utilisateurs, et de fonctionnalités :
Installez
le
paquet firefox
.
La plupart des informations de configuration ci-dessous concernent Firefox Quantum- moteur du navigateur à partir de la v57 !
Merci d’en tenir compte.
Pour une intégration propre avec les composants des environnements de bureau, Firefox a besoin d’une instance de D-Bus fonctionnelle.
Veuillez lire D-Bus [système de bus de messages] / OpenBSD
Cette option est disponible à partir de la v63.0 !
Pour activer DNS-sur-HTTPS (DoH: DNS-over-HTTPS), ouvrez les préférences
Il semble préférable de modifier l’URL proposée par défaut… retrouvez des adresses de serveurs DNS gérant DoH, par exemple, sur :
Cette URL est paramétrable aussi par le biais de l'
éditeur de configuration
;
cherchez puis modifiez la valeur network.trr.uri
.
L’éditeur de configuration permet de modifier les valeurs des Résolveurs Récursifs de Confiance (en anglais : TRR ).
network.trr.mode
:
0
: défaut, off
1
: mode race
2
: TRR en premier3
: TRR seulement4
: mode shadow
5
: désactivé par choix.OpenBSD 6.7 apporte la gestion de clés USB respectant la norme FIDO, permettant ainsi la double authentification U2F.
Firefox supporte U2F depuis la version 60.0 et supérieure. Néanmoins, il
peut être utile de vérifier sa configuration
et s’assurer que la variable de type booléenne security.webauth.u2f
soit bien configurée sur true
.
Ensuite, tout site web qui propose l’authentification U2F devrait être capable de voir la clé U2F, après la saisie de mots de passe :
(Exemples de site supportant la 2FA U2F : GitHub, GitLab, …)
Ces fonctionnalités ne sont utilisables qu’avec Firefox Quantum, et tout particulièrement à partir de la version 59.x !
Il est important que votre architecture matérielle gère OpenGL 4, et WebGL 2 ; autrement, OUBLIEZ !
⇒ Par défaut, l’accélération graphique OpenGL est désactivée. Il est possible de l’activer de deux manières :
MOZ_ACCELERATED=1
layers.acceleration.force-enable
pour la positionner sur true
.HW_COMPOSITING
et OPENGL_COMPOSITING
dans la section
Accélération graphique.⇒ Pour activer le compositeur basé sur Rust, deux manières possibles :
MOZ_WEBRENDER=1
gfx.webrender.enabled
pour la
positionner sur true
.WEBRENDER
dans la section Accélération graphique.Pour ajouter le support audio et vidéo HTML5,
installez
le
paquet ffmpeg
.
Vous pouvez ajouter le module HTML5 Video Everywhere! qui améliorera la lecture vidéo en favorisant celle-ci par le biais d’un lecteur vidéo HTML5 - utile, par exemple, pour les lectures Youtube…
Pour utiliser Firefox en mode KerberosV :
heimdal
.LD_LIBRARY_PATH=/usr/local/heimdal/lib
shlib_dirs
au fichier /etc/rc.conf.local
Si vous désirez spécifier l’usage de Kerberos en ciblant certains domaines,
utilisez l’éditeur de configuration
puis
modifiez la clé network.negotiate-auth.trusted-uris
en ajoutant votre
domaine, tel que :
.example.com
.
Depuis Firefox v69.0.2, sous OpenBSD 6.6, il est possible de changer en choisissant le menu “Préférences ”, onglet ‘General’ > Language, puis cliquez sur la liste déroulante pour ajouter une nouvelle langue.
Vous aurez une nouvelle fenêtre qui s’affiche qui vous permettra d’ajouter ‘French’ ; validez votre choix par l’appui sur le bouton [ OK ].
Redémarrez Firefox, et voilà !
Pour Firefox v59 ou supérieure :
Tools
> Add-ons
> Language
intl.locale.requested
et la mettre à fr-FR
⇒ Pour Firefox, inférieure ou égale à v56 :
general.useragent.locale
et mettre à fr-FR
.Vous pouvez aussi essayer à installer :
firefox-i18n-fr
.À-propos de la gestion des liens mailto :
network.protocol-handler.app.mailto
.
/usr/local/bin/thunderbird
new string
)Depuis OpenBSD 6.6, le logiciel de confidentialité KeePassXC est installable.
Pour fonctionner correctement avec Firefox, il est nécessaire d’installer le module KeePassXC-Browser.
Lire la page KeePassXC pour avoir plus d’informations concernant le module KeePassXC-Browser
Ajouter au fichier de configuration unveil
de firefox unveil.main
:
/usr/local/bin r
/usr/local/bin/keepassxc-proxy rx
Ainsi le proxy de KeePassXC pourra communiquer avec le module KeePassXC-Browser.
Retrouvez un module pour effectuer une recherche sur le site officiel OpenBSD Manual page :
Pour activer la gestion de la fonctionnalité des multi-processus, ouvrez l’éditeur de configuration , puis :
browser.tabs.remote.force-enable
true
;browser.tabs.remote.autostart
à true
;Puis, vérifiez le support , dans la section “Paramètres de base de l’application”, vous devriez lire à “Fenêtres multi-processus 1/1 (Activé par l’utilisateur)” - sinon, cela ne fonctionne pas !
Firefox sur OpenBSD est sécurisé par pledge(2) et unveil(2) - afin de limiter les appels systèmes et les accès au système de fichier.
Par défaut, seuls les répertoires /tmp
et ~/Downloads
sont autorisés
en écriture. De même, la lecture des fichiers locaux est autorisé en
préfixant le chemin vers le fichier par file://
.
Si votre répertoire personnel ~/Downloads
n’existe pas, créez-le puis
relancez Firefox.
Les permissions pour chaque type de processus sont localisées par défaut
dans des fichiers contenus dans /etc/firefox
qui est une copie de
/usr/local/lib/firefox/browser/defaults/preferences/
lors de
l’installation, principalement :
/etc/firefox/pledge.main
/etc/firefox/unveil.main
Du fait d’unveil(2), il est nécessaire de gérer finement les gestionnaires MIME.
Par exemple pour permettre l’utilisation d’un lecteur PDF avec Firefox, il faut :
déclarer par défaut le lecteur PDF en tant gestionnaire MIME, tel que
$ xdg-mime default xpdf.desktop application/pdf
$ xdg-mime default mupdf.desktop application/pdf
modifier le fichier /etc/firefox/unveil.main
pour gérer les droits
sur le binaire correspondant, tel que :
/usr/local/bin/xpdf rx
/usr/local/bin/mupdf rx
Ainsi vous pourrez lire le fichier PDF avec l’option “Ouvrir avec…”.
$ xdg-mime query default application/pdf
permet de connaître le lecteur
PDF par défaut.
Le support des webcams est normalement géré par Firefox, qui par défaut
a accès aux périphériques vidéo /dev/video
et /dev/video0
.
⇒ OpenBSD ≥ 6.9 : Il faut aussi : - activer l’enregistrement vidéo - puis vérifier le support et accéder à la webcam - et pour finir l’enregistrement audio .
⇒ OpenBSD ≥ 6.4 : Pour que la fonctionnalité WebRTC fonctionne correctement, il faut activer l’enregistrement audio .
L’éditeur de configuration est accessible en écrivant dans la barre
d’URL : about:config
.
L’édition de la configuration comporte des risques ; en effet, une mauvaise configuration peut rendre instable ou empêcher le logiciel de fonctionner.
Une fois la configuration modifiée, il est important de redémarrer le logiciel !
Les Préférences sont accessibles de deux manières :
about:preferences
La page Informations de dépannage est accessible en écrivant dans la
barre d’URL : about:support
.
Cette page contient des informations techniques qui permettent de vérifier le support de certaines fonctionnalités et d’aider à résoudre certains problèmes !
Veuillez ABSOLUMENT lire le fichier pkg-readme de Firefox, pour savoir comment faire pour remonter tout problème rencontré, si Firefox crashe régulièrement.
Attention, tout rapport de bogue envoyé sans les informations nécessaires et demandées dans la section “Debugging” sera purement et simplement ignoré !
Si Firefox ne démarre pas, essayez de le démarrer en mode console,
avec l’option -safe-mode
- cela aura pour effet d’essayer à le
démarrer après avoir désactivé toutes vos extensions, vos thèmes.
Si Firefox a un comportement étrange, essayez de créer un nouveau profil :
-ProfileManager
, puis vous cliquez sur [ Create Profile ]Pour exécuter les deux versions en même temps, la version Firefox ESR et celle-ci, vous devez créer des profils différents :
firefox -p
firefox-esr -p
Il suffit de créer et d’attribuer un profil différent…
Êtes-vous sûr d’avoir installé le paquet CUPS
et gtk+2-cups
ou son pendant gtk+3-cups
?
Vous avez besoin de consulter certains sites juste sur le protocole IPv4 ?
Ouvrez l’éditeur de configuration
et
paramétrez la variable network.dns.ipv4OnlyDomains
. Si vous voulez
gérer plusieurs domaines, séparez-les par une virgule.
Cette caractéristique de média CSS est fonctionnelle à partir de la v67.
privacy.resistFingerprinting
est paramétrée sur true
, la gestion de cette option ne fonctionnera pas ;
ce sera le schéma light
qui sera choisi par défaut.L’option de préférence du schéma de couleurs prefers-color-scheme
doit
être activé par l’éditeur de configuration
.
Créez une valeur numérique ui.systemUsesDarkTheme
en lui donnant pour valeur 1
.
Vous n’arrivez pas à vous connecter au service web de Protonmail.com !
Ouvrez l’éditeur de configuration
, puis
positionnez l’option javascript.options.asmjs
sur false
-
(source)
Après l’installation, n’oubliez pas de lire le fichier :
/usr/local/share/doc/pkg-readmes/firefox
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Si vous voulez aider à l’amélioration du support matériel d’OpenBSD, ça ne prend que quelques minutes.
(dmesg; sysctl hw.sensors) > ~/dmesg.txt
dmesg.txt
à dmesg@openbsd.org
, avec quelques
informations supplémentaires sur ce qui fonctionne ou non.Ajoutez l’option softdep
dans le fichier /etc/fstab
sur chaque ligne pour qu’elles ressemblent
à ça :
/dev/sd0a / ffs rw,softdep 1 1
De même, on peut rajouter l’option noatime
, ce qui donne :
/dev/sd0a / ffs rw,softdep,noatime 1 1
Attention à l’usage de cette option, dans certains contextes, elle peut être dangereuse car elle désactive la journalisation des informations relatives aux modifications dans le système de fichier.
Elle peut être utile dans le contexte d’usage de disque de type SSD, afin d’aider à ne pas les “user” prématurément…
Si vous décidez de l’utiliser, soyez attentif à tout dysfonctionnement de votre système d’exploitation !
La toute première source d’information disponible, nécessaire à consulter, juste après une installation, est celle-ci :
$ man afterboot
Les ‘pkg-readme’ sont les fichiers readme liés à un binaire, utilisables après l’installation du binaire lié :
$ less /usr/local/share/doc/pkg-readmes/pkg_name
‘pkg_name’ étant le nom du binaire… En effet, certaines informations pertinentes sont restituées dans ces fichiers ‘readme’ et expliquées clairement…
Astuce : si vous avez un environnement graphique, tel que XFCE , pourquoi pas créer un lien symbolique vers le répertoire ‘/usr/local/share/doc/pkg-readmes/’, sur votre “bureau” ;-)
$ ln -s /usr/local/share/doc/pkg-readmes/ ~/Desktop/
Il peut être très utile, voire indispensable, de lire notre Kit de survie sous OpenBSD :D
Retrouvez aussi tous nos Trucs et astuces pour OpenBSD, bien utiles, pour démarrer…
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
apmd
pour le mode d’ajustement automatique des
performances : -A
apm -S
.apm -Z
.Pensez à modifier l’ordre d’exécution des services pour que messagebus démarre en premier :
messagebus apmd
.apm [-AabHLlmPSvZz] [-f sockname] zzz [-SZz] [-f sockname] ZZZ [-SZz] [-f sockname]
apm communique avec le service de gestion avancée d’énergie apmd(8), faisant des requêtes du statut actuel de l’énergie, ou permettre de mettre le système en étant d’hibernation ou de veille. Sans aucun drapeau, apm affiche l’état actuel de la gestion d’énergie avec des messages détaillés.
Pour connaître les options, lisez le manpage apm(8) !
/var/run/apmdev
: Le socket de communication par défaut sous Unix,
avec apmd(8). Le drapeau -f
peut être
utilisé pour spécifier un autre nom de socket. Les modes de protection de
ce socket gère quels utilisateurs peut accéder aux fonctions APM.apm(4), [[https://man.openbsd.org/apmd.8|apmd(8)]]
Advanced Power Management (APM) BIOS Interface Specification (revision 1.2), Intel Corporation and Microsoft Corporation
La commande apm est apparue dans NetBSD 1.3 ; le support OpenBSD a été ajoutée dans OpenBSD 1.2.
Traduction ci-dessus du manpage apm(8) !
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Quelques exemples :
⇒ charge réseau :
systat ifstat
⇒ charge système :
systat vm
⇒ pour les températures :
systat sensors
systat [-aBbiNn] [-d count] [-s delay] [-w width] [view] [delay]
systat affiche nombre de statistiques systèmes, en fonction de l’écran, en utilisant la bibliothèque curses(3).
Durant le fonctionnement de systat, l’écran est divisé en plusieurs zones.
La première ligne en haut affiche le nombre actuel d’utilisateurs, la charge moyenne des trois systèmes (réel, virtuel, et mémoire) durant l’intervalle de la première minute, des 5 et 15 dernières minutes, et l’horloge système.
La ligne en bas de l’écran est réservé aux entrées utilisateurs, et messages d’erreurs.
L’information affichée dans le reste de l’écran comprend une vue de
l’activité système, et est l’interface principale pour afficher les
différentes statistiques du système. La vue vmstat
est celle par défaut.
Certaines informations peuvent ne pas être affichées si la taille de l’écran est insuffisante pour les afficher. Par exemple, sur une machine avec 10 disques, la barre graphique d’iostat affichera seulement 3 disques sur un terminal de 24 lignes.
Pour connaître les options, lisez le manpage !
/etc/hosts
: les noms de l’hôte./etc/pf.conf
: la configuration de pf(4)./etc/services
: les noms des ports.fstat(1), kill(1), netstat(1), nfsstat(1), ps(1), top(1), iostat(8), pfctl(8), pstat(8), renice(8), sysctl(8), vmstat(8)
Le programme systat est apparu la première fois dans 4.3BSD.
Certains affichages présument d’un minimum de 80 caractères par ligne.
L’affichage vmstat
a ce problème (il a été ajouté en tant qu’affichage
séparé, plutôt qu’en tant que nouveau programme).
Traduction du manpage systat(1) !
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
La synchronisation de l’heure locale sous OpenBSD n’est pas bien difficile. Elle s’effectue au-travers du projet OpenNTPD, intégré nativement dans OpenBSD, et fonctionnel au démarrage de votre ordinateur sous OpenBSD.
Les adresses de serveurs NTP sont visibles depuis la page pour trouver un serveur.
Les serveurs de pool NTP sont par zones mondiales comportant plusieurs pays.
Le fichier de configuration est /etc/ntpd.conf
.
Pour qu’il corresponde à l’heure française, il faut modifier la ligne
correspondante à l’option servers
, telle que :
servers fr.pool.ntp.org
Pour en serveur NTP en local, utilisez plutôt - à mettre en premier - :
server adr_ip_srvr
adr_ip_srvr
est bien sûr l’adresse ip de votre serveur NTPD local ;
si vous avez une résolution DNS de celui-ci, vous pouvez spécifier le
nom d’hôte !
À-propos des options de contraintes : ntpd(8) peut être configuré pour interroger la ‘Date’ des serveurs HTTPS de confiance via TLS. Cette information de temps n’est pas utilisée pour la précision mais agit comme une contrainte authentifiée, réduisant ainsi l’impact des attaques NTP non authentifiées de l’homme au milieu. Les paquets NTP reçus dont les informations temporelles se situent en dehors d’une plage proche de la contrainte seront rejetés et ces serveurs NTP seront marqués comme invalides.
Dans ce mail, Theo de Raadt explique pourquoi il n’est pas désirable de personnaliser les paramètres de contraintes autrement que ceux que l’équipe fixe. Où l’on apprend aussi que le domaine www.openbsd.org ne doit pas être invoqué, non plus…
Exemple de configuration du fichier /etc/examples/ntpd.conf
:
# $OpenBSD: ntpd.conf,v 1.5 2019/11/11 16:44:37 deraadt Exp $
# sample ntpd configuration file, see ntpd.conf(5)
# Addresses to listen on (ntpd does not listen by default)
#listen on *
# sync to a single server
#server ntp.example.org
# use a random selection of NTP Pool Time Servers
# see http://support.ntp.org/bin/view/Servers/NTPPoolServers
servers pool.ntp.org
# time server with excellent global adjacency
server time.cloudflare.com
# use a specific local timedelta sensor (radio clock, etc)
sensor nmea0 trusted
# use all detected timedelta sensors
#sensor *
# get the time constraint from a well-known HTTPS site
constraint from "9.9.9.9" # quad9 v4 without DNS
constraint from "2620:fe::fe" # quad9 v6 without DNS
constraints from "www.google.com" # intentionally not 8.8.8.8
⇒ OpenBSD ≥ 6.9 : Il n’est plus recommandé d’activer le drapeau -s
pour gérer correctement les contraintes !
⇒ OpenBSD < 6.9 : Ensuite, il faut activer le drapeau -s
pour que
le serveur ntpd essaye de modifier l’heure locale, immédiatement au
moment du (re)démarrage du serveur.
# rcctl set ntpd flags -s
Maintenant que la configuration est correctement faite, il nous faut (re)démarrer le service ntpd(8) :
# rcctl restart ntpd
ntpd(ok)
ntpd(ok)
Toute modification du fichier de configuration nécessite le redémarrage du service NTP !
Attendre quelques secondes, et ensuite, vérifiez le status de ntpd, avec l’outil de contrôle ntpctl(8) :
$ doas ntpctl -sa
5/5 peers valid, 0/1 sensors valid, constraint offset -2s, clock unsynced
peer
wt tl st next poll offset delay jitter
162.159.200.1 time.cloudflare.com
1 7 3 5s 9s 0.848ms 52.534ms 1.445ms
195.154.226.102 from pool fr.pool.ntp.org
1 8 2 28s 32s 5.421ms 48.736ms 1.627ms
93.113.207.65 from pool fr.pool.ntp.org
1 8 2 33s 34s 6.263ms 51.508ms 2.299ms
51.15.175.180 from pool fr.pool.ntp.org
1 8 2 31s 32s 5.530ms 49.960ms 2.917ms
5.39.80.51 from pool fr.pool.ntp.org
1 7 2 4s 9s 9.524ms 52.748ms 3.335ms
sensor
wt gd st next poll offset correction
upd0
1 0 0 12s 15s - sensor not valid -
Un coup d’œil pour vérifier l’horloge, en mode graphique, ou en mode console :
$ date
Thu Apr 27 12:29:51 CEST 2023
/etc/examples/ntpd.conf
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Mozilla Thunderbird est une ré-écriture des composants de la suite mail de Mozilla. Son objectif est d’exploiter une grande partie des fonctionnalités existantes de ce produit pour créer une application de messagerie autonome, simple et extensible.
installez
le
paquet thunderbird
.
Pour désactivez l’anti-aliasing, paramétrez GDK_USE_XFT=0
dans votre e
nvironnement.
Cette option semble être disponible depuis la v68.1 !
Pour activer DNS-sur-HTTPS (DoH ), ouvrez les préférences :
Il semble préférable de modifier l’URL proposée par défaut… retrouvez des adresses de serveurs DNS gérant DoH, par exemple, sur :
Cette URL est paramétrable aussi par le biais de
l’éditeur de configuration
; cherchez puis
modifiez la valeur network.trr.uri
.
L’éditeur de configuration permet de modifier les valeurs des Résolveurs Récursifs de Confiance (en anglais : TRR ) :
network.trr.mode
:
0
: défaut, off
1
: mode race
2
: TRR en premier3
: TRR seulement4
: mode shadow
5
: désactivé par choix.Installer Enigmail depuis le site officiel ou en tant que module.
Enigmail fonctionne avec la version GPG2 - /usr/local/bin/gpg2
, installé
dans la structure de base d’OpenBSD.
Néanmoins, pour que cela fonctionne correctement, il faudra
installer
les
paquets suivants : pinentry
pinentry-gtk2
(ou pinentry-gtk3
selon votre environnement graphique).
Avec Thunderbird v68, sous OpenBSD 6.6, il est possible de changer en choisissant le menu “Préférences” (Edit > Preferences), onglet ‘General’, Language, puis cliquez sur la liste déroulante pour ajouter une nouvelle langue.
Vous aurez une nouvelle fenêtre qui s’affiche qui vous permettra d’ajouter ‘French’ ; validez votre choix par l’appui sur le bouton [ OK ].
Redémarrez Thunderbird, et voilà !
Sinon, essayer d’installer
le paquet : thunderbird-i18n-fr
.
Vous pouvez aussi d’essayer l’éditeur de configuration :
intl.locale.requested
et mettez la valeur fr-FR
.Si vous avez des problèmes pour ouvrir les liens dans les mails, en premier arrêtez Thunderbird.
Ensuite, éditez votre fichier ~/.thunderbird/<something>.default/prefs.js
pour ajouter ce qui suit :
user_pref("network.protocol-handler.app.ftp", "/usr/local/bin/firefox");
user_pref("network.protocol-handler.app.http", "/usr/local/bin/firefox");
user_pref("network.protocol-handler.app.https", "/usr/local/bin/firefox");
Puis, relancez Thunderbird !
Thunderbird cherche les plugins dans les répertoires ~/.mozilla/plugins
et /usr/local/lib/mozilla/plugins
.
Si la variable d’environnement MOZ_PLUGIN_PATH
est spécifiée, elle
remplacera l’endroit de recherche.
Il est possible de faire certaines modifications de la configuration de
Thunderbird, par le biais de l’éditeur de configuration about:config
.
L’édition de la configuration comporte des risques ; en effet, une mauvaise configuration peut rendre instable ou empêcher le logiciel de fonctionner.
Une fois la configuration modifiée, il est important de redémarrer le logiciel !
Dans la fenêtre Thunderbird Preferences
:
Advanced
General
Dans la fenêtre about:config
:
Dans la fenêtre Préférences de Thunderbird
:
Avancé
Général
Dans la fenêtre about:config
:
Veuillez IMPÉRATIVEMENT lire le fichier pkg-readme pour savoir comment faire. Tout rapport sans information correcte sera purement et simplement ignoré !
Si vous rencontrez des problèmes étranges ou que Thunderbird refuse de
démarrer, essayer de le démarrer avec l’usage de l’option -safe-mode
.
Il semble avoir un problème avec les versions 60.x de Thunderbird pour pouvoir se connecter aux services CalDAV de Nextcloud.
⇒ Version utilisée sous OpenBSD 6.4 !
C’est un problème connu chez Mozilla.
Ouvrez l’éditeur de configuration , puis :
network.cookie.same-site.enabled
false
Sous OpenBSD v6.0, un bogue fait que gpg 1 n’est pas installé|installable ;
faites un lien symbolique de /usr/local/bin/gpg2
vers /usr/local/bin/gpg
:
# ln -sf /usr/local/bin/gpg2 /usr/local/bin/gpg
OpenBSD v6.1 ne connaît pas ce soucis.
Vous devez/pouvez aussi installer le pack Français en tant qu’addon.
Une fois téléchargé, ouvrez TB, puis le menu “Addons”, puis cliquez sur l’icône en forme de roue crantée (//alias préférences//) pour choisir le menu “Install addon from file…”.
Une fois installé, redémarrez TB.
Vous pouvez aussi installer l’outil supplémentaire “Quick Locale Switcher 2"… qui vous servira surtout à basculer d’une langue à l’autre, au besoin.
/usr/local/share/doc/pkg-readmes/thunderbird
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
GIT est un “gestionnaire de contenu de répertoire” conçu pour gérer des projets massifs avec rapidité et efficacité,
GIT entre dans la catégorie des outils de gestion de code source distribués, semblable à par exemple GNU Arch ou Monotone (ou, dans le monde commercial, BitKeeper). Chaque répertoire de travail GIT est un référentiel à part entière avec des capacités de suivi de révision complètes, ne dépendant pas de l’accès réseau à un serveur central.
Installez
le
paquet git
.
Pour pouvoir utiliser la fonction git send-email
, et utiliser smtp
,
tls
, il vous faut installer aussi les packages suivants :
p5-Net-SMTP-SSL
p5-Authen-SASL
Le fichier de configuration : ~/.gitconfig
Exemple minimaliste :
[user]
name = identifiant
email = email@domain.com
Depuis la version 1.7.9 de Git, il est possible de signer les commits, ce qui permet d’assurer que vous êtes bien l’auteur de ceux-ci.
Pour signer vos commits, il est nécessaire d’avoir créé dans un premier temps une clé GPG - ce mémo ne vous montrera pas comment faire… L’outil GPG2 est fourni de base dans OpenBSD. Néanmoins, il vous faudra créer un lien symbolique pour lui faire croire qu’il utilise GPG, car Git semble ne pas être capable de comprendre !
Vous devrez ensuite modifier votre fichier de configuration afin de rajouter
l’option signingkey
dans la partie de configuration [user], tel que :
[user]
name = identifiant
email = email@domain.com
signingkey = votre_id_gpg
La commande pour signer :
git commit -a -S -m 'un ou plusieurs longs commentaires'
git tag -s v1.5 -m 'mon tag signé'
Pour en connaître plus sur le fonctionnement de git et le fait de signer, veuillez lire la doc officielle…
Vous avez le message d’erreur suivant dans son ensemble :
error: cannot run gpg: No such file or directory
error: impossible de lancer gpg.
fatal: échec de l'écriture de l'objet commit
L’outil GPG n’est pas trouvé ; normal sous OpenBSD, il n’existe pas. L’astuce est de lier GPG au binaire GPG2 :
# ln -sf /usr/local/bin/gpg2 /usr/local/bin/gpg
Le message d’erreur est le suivant :
gpg: échec de la signature : Inappropriate ioctl for device
gpg: signing failed: Inappropriate ioctl for device
error: gpg n'a pas pu signer les données
fatal: échec de l'écriture de l'objet commit
Il vous manque les paquets suivants : pinentry
pinentry-gtk2
ou
pinentry-gtk3
- veillez à les installer
!
Pour info, il semble que ce soit lié au bogue 2680 relatif à la version 2.1x de GPG.
N’oubliez pas de lire le fichier /usr/local/share/doc/pkg-readmes/git
! ;-)
⇒ Git :
⇒ GPG :
Comment bien configuré GPG pour l’utiliser correctement : GPG : Du bon usage sécurisé
Un guide des bonnes pratiques pour créer ses clés GPG …
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
(de l’ethernet au wifi, et réciproquement)
Pour ne pas se compliquer la vie et laisser OpenBSD utiliser la connexion disponible, c’est à dire le filaire quand il est branché physiquement, par câble RJ45 ou par le wifi le cas échéant, on peut procéder comme suit :
⇒ Création d’un fichier /etc/hostname.re0
(où re0
est l’interface ethernet) :
$ cat /etc/hostname.re0
up
⇒ Création d’un fichier /etc/hostname.rtwn0
(rtwn0
est l’interface wifi) :
$ cat /etc/hostname.rtwn0
up
nwid kamehameha wpakey xxxxxxxxxxxxxxx
⇒ Et enfin, création d’un fichier /etc/hostname.trunk0
qui permet de
basculer sur l’interface disponible :
$ cat /etc/hostname.trunk0
trunkproto failover trunkport re0
trunkport rtwn0
dhcp
inet6 autoconf
ps : bien sûr, vous pouvez ajouter d’autres interfaces si vous en disposez.
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”.
Avez-vous lu le Kit de survie après votre installation et suivie l’étape “Que faire après l'installation d’OpenBSD ?”
Si oui, c’est bien… sinon, faites-le !
Alors, retrouvez ci-dessous, classés par thématique, les différents trucs et astuces qui pourront vous aider à démarrer… :D
Utiliser un serveur proche pour obtenir des paquets (France) : installurl : localisation du serveur miroir OpenBSD
Utiliser le résolveur DNS local : OpenBSD : utiliser Unbound
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
Retrouvez ci-dessous la traduction EN → FR de l’article “Learn UNIX in 10 minutes”, écrit sur le site disparu ‘Freeengineer.org’.
Le propos est d’avoir une page contenant les commandes de bases pour démarrer l’usage d’un shell UNIX.
Ce document est protégé par les droits d’auteurs, et placé sous les termes de la licence GNU/FDL.
Les chemins de répertoires et fichiers dans Unix utilisent le symbole ‘/’ (slash) pour séparer le nom des répertoires, dans le contexte du chemin.
exemples:
/
répertoire racine
/usr
répertoire usr (répertoire enfant de la racine)
/usr/STRIM100
STRIM100 est un sous-répertoire de /usr
pwd
voir le nom du répertoire courant
cd
Se rediriger vers votre répertoire utilisateur personnel
cd /usr/STRIM100
Se diriger vers /usr/STRIM100.
cd INIT
Se diriger vers le répertoire INIT, qui est un
sous-répertoire du répertoire courant.
cd ..
Se diriger vers le répertoire parent du répertoire courant.
cd $STRMWORK
Se diriger vers le répertoire renfermé dans la
variable d’environnement ‘STRMWORK’.
cd ~bob
Se diriger vers le répertoire personnel de bob.
ls
liste un répertoire
ls -l
liste un répertoire dans un format détaillé
ls -a
liste le répertoire courant en affichant les fichiers cachés,
ceux-ci commencent par un “.”
ls -ld
Liste tous les noms de fichiers et répertoires dans le
répertoire courant, utilisant un format détaillé. Sans l’option ’d’,
la commande ’ls’ listera le contenu des sous-répertoire du
répertoire courant. Avec, ’ls’ listera juste le nom des fichiers.
Pour l’exemple :
$ ls -l
drwxr-xr-x 4 cliff user 1024 Jun 18 09:40 WAITRON_EARNINGS
-rw-r--r-- 1 cliff user 767392 Jun 6 14:28 scanlib.tar.gz
^^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|| | | | | | | | | |
|| | | | |id |group |poids |date |heure |nom
|| | | |nombre de contenu
|| | |permissions pour les autres
|| |permissions pour les membres du groupe
||permission pour le propriétaire du fichier : r = lecture, w = écriture, x = éxecution, - = pas de permission
|type de fichier : - = fichier normal, d = répertoire, l = lien symbolique, etc…
chmod 755 file
Change les permissions du fichiers, en donnant tous
les droits au propriétaire du fichier, et les droits de lecture et
d’exécution pour le groupe et les autres.
(7 = rwx = 111 en binaire ; 5 = r-x = 101 en binaire)
chgrp user file
Change l’appartenance du groupe sur le fichier.
chown cliff file
Change le propriétaire du fichier.
chown -R cliff dir
Change le propriétaire du répertoire, de manière
récursive.
Vous devez être le propriétaire des fichiers ou répertoires, ou être en mode administrateur (root) avant de pouvoir interagir ainsi.
cp file1 file2
Copier un fichier
mv file1 newname
Déplacer ou renommer un fichier
mv file1 ~/AAA/
Déplacer un fichier dans le sous-répertoire AAA de
votre répertoire utilisateur personnel
rm file1 [file2…]
Supprimer un fichier
rm -r dir1 [dir2…]
Supprimer un répertoire récursivement, et son
contenu. FAITES ATTENTION !
mkdir dir1 [dir2…]
Créer un répertoire
mkdir -p dirpath
Créer un répertoire, incluant tous les
sous-répertoires nommés en suivant
rmdir dir1 [dir2…]
Supprimer un répertoire vide
cat filename
Afficher le contenu d’un fichier à l’écran, en ascii
more filename
Afficher le contenu d’un fichier à l’écran de manière
progressive. L’appui sur la touche Entrée affiche la ligne
suivante ; celui sur la barre d’espace affiche une nouvelle
page ; celui sur la touche q permettra la sortie.
less filename
Un peu comme ‘more’, mais permet l’usage de la touche
^ “Défilement Haut”, pour remonter les pages. Fonctionne
sur certains systèmes.
vi filename
Éditer le fichier en utilisant l’éditeur ‘vi’.
Tous les systèmes Unix ont cet éditeur.
emacs filename
Éditer le fichier en utilisant l’éditeur ’emacs’.
Tous les systèmes Unix n’ont pas cet éditeur.
head filename
Lire les premières lignes d’un fichier.
head -n x filename
Lire les x premières lignes d’un fichier
tail filename
Lire les dernières lignes d’un fichier
tail -n x filename
Lire les x dernières lignes d’un fichier
Le comportement d’une interface de ligne de commande diffère étroitement du programme shell dans lequel il est utilisée.
Dépendant du shell utilisé, quelques comportements supplémentaires peuvent être utiles.
Il est possible de savoir sous quel shell vous fonctionnez, en utilisant la commande suivante :
$ echo $SHELL
Bien-sûr, vous pouvez créer un fichier ayant une liste de commandes shell, l’exécuter tel un programme. Ceci est appelé un script shell. C’est le but premier de la plupart des shells.
Les variables d’environnement permettent au shell d’enregistrer des données, pour un usage ultérieur.
Par exemple, pour le shell nommé Bash :
export CASROOT=/usr/local/CAS3.0
Définit la variable CASROOT avec
la valeur /usr/local/CAS3.0.
export LD_LIBRARY_PATH=$CASROOT/Linux/lib
Définit la variable
LD_LIBRARY_PATH
avec la valeur de la variable $CASROOT
concaténé
avec /Linux/lib
, ou /usr/local/CAS3.0/Linux/lib
En préfixant la variable du symbole ‘$’, vous pouvez utiliser son contenu dans le contexte de toute commande :
cd $CASROOT
Se rediriger vers le répertoire contenu dans la
variable CASROOT
echo $CASROOT
Afficher le contenu de la variable CASROOT,
soit /usr/local/CAS3.0
printenv CASROOT
Faire la même chose dans le shell bash ou
d’autres environnements.
Une fonctionnalité des shells bash, tcsh (et certainement d’autres) est de pouvoir utiliser l’accès aux commandes précédentes par l’appui de la touche ^ “Flèche Haut”, de les éditer, et/ou de les exécuter à nouveau.
Certains shells proposent l’usage de la commande history
, qui
affichera l’ensemble des commandes utilisées.
Pour les réutiliser, si besoin, il suffit de précéder le numéro de la
commande du symbole !
.
Une fonctionnalité des shells bash, tcsh (et certainement d’autres) est
de pouvoir utiliser la touche de Tabulation pour compléter un nom de
fichier partiellement tapé. Par exemple, si vous avez un fichier nommé
èconstantine-monks-and-willy-wonka.txt’ dans votre répertoire et que
vous désirez l’éditer, vous pouvez écrire vi const
, appuyez sur la
touche Tab, et le shell remplira le reste du nom de fichier.
Bash est même capable de compléter le nom des commandes et des variables d’environnement. S’il y a plusieurs complétions possibles, l’appui plusieurs fois sur la touche Tab vous affichera les différentes possibilités.
Bash est le shell par défaut pour les systèmes Linux.
grep string filename > newfile
Redirige la sortie de la commande
grep vers un nouveau fichier
grep string filename >> existfile
Ajoute la sortie de la commande
grep à la fin du fichier existfile
.
Les directives de redirection >
et >>
peuvent être utilisées pour
diriger la sortie de la plupart des commandes vers un fichier.
Le symbole |
(la barre vertical sous le chiffre 6 ; appuyer
simultanément sur les touches Alt Gr et 6) est
utilisé pour diriger la sortie d’une commande vers l’entrée d’une autre
commande.
Par exemple :
ls -l | more
Cette commande prend la sortie de la commande ls
dans
son format détaillé et l’affiche au-travers de la commande ‘more’.
Cela permet dans le cas d’une très longue liste d’être affichée page
par page.
du -sc * | sort -n | tail
La commande du -sc
liste les tailles des
fichiers et répertoires, dans le répertoire de travail courant, puis
trie le résultat de la plus petite à la plus grosse grâce à la
commande sort -n
. Finalement, seront affichés les quelques
derniers résultats, les plus gros fichiers, par le biais de la
commande tail
.
Vous pouvez utiliser la sortie d’une commande comme entrée d’une autre commande d’une autre manière, appelée “Substitution de commande”. Elle est invoquée par l’usage du symbole ` (appui simultané des touches Alt Gr et 7), tel que, pour l’exemple :
$ cat `find . -name aaa.txt`
Ce qui affichera à l’écran tous les fichiers nommés aaa.txt
dans le
répertoire courant, et de ses sous-répertoires.
Actuellement, il est recommandé de l’écrire ainsi :
$ cat "$(find . -name aaa.txt)"
grep string filename
affiche toutes les lignes contenant la
chaine string
dans tel nom de fichier.find search_path -name filename
find . -name aaa.txt
Cherche tous les fichiers nommés aaa.txt
dans le répertoire courant et ses sous-répertoires.
find / -name vimrc
Cherche tous les fichiers nommés vimrc
partout
dans le système de fichiers.
find /usr/local/games -name "*xpilot*"
Cherche tous les fichiers
containant la chaîne xpilot
dans leurs noms, qui existent dans le
répertoire /usr/local/games
.
La commande ’tar’ signifie “tape archive”. C’est la manière “standard” de lire et d’écrire des archives (qui sont des collections de fichiers, dans un répertoire donné).
Vous trouverez souvent des archives avec des noms tels que stuff.tar
,
ou stuff.tar.gz
. En substance, cela signifie que le répertoire stuff
a été archivé dans une archive tar, et pour le second cas, que cette
archive a été compressée par le moyen du programme de compression gzip
.
Il y a de fortes probabilités que si quelqu’un vous donne une sauvegarde,
faite sur un système Unix, que cette sauvegarde soit faite dans le
format tar… et, dans ce cas, vous devrez utiliser tar
, et votre lecteur
de bande, pour la lire.
De même, si vous voulez écrire une bande de sauvegarde pour quelqu’un d’autre, vous devriez utiliser probablement tar, aussi.
Exemples :
tar xv
Extrait les fichiers depuis la sauvegarde, en affichant le
nom des fichiers à l’écran. (v
= verbeux)
tar tv
Liste les fichiers depuis la sauvegarde sans les extraire.
tar cv file1 file2
Écrit les fichiers file1
et file2
dans la
sauvegarde.
tar cvf archive.tar file1 [file2…]
Créer une archive tar, nommée
archive.tar
, contenant les fichiers file1
, file2
, etc…
Ne pas utilisez les symboles [
, ]
: c’est juste une convention
d’écriture pour signifier l’option…
tar xvf archive.tar
Extrait les fichiers de l’archive archive.tar
tar cvfz archive.tar.gz dname
Créer une archive compressée par gzip,
contenant tout le contenu du répertoire dname
.
Ne fonctionne pas avec toutes les versions de tar.
tar xvfz archive.tar.gz
Extrait une archive compressée avec gzip.
Ne fonctionne pas avec toutes les versions de tar.
tar cvfI archive.tar.bz2 dname
Créer une archive tar compressée avec
le programme de compression bzip2.
Ne fonctionne pas avec toutes les versions de tar.
Les commandes de compression Unix, par défaut, sont compress
et
uncompress
. Les fichiers compressés ont le suffixe .Z
ajouté à leur
nom.
Pour l’exemple :
compress part.igs
Créer un fichier compressé part.igs.Z
uncompress part.igs
Décompresser le contenu du fichier part.igs.Z
Note que l’usage de .Z
n’est pas requis.
Un autre utilitaire de compression commun est gzip
(et gunzip
). Ce
sont des outils GNU de compression et décompression. gzip utilise un
meilleur format de compression que le standard compress, mais n’est pas
installé sur tous les systèmes. Le suffixe pour les fichiers compressés
par gzip est .gz
gzip part.igs
Créer un fichier compressé part.igs.gz
gunzip part.igs
Extrait le contenu de l’archive part.igs.gz
L’utilitaire bzip2 a (en général) un meilleur taux de compression que gzip, mais prend plus de temps pour compresser ou décompresser des fichiers. Ce n’est pas un utilitaire commun comme gzip, mais il devient de plus en plus disponible. (À ce jour de la traduction, c’est devenu un outil commun !)
bzip2 part.igs
Créer un fichier compressé part.igs.bz2
bunzip2 part.igs.bz2
Décompresse le contenu du fichier part.igs.bz2
La plupart des commandes ont une page de manuel qui décrit comment
l’utiliser, de manière plus ou moins détaillée. Ces pages de manuels
sont appelés des man pages
parce qu’elles sont faites pour être lues
par des humains.
Exemple :
man ls
Lire le manuel de la commande ls
.Vous pouvez trouver les man pages en utilisant la commande apropos
.
Exemple :
apropos build
Afficher tous les man pages dont la description
contient le mot build
.Pour l’exemple, exécuter donc un man apropos
pour obtenir l’aide
détaillé de la commande apropos
.
vi
vi nom_fichier
Les modes d’édition : l’appui sur les touches ci-dessous permettent d’entrer en mode édition, puis d’écrire le contenu de votre document.
i
Insérer des caractères avant la position du curseur.
I
Insérer des caractères au début de la ligne courante.
a
Ajouter après la position du curseur.
A
Ajouter à la fin de la ligne courante.
r
Remplacer un caractère.
R
Mode remplacement
<ESC>
Sort des modes insertion.
x
Supprime un caractère
dd
Supprime la ligne courante et la met en mémoire-tampon
ndd
Supprime n lignes (n étant un nombre) et les mets dans la
mémoire-tampon.
J
Attache une nouvelle ligne à la fin de la ligne courante (et
supprime les caractères de retour-à-la ligne)
u
Annule la dernière commandeyy
Copie la ligne courante dans la mémoire-tampon
nyy
Copie n lignes dans la mémoire-tamon
p
Colle le contenu de la mémoire-tampon après la ligne courante
P
Colle le contenu de la mémoire-tampon avant la ligne courante
Le symbole ^
signifie l’appui simultanée sur la touche Ctrl
puis la touche signalée !
^d
Descend d’une page
^u
Remonte d’une page
:n
Positionne le curseur à la ligne n
:$
Positionne le curseur à la fin de la ligne courante
^g
Affiche le numéro de la ligne courante
h,j,k,l
Respectivement, à gauche, en bas, au-dessus, et à droite du
curseur. Vous pouvez aussi utiliser les touches fléchées si cela
fonctionne avec votre clavier.
:n1,n2:s/string1/string2/[g]
Remplace la chaîne de caractères 1 par la
chaine de caractères 2 sur les lignes n1 et n2. Quand g
est inclus
(pour global), toutes les instances de la chaînes de caractère 1 sur
chacunes des lignes sont remplacées. Si g
n’est pas inclus, seule
la première instance par ligne correspondante est remplacée.
^
correspond au début de ligne.
.
signifie tout caractère
$
correspond à la fin de ligne.
Ces caractères, ainsi que d’autres “caractères spéciaux” (tels que
l’anti-slash) peuvent être échappés par l’usage du symbole \,
tel que \/usr\/STRIM100\/SOFT
signifiant littéralement la chaîne de
caractère /usr/STRIM100/SOFT
Exemples :
:1,$:s/dog/cat/g
Remplacer chaque instance dog
par cat
, dans
tout le fichier. L’usage de :1,$
signifie du début à la fin du
fichier.:23,25:/frog/bird/
Sur les lignes 23 à 25, remplacer la première
instance de frog
par bird
, dans chacune de ces lignes.ex
Ces commandes sont toutes préfixées par l’usage du symbole :,
et affichées en bas, à gauche de l’écran. Ce sont les commandes ex
,
parce qu’elles font partie de l’éditeur de texte ex
, le précurseur de
l’éditeur de texte vi
.
Vous ne pouvez pas taper une commande ex
quand vous êtes dans un des
modes insertion. (la saisie de texte à l’écran). Pour pouvoir le faire,
il faut appuyer sur la touche ESC, qui vous fera sortir de ce
mode d’insertion.
:w
Sauvegarde le fichier courant
:w new.file
Sauvegarde le fichier courant, dans un nouveau fichier
:w! existing.file
Sauvegarde un fichier existant avec le contenu
du fichier courant.
:wq
Sauvergarde le fichier et sors de l’éditeur
:q
Ferme l’éditeur
:q!
Ferme l’éditeur sans faire de changement
:e filename
Ouvre le fichier ‘filename’ pour édition
:set number
Affiche le numéro de ligne
:set nonumber
Éteint le numéro de ligne
Le contenu des Foire-aux-Questions Usenet devraient être le premier endroit à lire pour vos questions. Vous pouvez y trouver beaucoup de manuel RTFM (Read the F*** Manuals ; Lis ce Fichu Manuel).
Le contenu de ce répertoire inclut les FAQs vi, bash, et comp.unix.questions.
Rechercher dans les archives Usenet est souvent très utile, aussi.
Google.com a sa propre archive Usenet (formellement Deja.com), voire les règles “Advanced Group Search”.
Ce document (comprendre l’original ; ce n’est pas le cas de la traduction) a été converti depuis un fichier texte, en utilisant Vim. Vim est la meilleure version du seul vrai éditeur de texte : vi.
Copyright (c) 2000-2006 - cliff@freeenginer.org
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with Invariant Section: Preface, with Front-Cover Texts, and with no Back-Cover Texts. A copy of the license can be found on the GNU web site here.
J’ai écrit historiquement cette traduction sur le wiki de la communauté “OpenBSD Pour Tous”.
Éditez votre fichier ~/.profile
!
alias add="doas pkg_add"
alias del="doas pkg_del"
alias enable="doas rcctl enable"
alias query="pkg_info -Q"
alias ll="ls -lart"
alias restart="doas rcctl restart"
alias start="doas rcctl start"
alias stop="doas rcctl stop"
# Alias
# Raccourcis pour 'ls'
alias ll='ls -l'
alias la='ls -a'
alias lla='ls -la'
alias lls='ls -s'
# Quelques alias pratiques
alias cls='clear'
alias less='less --quiet'
#Connaitre l'espace restant
alias dh='df -h'
# kill'em all
alias rmr='rm -rf'
alias cpr='cp -r'
# noir et blanc, c'est cool
alias xterm='xterm -bg black -fg white'
# Remonter d'un dossier et ls
alias u="cd .. && ls "
# Edition simple
alias v='vim'
# Voir le débit réseau
alias bw='systat ifstat'
# infos sur la charge de la machine
alias totop='systat vm'
# info ram/swap (free-like)
alias freemem='top -d1 | grep "^Memory" && printf "Swap: " ; swapctl -s'
# Une calculatrice en python
alias calc='python3.4 -ic "from math import *; from random import *"'
# compare 2 répertoire
alias diffdir='diff -rq $1 $2'
# réduire le poids d'un pdf
alias pdfmini="gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=fichier_reduit.pdf "
# adresse ip
alias whatsmyip='http_proxy="" ftp -o - -V http://ipecho.net/plain && echo ""'
alias whatsmyip2='ftp -o - -V http://ifconfig.me/ip'
# Enlever les commentaires :
alias nocomment='egrep -v "^\s*(#|$)"'
# insert image in latex slide
alias img2slide='mogrify -density 96 -units PixelsPerInch'
# easy pastebin
alias clbin='curl -v -F "clbin=<-" https://clbin.com'
# serveur http simple
alias pyserver='python3.4 -m http.server'
# w3m et ses bookmarks
alias web='w3m -B'
# star wars
alias sw='telnet towel.blinkenlights.nl'
# quels ports sont ouverts ?
alias openports='netstat -na -f inet |grep LISTEN'
# trouver un processus en lien avec un port/ip/proto/etc.
openpid() {
fstat | egrep "(^USER|$1)"
}
# take screenshot and upload. Save the URL in clipboard
alias shotup='scrot -s /tmp/shotup.png && curl -F "clbin=@/tmp/shotup.png" https://clbin.com -selection clipboard'
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
La majeure partie de ce qui est écrit ici provient, comme d’habitude, de la documentation.
Déjà, on commence par mettre tous les fichiers à graver dans un dossier que j’appelle ici “cd” par souci d’originalité :) .
Vérifiez bien que les documents ne prennent pas trop de place. Par exemple, j’ai un CD de 700MB , je regarde avec la commande “du” si ça passe :
$ du -h cd
472M cd
C’est bon :)
On fabrique maintenant un fichier moncd.iso
que l’on pourra graver :
$ mkhybrid -R -o moncd.iso cd/
On vide le cd :
# cdio -f cd0c blank
Et enfin, on grave l’iso :
# cdio -f cd0c tao moncd.iso
On peut vérifier que tout s’est bien passé en montant le CD fraîchement gravé :
# mount /dev/cd0c /mnt/cdrom
# ls /mnt/cdrom
ATTENTION : Pour les DVD, la démarche est légèrement différente.
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.
spamd fait semblant d’être un serveur mail afin de rejeter les spams. Il a été écrit dans l’optique d’être très efficace et ne pas ralentir la machine.
Bien sûr, il transmet les mails légitimes au serveur smtp ensuite.
Ce qui est rigolo en plus, c’est qu’il va faire en sorte de ralentir les spammeurs en communiquant tout doucement avec eux et leur faire consommer inutilement leur ressources :) .
Enfin, avantage non négligeable, il est présent par défaut dans OpenBSD.
Afin de reconnaître les spam, spamd va mettre en attente ceux qui contactent le serveur. Ils sont mis sur liste grise.
Normalement, un expéditeur légitime réessaie automatiquement de délivrer le message.
Lors du 2e essai, ce serveur est mis sur liste blanche.
Les spammeurs ne vont pas réessayer de délivrer le message. Dans ce cas, ils sont mis après un délai assez long sur liste noire. Par la suite, votre serveur n’écoutera même plus les requêtes provenant de ces spammeurs.
Afin d’enregistrer les vilains expéditeurs, il faudra exécuter spamd
régulièrement.
On commence par activer spamd au démarrage, en indiquant les options dont il aura besoin, puis on le lance :
rcctl enable spamd
rcctl set spamd flags "-v -G 15:4:4242"
rcctl start spamd
On va maintenant éditer la configuration du parefeu et filtre de paquets (packet filter). Il va envoyer à spamd tous le flux destiné au serveur smtp, qui relaiera normalement ensuite si le mail est légitime.
Voici ce qu’il faut donc ajouter dans /etc/pf.conf
:
table <nospamd> persist file "/etc/mail/nospamd"
pass in on egress proto tcp from any to any port smtp \
divert-to 127.0.0.1 port spamd
pass in on egress proto tcp from <nospamd> to any port smtp
pass in log on egress proto tcp from <spamd-white> to any port smtp
Dans l’ordre des lignes :
/etc/mail/nospamd
qui contiendra les expéditeurs légitimesVoilà pour le parefeu. N’oubliez pas de le recharger :
# pfctl -d && pfctl -ef /etc/pf.conf
Il est nécessaire de régulièrement charger la liste noire des spammeurs dans le parefeu afin que spamd fonctionne bien. Nous allons nous servir d’une tâche cron pour ça.
Éditez votre crontab puis ajoutez la ligne suivante :
*/10 * * * * /usr/libexec/spamd-setup
Nous lançons ici spamd-setup
toutes les 10 minutes. Ce temps doit être
inférieur au temps que doit attendre un expéditeur pour tenter de renvoyer
son message définit dans l’appel de spamd. Nous avions mis 15 minutes.
Vous pouvez piéger les spammeurs en laissant traîner sur le web une fausse adresse mail. Si spamd voit un message arriver pour cette adresse, alors il sait déjà que c’est un spam : il peut donc le mettre sur liste noire.
Vous voilà protégés pour l’avenir.
Afin de glisser cette “adresse-piège” sur le web sans que ça soit visible par les humain, vous pouvez l’insérer ainsi dans une page web de votre site :
<a href="mailto:blackhole@votre-nom-de-domaine.tld"></a>
Pour indiquer à spamdb cette adresse piège, il faut ajouter les options suivantes à spamdb (attention au “b” final, ce n’est pas spamd). :
# spamdb -T -a 'blackhole@votre-nom-de-domaine.tld'
Bien entendu, cette adresse piège ne doit pas être créée et ne risque pas de servir à quiconque.
Pour voir l’activité de spamd, lancez la commande spamdb
pour voir
apparaître des choses comme ça :
WHITE|62.4.1.33|||1462699174|1462699174|1465809574|1|0
GREY|46.105.39.61|2.mo178.mail-out.ovh.net|<contact@arpinux.org>|<thuban@yeuxdelibad.net>|1462696130|1462710530|1462710530|1|0
On peut lire dans l’ordre :
Il n’y a pas à dire, les “temps” sont illisibles pour les humains.
Utiliser la commande date
pour avoir un format lisible :
$ date -r 1462699174
Sun May 8 11:19:34 CEST 2016
Si vous constatez des erreurs en tapant spamdb
, vous pouvez autoriser
une IP ainsi :
# spamdb -a 12.234.56.67
J’ai écrit historiquement cette documentation sur le wiki de la communauté “OpenBSD Pour Tous”, (conjointement avec Xavier Catron).
Le but d’utiliser Unbound est d’avoir localement sur sa station son propre serveur DNS Cache (enregistrant la relation noms de domaine et adresses IP déjà visités, afin de ne pas aller interroger les serveurs DNS Root, sauf à changement de ladite information). Et, utiliser Unbound avec la gestion sécurisée des informations DNS, par le biais de la technologie DNSSEC, est un plus indéniable (cela évite d’avoir à obtenir des informations DNS faussées, par une action pirate).
Cette dernière est assumée, en partie, par l’outil dnssec-trigger !
Avec Debian, comme d’habitude, rien de bien compliqué !
# apt install unbound unbound-host dnssec-trigger
Les fichiers de configuration principaux :
/etc/unbound/
;/etc/dnssec-trigger/
Testez que l’installation de dnssec-trigger est correcte à l’aide de la
commande de contrôle dnssec-trigger-control-setup
:
Code : shell
# dnssec-trigger-control-setup
setup in directory /etc/dnssec-trigger
dnssec_trigger_server.key exists
dnssec_trigger_control.key exists
create dnssec_trigger_server.pem (self signed certificate)
create dnssec_trigger_control.pem (signed client certificate)
Signature ok
subject=/CN=dnssec-trigger-control
Getting CA Private Key
Setup success. Certificates created.
run this script again with -i to:
- enable remote-control in unbound.conf
- start unbound-control-setup
- add root trust anchor to unbound.conf
if you have not done this already
Si c’est votre cas, c’est une bonne chose ! :p
Pensez à redémarrer le service lié à unbound !
La configuration d’unbound ne pose pas de gros problème, en soit, il faut veiller à l’écriture correcte des informations !
Toutes les variables et leur impact sont expliquées dans la documentation officielle anglaise : https://unbound.net/documentation/unbound.conf.html
Voyons quelques détails dits de sécurité à paramétrer absolument dans votre
propre fichier de configuration, que l’on nommera ainsi, pour l’exemple :
/etc/unbound/unbound.conf.d/perso.conf
Pour tester la configuration de vos fichiers, utilisez la commande unbound-checkconf
!
access-control: 127.0.0.0/8 allow
## j’autorise l’interface de bouclage local sur la couche IPv4
access-control: 192.168.1.0/24 allow
## j’autorise le réseau local
access-control: 0.0.0.0/0 refuse
## j’interdis tout le reste de l’Internet !
Le segment réseau peut-être de type IPv4 ou IPv6. L’action à allouer peut-être :
allow
permet l’accèsallow_snoop
permet l’accès, en utilisant une technique de “cache snopping”,
qui donne le droit d’examiner le contenu en cache.deny
refuse l’accès - option par défaut, si non spécifiée
deny_non_local
,refuse
refuse l’accès, tout en envoyant un message d’erreur adéquat.refuse_non_local
Pour les autres options, ou afin de mieux saisir les subtilités, merci de lire la page officielle anglaise !
Code : unbound
harden-algo-downgrade: no
harden-glue: yes
hide-identity: yes
hide-version: yes
private-address: 192.168.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
use-caps-for-id: no
val-clean-additional: yes
Explications
harden-algo-downgrade
empêche ou non de choisir l’algorithme le plus faible .
no
est choisi, ce sera l’algorithme le plus faible qui sera élu…no
.
Cette option n’est pas reconnue avec la version Jessie, utilisez la version backports !private-address
renforcent l’aspect privé de ces réseaux.
Cela empêche l’inclusion de ces segments réseaux dans les réponses DNS,
et protège de la technique des “Relais DNS”
(qui utilise, par exemple, un navigateur internet comme relais ou proxy réseau).use-caps-for-id
est expérimentale et peut créer des bogues,
ou résultats incorrects - ne pas l’utiliser à moins d’être sûr de ce que vous faites…val-clean-additional
assure de nettoyer toutes les données DNS non sécuriséesCode : unbound
num-threads: 4
key-cache-slabs: 8
infra-cache-slabs: 8
msg-cache-slabs: 8
rrset-cache-slabs: 8
key-cache-size: 16m
msg-cache-size: 4m
rrset-cache-size: 8m
outgoing-range: 206
qname-minimisation: yes
so-rcvbuf: 1m
so-sndbuf: 1m
so-reuseport: yes
Explications
num-thread
correspond au nombre de cœurs CPU dont dispose
votre station, soit pour 4 CPU ayant chacun deux cœurs, on lui attribuera
le chiffre 8
.
Une manière d’être sûr du nombre de cœurs utilisés dans votre machine
est d’utiliser la commande suivante :
$ cat /proc/cpuinfo | grep processor | wc -l
*-cache-slabs
doivent être paramétrées
au double de la variable num-thread
. Ces variables gèrent les conflits
de verrouillage en les diminuant.*-cache-size
est sensible et doit être ainsi
paramétrée : la variable rrset-cache-size
doit être le double de la
variable msg-cache-size
; quant à la variable key-cache-size
, elle
doit être elle-même le double de la variable rrset
.outgoing-range
qui gère le nombre de connexions par cœurs
CPU doit être ainsi calculée : 1024 / nb_coeurs_CPU - 50so-reuseport
permet d’améliorer significativement les performances
de l’usage du protocole UDP !qname-minimisation
envoie un minimum d’information DNS pour
améliorer l’aspect privé de celles-ci :
Cette option n’est pas reconnue avec la version Jessie, utilisez la version backports !so-rcvbuf
,
et so-sndbuf
qui doivent être augmentées dans le cas de serveur surchargé.
Autrement, laissez la valeur 0
par défaut - cela utilise les valeurs systèmes !Code : unbound
# garde en cache les bons résultats
prefetch: yes
cache-min-ttl: 3600
cache-max-ttl: 86400
Code : unbound
# gestion logs
logfile: /var/log/unbound/unbound.log
use-syslog: yes
unwanted-reply-threshold: 10000000
val-log-level: 2
verbosity: 1
Explications
unwanted-reply-threshold
est définie, le nombre paramétré
total de réponses indésirables est gardé dans chacun des processus.
Ce nombre paramétré atteint déclenche une action défensive de nettoyage
des caches rrset
et autres messages, un avertissement est affiché
dans les journaux.
Il est recommandé de positionner ce nombre à une valeur de 10 Millions !verbosity
est le degré de verbosité des journaux :
0
signifie que seules les erreurs seront affichées ;1
que ce sont des informations opérationnelles - valeur par défaut - ;2
que celles-ci seront plus détaillées ;3
définit les informations par niveau de requêtes et leurs sorties ;4
restitue l’information du niveau d’algorithme utilisé ;5
, quant à lui, enregistre l’identification des clients en cas d’erreurs de cache.Code : unbound
# bloque certaines pubs
local-zone: "doubleclick.net" redirect
local-data: "doubleclick.net A 127.0.0.1"
local-zone: "googlesyndication.com" redirect
local-data: "googlesyndication.com A 127.0.0.1"
local-zone: "googleadservices.com" redirect
local-data: "googleadservices.com A 127.0.0.1"
local-zone: "google-analytics.com" redirect
local-data: "google-analytics.com A 127.0.0.1"
local-zone: "ads.youtube.com" redirect
local-data: "ads.youtube.com A 127.0.0.1"
local-zone: "adserver.yahoo.com" redirect
local-data: "adserver.yahoo.com A 127.0.0.1"
local-zone: "ask.com" redirect
local-data: "ask.com A 127.0.0.1"
Pour info, il existe des projets de listes, tels que :
Dans le cas d’usage de listes, il faut les inclure en utilisant la déclaration :
include: /var/lib/unbound/nom-fichier-liste
Code : unbound
statistics-interval: 0
extended-statistics: yes
statistics-cumulative: no
Explications
statistics-cumulative
est à paramétrer sur yes
-
si vous utilisez un outil d’affichage graphique des rapports, tel que Munin…Le fichier root.hints
est une liste des serveurs de noms faisant autorité,
les premiers serveurs DNS, dits roots
.
Pour le récupèrer :
# curl ftp://FTP.INTERNIC.NET/domain/named.cache -o /var/lib/unbound/root.hints
Puis, modifiez le fichier de configuration, pour ajouter :
root-hints: "var/lib/unbound/root.hints
La gestion DNSSEC se fait par l’usage de l’outil unbound-anchor
qui crée un fichier de clé nécessaire et l’ajout de la variable auto-trust-anchor-file
qui pointe vers ledit fichier de clés.
Exécutez :
# unbound-anchor -a "/var/lib/unbound/root.key"
La variable auto-trust-anchor-file
est normalement déclarée dans le fichier
/etc/unbound/unbound.conf.d/root-auto-trust-anchor-file.conf
.
Si ce fichier n’existe pas, vous pouvez l’ajouter à votre fichier de configuration
personnel, ou créer ledit fichier qui sera pris en charge lors du (re)démarrage
lié au service unbound.
Elle a cette teneur :
auto-trust-anchor-file: "/var/lib/unbound/root.key"
De même, il faut ajouter les variables suivantes à votre propre fichier de configuration :
Code : unbound
harden-below-nxdomain: yes
harden-dnssec-stripped: yes
harden-referral-path: yes
Explications
harden-referral-path
renforce la validation DNSSEC -
c’est une option expérimentale, sans norme RFC, et peut poser des problèmes
de performances !Un premier test à faire est l’usage de la commande dig
, telle que :
Code : shell
$ dig com. SOA +dnssec
; <<>> DiG 9.10.3-P4-Debian <<>> com. SOA +dnssec
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60764
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 14, ADDITIONAL: 1
(…)
Ce qu’il faut repérer dans la sortie complète de la commande dig
est
sur la ligne flags:
: il faut la présence du drapeau ad
-
si celui-ci figure bien, c’est bon signe ! :D
$ dig com. SOA +dnssec | grep ";; flags"
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
L’autre commande à utiliser est la commande unbound-host
qui permet
de s’assurer du même résultat, telle que :
Code : shell
$ unbound-host com. -f /var/lib/unbound/root.key -v
com. has no address (secure)
com. has no IPv6 address (secure)
com. has no mail handler record (secure)
$ unbound-host dnssec.cz -f /var/lib/unbound/root.key -v
dnssec.cz has address 217.31.205.51 (secure)
dnssec.cz has IPv6 address 2001:1488:0:3::5 (secure)
dnssec.cz mail is handled by 10 mail.nic.cz. (secure)
dnssec.cz mail is handled by 15 mx.nic.cz. (secure)
dnssec.cz mail is handled by 20 bh.nic.cz. (secure)
# unbound-host dnssec.cz -C /etc/unbound/unbound.conf -v
[1472755792] libunbound[44222:0] debug: switching log to /var/log/unbound/unbound.log
dnssec.cz has address 217.31.205.51 (secure)
dnssec.cz has IPv6 address 2001:1488:0:3::5 (secure)
dnssec.cz mail is handled by 10 mail.nic.cz. (secure)
dnssec.cz mail is handled by 15 mx.nic.cz. (secure)
dnssec.cz mail is handled by 20 bh.nic.cz. (secure)
Utilisez l’outil dnssec-trigger
est trivial :
Code : shell
# dnssec-trigger-control status
at 2016-09-01 08:41:22
authority 192.33.4.12: OK
http ster.nlnetlabs.nl (185.49.140.10): OK
state: auth secure
Un moyen visuel est d’ouvrir votre navigateur internet favori, puis d’aller sur les sites suivants :
Pensez à créer un fichier cron mensuel /etc/crond.monthly/unbound
, pour
mettre-à-jour les fichiers root.hints
, et ads server
:
Code : shell
#!/bin/sh
# update file named.cache
curl ftp://FTP.INTERNIC.NET/domain/named.cache -o /var/lib/unbound/root.hints
# update file ads servers
curl -sS -L --compressed "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=unbound&showintro=0&mimetype=plaintext" > /var/lib/unbound/unbound_ad_servers
chown unbound:unbound /var/lib/unbound/unbound_ad_servers
Si vous avez l’erreur ci-dessous :
# dnssec-trigger-control status
Mar 20 15:08:13 dnssec-trigger-control[2016] fatal error: SSL handshake failed error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed
redémarrez d’abord le service unbound !
J’ai écrit pour la première fois cet article pour le wiki de la communauté de Debian-fr.xyz !
Tout d’abord commençons par cet avertissement auquel vous devez consentir, AUTREMENT passez votre chemin et fermer cette page :
Je ne suis pas responsable en cas de problème sur votre tablette ; vous prenez VOS responsabilités !
Pour toute manœuvre root, flash, etc, veillez à ce que votre tablette soit impérativement à plus de 50 % de charge de batterie… mieux vaut la brancher électriquement.
/!\ Risque de brickage /!\
FONCTIONNE À PARTIR D’ANDROID 4.4.4
Concernant les tablettes Rockchip, oubliez l’usage de l’outil fastboot - cet outil ne fonctionne pas avec !
L’outil adb
va nous servir simplement à redémarrer la tablette dans le
mode nécessaire : le mode bootloader…
$ adb reboot-bootloader
Dans le mode bootloader, la tablette semble éteinte ; en effet, l’écran est tout noir, et aucune des touches - s’il y’en a - ne réagit !
De même, dans ce mode, l’outil adb
ne sera plus d’aucune utilité.
Cet outil nous permet donc de flasher et/ou sauvegarder les partitions de nos tablettes.
Il s’utilise aussi en mode terminal console.
De même, il est nécessaire d’être dans le mode bootloader afin qu’il fonctionne, sinon il ne trouvera pas correctement votre tablette !
Entrez dans le répertoire de l’outil, puis en mode console, exécutez-le :
Code : shell
$ ./upgrade_tool
List of rockusb connected
DevNo=1 Vid=0x2207,Pid=0x310b,LocationID=217 Loader
Found 1 rockusb,Select input DevNo,Rescan press <R>,Quit press <Q>:
On remarque qu’un périphérique est détecté en tant que device numero = 1
,
les paramètres VendorId (Vid) et ProductId (Pid) sont ceux qui
correspondent bien à notre tablette.
Le système attend votre réponse ; tapez le chiffre correspondant,
dans ce cas, le chiffre 1
!
Code : shell
Found 1 rockusb,Select input DevNo,Rescan press <R>,Quit press <Q>:1
---------------------Tool Usage ---------------------
Help: H
Quit: Q
Version: V
Clear Screen: CS
------------------Upgrade Command ------------------ </nowiki>
ChooseDevice: CD
SwitchDevice: SD
UpgradeFirmware: UF <Firmware>
UpgradeLoader: UL <Loader>
DownloadImage: DI <-p|-b|-k|-s|-r|-m image> [parameter file] </nowiki>
DownloadBoot: DB <Loader> </nowiki>
EraseFlash: EF <Loader|firmware> </nowiki>
LowerFormat: LF
----------------Professional Command ----------------- </nowiki>
TestDevice: TD
ResetDevice: RD
ReadFlashID: RID
ReadFlashInfo: RFI
ReadChipInfo: RCI
ReadSector: RS <BeginSec> <SectorLen> [-decode] [File] </nowiki>
WriteSector: WS <BeginSec> <File> </nowiki>
ReadLBA: RL <BeginSec> <SectorLen> [File]
WriteLBA: WL <BeginSec> <File>
EraseBlock: EB <CS> <BeginBlock> <BlokcLen> [--Force]
-------------------------------------------------------
Rockusb>
À savoir que certaines commandes sont directement fonctionnelles, en mode
console, en tant qu’argument de l’outil.
Ce sont les commandes UF
, UL
, DI
, DB
, EL
, LF
, SD
, RD
…
Tel que : ./upgrade_tool UF update.img
De même, la commande RD signifiant Reset Device est en fait la commande pour redémarrer la tablette - c’est un reboot, ni plus ni moins !
Depuis la version 1.13 de l’outil “Linux Upgrade Tool”, il est possible de flasher simultanément plusieurs partitions.
Tel que : ./upgrade_tool DI -k,-s kernel.img, system.img
Très simplement, en utilisant l’option UF
:
Code : shell
$ Rockusb>UF PiPO_M9pro_update_andriod4.4_20140504.img
Loading firmware...
Support Type:RK31 FW Ver:4.4.02 FW Time:2014-05-04 17:38:05
Loader ver:2.10 Loader Time:2013-12-27 22:12:16
Upgrade firmware ok.
ou, directement en mode CLI : ./upgrade_tool UF PiPO_M9pro_update_andriod4.4_20140504.img
Pour flasher une ROM Custom, telles que les RileyROM, FinlessRom, il faut, dans un premier temps décompresser, l’archive de la ROM.
Copier le répertoire RileyRom dans celui de l’outil “Linux Upgrage Tool” ; cela simpliefiera l’usage.
Code : shell
$ Rockusb>LF
Lower Format Device,total(8192),current(7460)
Lower Format Device OK.
Code : shell
$ Rockusb>UL RileyROM/RK3188Loader(L)_V2.10.bin
Loading loader...
Support Type:RK310B Loader ver:2.10 Loader Time:2013-12-27 22:12:16
Upgrade loader ok
Code : shell
$ Rockusb>CD
List of rockusb connected
DevNo=1 Vid=0x2207,Pid=0x310b,LocationID=210 Loader
Found 1 rockusb,Select input DevNo,Rescan press <R>,Quit press <Q>:1
parameter
:
Code : shell
$ Rockusb>DI -p RileyROM/parameter
Download parameter ok.
Code : shell
$ Rockusb>DI -k,-b,-r,-m,-s RileyROM/kernel.img,RileyROM/boot.img,RileyROM/recovery.img,RileyROM/misc.img,RileyROM/system.img
Download kernel start...
Download image ok.
Download boot start...
Download image ok.
Download recovery start...
Download image ok.
Download misc start...
Download image ok.
Download system start...
Download image ok.
buffer overflow detected: ./upgrade_tool terminated
le logiciel vient de killer ;
relancez-le en utilisant la commande DI
fichier après fichier…ok
, il ne reste
plus qu’à redémarrer la tablette :
Code : shell
$ Rockusb>RD
Reset Device OK.
Sortir du mode maskrom n’est pas chose aisée car vous n’avez aucun voyant, ni aucun moyen visuel pour être sûr !
L’outil upgrade_tool
nous y aide :
Code : shell
$ ./upgrade_tool
List of rockusb connected
DevNo=1 Vid=0x2207,Pid=0x310b,LocationID=265 Maskrom
Found 1 rockusb,Select input DevNo,Rescan press <R>,Quit press <Q>:
Comme nous le voyons sur la ligne DevNo
, à la fin de celle-ci, est indiqué
Maskrom
- au lieu de Loader
!
On lance le formatage de l’image avec upgrade_tool :
Code : shell
$ Rockusb>UF PiPO_M9pro_update_andriod4.4_20140504.img
Loading firmware...
Support Type:RK31 FW Ver:4.4.02 FW Time:2014-05-04 17:38:05
Loader ver:2.10 Loader Time:2013-12-27 22:12:16
Upgrade firmware ok.
Une fois le message Upgrade firmware ok
affiché, la tablette redémarrera
toute seule !
Le logiciel vient de terminer son processus, à cause d’un problème de gestion de la mémoire. Veuillez relancer le processus fichier après fichier !
Il y a de fortes probabilités pour que le chemin entré ne corresponde pas à celui dans votre système de fichier…
Le logiciel vous dit d’utiliser la commande CD
pour faire (re?)connaître
votre tablette, à nouveau !
Le programme n’arrive pas à faire redémarrer la tablette… c’est signe qu’il y a un problème de communication entre celle-ci et votre ordinateur.
Cherchez à comprendre la raison !
Tout d’abord commençons par cet avertissement auquel vous devez consentir, AUTREMENT passez votre chemin et fermer cette page :
Je ne suis pas responsable en cas de problème sur votre tablette ; vous prenez VOS responsabilités !
Pour toute manœuvre root, flash, etc, veillez à ce que votre tablette soit impérativement à plus de 50 % de charge de batterie… mieux vaut la brancher électriquement.
/!\ Risque de brickage /!\
La commande principale est :
$ adb backup -f nom_fichier_sauvegarde.ab
Si l’option -f
n’est pas spécifiée, le fichier backup.ab
sera créé dans
le répertoire courant où est exécutée la commande de sauvegarde…
L’aide nous restitue :
Code : shell
adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]
- write an archive of the device's data to <file>.
If no -f option is supplied then the data is written
to "backup.ab" in the current directory.
(-apk|-noapk enable/disable backup of the .apks themselves
in the archive; the default is noapk.)
(-obb|-noobb enable/disable backup of any installed apk expansion
(aka .obb) files associated with each application; the default
is noobb.)
(-shared|-noshared enable/disable backup of the device's
shared storage / SD card contents; the default is noshared.)
(-all means to back up all installed applications)
(-system|-nosystem toggles whether -all automatically includes
system applications; the default is to include system apps)
(<packages...> is the list of applications to be backed up. If
the -all or -shared flags are passed, then the package
list is optional. Applications explicitly given on the
command line will be included even if -nosystem would
ordinarily cause them to be omitted.)
$ adb backup -f nom_fichier_sauvegarde.ab -apk -obb
Cette commande sauvegarde les fichiers apk des applications installées.
L’option par défaut est -noapk
qui signifie que les fichiers apk ne seront pas sauvegardés !
L’option -obb
implique la sauvegarde des fichiers relatifs aux applications
installées, tels que fichiers de sauvegarde, de config, etc…
par défaut, c’est l’option -noobb
qui est active !
$ adb backup -f nom_fichier_sauvegarde.ab package1 package2 package_n
Sauvegarde les noms des applications concernées !
L’outil adb
peut servir à sauvegarder indirectement les partitions de votre tablette…
Pour cela, il faut télécharger l’outil rkdump !
Puis l’utiliser ainsi :
$ adb push rkdump /data/
$ adb shell chmod 0755 /data/rkdump
Puis utiliser l’outil rkdump comme décrit dans son tutoriel…
$ adb backup -f nom_fichier_sauvegarde.ab -shared
Sauvegarde le contenu de la SD Carte, ainsi que de tout répertoire de stockage partagé.
Il est bien sûr nécessaire d’avoir une SD Carte dans votre appareil…
Par défaut, c’est l’option -noshared
qui est active et implique la non sauvegarde !
$ adb backup -f nom_fichier_sauvegarde.ab -system
Par défaut, c’est l’option -nosystem
qui est activée, ce qui a pour effet
de ne pas inclure les applications systèmes !
$ adb backup -f nom_fichier_sauvegarde.ab -all
Cette commande implique la sauvegarde de toutes les applications installées, dont les applications systèmes.
Cette option intègre l’option -system
!
Le moyen pertinent de sauvegarder tout correctement est, sans s’occuper du contenu de la SD Carte :
$ adb backup -f nom_fichier_sauvegarde.ab -apk -obb -all
$ adb restore nom_fichier_sauvegarde.ab
Tout ce qui concerne le contenu du fichier de sauvegarde sera restauré !
Tout d’abord commençons par cet avertissement auquel vous devez consentir, AUTREMENT passez votre chemin et fermer cette page :
Je ne suis pas responsable en cas de problème sur votre tablette ; vous prenez VOS responsabilités !
Pour toute manœuvre root, flash, etc, veillez à ce que votre tablette soit impérativement à plus de 50 % de charge de batterie… mieux vaut la brancher électriquement.
/!\ Risque de brickage /!\
Tablettes testées :
Tant que le mode “Débogage USB” n’est pas actif, ou que vous ne pouvez pas l’activer, pas la peine de continuer… en effet, sans ce mode actif, le périphérique NE PEUT être reconnu !
Ce mode s’active différemment selon la version d’Android.
Veuillez-vous référer à la documentation technique de votre périphérique…
Il faut installer les outils suivants : android-tools-adb android-tools-fastboot android-tools-fsutils
Les deux derniers ne sont pas strictement nécessaires…
À vous de le faire, selon votre convenance - terminal-console, synaptic, etc.
Pour faire reconnaître proprement la tablette, il faut :
lsusb
.Exemple : Pour une tablette PiPo, telle la M8HD, vous aurez comme réponse :
$ lsusb
(…)
Bus 002 Device 014: ID 2207:0010
L’information importante est celle après ID
, dans ce cas : 2207:0010
Il nous faut créer une règle udev
, et pour cela, écrire le fichier /etc/udev/rules.d/51-android.rules
:
SUBSYSTEM=="usb", ATTR{idVendor}=="2207", MODE="0666", GROUP="plugdev"
=> Modifiez dans cette règle selon les informations idVendor, idProduct que vous avez trouvées…
Ensuite, il nous faut créer/modifier un autre fichier utile ~/.android/adb_usb.ini
,
pour y ajouter l’information de l’identifiant du fabriquant de la manière
suivante, soit un 0x
suivi de idVendor, un identifiant par ligne.
Pour l’exemple ci-dessus, ce serait 0x2207
=> Assurez-vous que votre utilisateur linux soit dans le groupe plugdev
…
sinon ajoutez-le !
# usermod -G plugdev votre_id_utilisateur
=> Enregistrez le fichier, puis redémarrez udev : # service udev restart
Pour être sûr que la tablette soit reconnue, utilisez la commande adb devices
:
$ adb devices
List of devices attached
WAWJM5UMUW device
Pour le reste, tapez la commande adb
; elle vous restituera les différentes options !
Êtes-vous sûr d’avoir installé
les outils adb
???
Si rien n’est reconnu, et donc qu’aucun device n’apparaît, c’est que vous
avez peut-être mal renseigné le fichier /etc/udev/rules.d/51-android.rules
et/ou n’avez pas redémarré le système udev !
Si malgré tout, vous êtes absolument sûr d’avoir bien rempli le fichier en question, et d’avoir redémarré udev, il peut être intéressant d’effectuer la manipulation suivante :
~/.android/adb_usb.ini
, et écrivez dedans 0x
suivi de votre idVendorPour la tablette PiPo M8HD, ce sera : 0x2207
# adb kill-server
adb devices
adb devices
: ???????????? no permissionsLorsque je tape adb devices
, le périphérique n’est pas reconnu et il est
affiché ???????????? no permissions
Il vous faut tuer le serveur, le redémarrer avec des droits administrateur ensuite le périphérique apparaîtra !
$ adb kill-server
# adb start-server
adb devices
: offlineLorsque je tape adb devices
, le périphérique est reconnu mais affiché offline
$ adb devices
List of devices attached
WAWJM5UMUW offline
Il vous faudra alors :
À ce moment-là, essayez à nouveau la commande adb devices
; vous devriez
voir apparaître votre périphérique… correctement !
Si vous fonctionnez avec une distribution GNU/Linux 64 bits, c’est qu’il vous manque les librairies pour l’architecture 32 bits !
Vous pouvez lire mes autres articles, pour :
Ce tutoriel n’aurait pas existé sans le fourmillement d’idées glanées ici et là… merci à leurs auteurs respectifs !
Tout d’abord commençons par cet avertissement auquel vous devez consentir, AUTREMENT passez votre chemin et fermer cette page :
Je ne suis pas responsable en cas de problème sur votre tablette ; vous prenez VOS responsabilités !
Pour toute manœuvre root, flash, etc, veillez à ce que votre tablette soit impérativement à plus de 50 % de charge de batterie… mieux vaut la brancher électriquement.
/!\ Risque de brickage /!\
FONCTIONNE AVEC ANDROID 4.2.2, 4.4.2, 4.4.4
Tablette testée :
TOUTES les manipulations, que nous allons faire, se font dans un terminal console !
Décompressez l’archive de Supersu, précédemment téléchargée et allez dans le répertoire de l’archive décompressée.
Vous trouverez dans l’archive de SuperSu des répertoires portant les noms relatifs aux différentes architectures matérielles de tablettes gérées :
Si dans l’archive de SuperSu, vous n’avez pas de répertoire correspondant à votre version, c’est que vous avez une ancienne version… téléchargez la plus récente !!!
Vérifions que la tablette soit “vue” :
$ adb devices
List of devices attached
WAWJM5UMUW device
Entrons la tablette dans le mode en écriture nécessaire :
$ adb wait-for-device
adb root
adb remount
Si la commande adb root
restitue adbd cannot run as root in production build
, cela semble compromis
!
Si la commande adb remount
ne fonctionne pas :
adb root
a fonctionné ; essayez la commande :
adb shell mount -o remount,rw /system
Si elle ne fonctionne pas non plus… cela ne sert à rien d'aller plus loin !
adb root
n’a pas fonctionné, et que vous avez
le message suivant remount failed: permission denied
… inutile d'aller plus loin !
Détectons votre version Android :
$ adb shell getprop ro.build.version.sdk
17
Si cela ne fonctionne pas, essayez ceci :
$ adb shell cat /system/build.prop | grep "ro.build.version.sdk="
ro.build.version.sdk=17
17
est Jelly Bean.19
, nous avons bien KitKat.Détectons votre architecture :
$ adb shell getprop ro.product.cpu.abi
armeabi-v7a
Si cela ne fonctionne pas, essayez ceci :
$ adb shell cat /system/build.prop /default.prop | grep -m 1 "ro.product.cpu.abi="
ro.product.cpu.abi=armeabi-v7a
Les valeurs détectées correspondent aux architectures nommées par SuperSU !
Dirigez-vous dans le répertoire de l’archive décompressée de SuperSU !
En partant du principe que l’architecture détectée correspond à “armv7” -
adaptez selon votre architecture - passons à la phase de rootage proprement dite :
$ adb push armv7/su /system/xbin/su
$ adb shell chown root.root /system/xbin/su
$ adb shell chmod 0755 /system/xbin/su
Installons SuperSu :
$ adb push common/Superuser.apk /system/app/Superuser.apk
$ adb shell chown root.root /system/app/Superuser.apk
$ adb shell chmod 0644 /system/app/Superuser.apk
Copier su
en daemonsu
, qui sera lancé en tant que service par le système
au démarrage :
$ adb shell cp /system/xbin/su /system/xbin/daemonsu
$ adb shell chown root.root /system/xbin/daemonsu
$ adb shell chmod 0755 /system/xbin/daemonsu
La deuxième étape est d’injecter le fichier install-recovery.sh
-
c’est lui qui lancera daemonsu au démarrage - :
$ adb push common/install-recovery.sh /system/etc/install-recovery.sh
$ adb shell chown root.root /system/etc/install-recovery.sh
$ adb shell chmod 0755 /system/etc/install-recovery.sh
Redémarrons proprement la tablette :
$ adb reboot
adb kill-server
Une fois, la tablette redémarrée, entrez dans votre session, il vous sera certainement demander de mettre-à-jour le binaire SuperSu : faites-le ! Sinon, cliquez sur l’icône de Supersu, et faites-la mise-à-jour qui sera demandée.
Puis cliquez sur le binaire SuperSU - qui la première fois, vous demandera d’installer le binaire SU - choisissez le mode normal, quand il vous sera proposé “Normal” ou “TWRP”.
Si le binaire vous informe que tout est ok, redémarrez à nouveau la tablette !
Vous pouvez lire mes autres articles, pour :
Nvidia a créé une technologie hybride, appelée Optimus. Cette technologie a pour but d’utiliser la puce graphique intégrée, généralement de marque Intel, ainsi que le processeur graphique, couplée à la première puce, de marque Nvidia. Cela permet de faire fonctionner le GPU Nvidia, à la demande, lors de nécessités de fonctions 3D poussées (vidéos, jeux…), et de “rendre la main” à l’IGP Intel, soulageant ainsi la batterie, pour le reste.
Un développeur a créé un projet, nommé Bumblebee, qui nous apporte une certaine gestion de cette technologie. Elle n’est pas complètement gérée, mais est fonctionnelle ! Néanmoins, la gestion HDMI n’est pas accessible…
# apt remove --purge nvidia-*
Nativement sous Linux, cette technologie n’est pas pleinement supportée. Officiellement, depuis la version 319.12, Nvidia apporte son support, en phase bêta - cela nécessite de pouvoir connecter l’écran au GPU Nvidia ; cette option est modifiable par certains BIOS récents. Si votre pilote est plus ancien, ou que vous n’êtes pas dans ce cas de configuration matérielle, cette page est vraiment faite pour vous.
Si vous voulez être sûr d’avoir une telle technologie, entrez la commande
suivante dans votre terminal préféré :
lspci | egrep "VGA|3D|Display"
Si le système vous répond, ainsi, avec deux lignes, telles que :
$ lspci | egrep "VGA|3D|Display"
00:02.0 VGA compatible controller: Intel Corporation 2nd Generation Core Processor Family Integrated Graphics Controller (rev 09)
01:00.0 VGA compatible controller: NVIDIA Corporation GF108 [GeForce GT 540M] (rev ff)
Alors, c’est votre cas !
Explications
INFORMATION : Ne cherchez pas à utiliser le pilote libre ’nouveau’ si votre carte graphique de fabriquant nvidia n’est pas supportée par celui-ci.
Pour récapituler, il faut la version du serveur X suivante pour :
La version du serveur X est disponible à partir de :
De fait, les cartes de famille Maxwell, ou Pascal, n’ont pas le support du pilote libre ni pour Jessie, ni pour Stretch. Pour les plus récentes, passez directement à nvidia. Si votre carte graphique n’est pas supportée, ou semble mal supportée du fait de saccades, utilisez directement le projet Bumblebee avec le pilote privatif !
Vérifiez que vous n’avez aucun des deux modules suivants installés et/ou chargés :
$ lsmod | egrep -i "nouveau|vga_switcheroo"
Si c’est le cas, il faudra les décharger, à l’aide de la commande :
# modprobe -r nom-du-module
Vérifier que vous avez bien les binaires, ci-dessous, installés :
# apt install gcc make linux-headers-i586 dkms bbswitch-dkms
# apt install -t stretch-backports gcc make linux-headers-i686 dkms bbswitch-dkms
# apt install gcc make linux-headers-amd64 dkms bbswitch-dkms
Puis, assurez-vous que le module bbswitch fonctionne bien :
# modprobe bbswitch load_state=0
Vérifiez que vous n’avez pas de fichier de configuration /etc/X11/xorg.conf
,
ni de répertoire /etc/X11/xorg.conf.d/
- si c’est le cas, supprimez-le
avec vos droits administrateur !
La page wiki du projet Debian nous informe que les utilisateurs de Jessie, et Sid peuvent installer Bumblebee à partir des dépôts officiels Debian.
Depuis le 26.05.2013, cela semble aussi le cas pour les utilisateurs des dépôts Wheezy-Backports !
contrib
et non-free
.Architecture 64 bits : Pensez à ajouter la gestion de l’architecture i386,
et installez en plus le package primus-libs-ia32
- anciennement primus-libs:i386 -
si vous voulez faire fonctionner un binaire 32 bits.
Mettez-à-jour votre système, et installez les binaires :
bumblebee
- rien que pour l’usage du pilote libre nouveau
,bumblebee-nvidia
- pour l’usage du pilote privatif Nvidia
.# apt update && apt install bumblebee mesa-utils
Ainsi que le fait remarquer le changelog, il est suggéré d’installer à-partir de la version 1.0.15-2 du serveur X nouveau le firmware firmware-misc-nonfree. Si vous exécutez Buster, ou supérieure, faites-le !
# apt update && apt install bumblebee-nvidia primus nvidia-kernel-dkms nvidia-xconfig nvidia-settings nvidia-vdpau-driver vdpau-va-driver mesa-utils xserver-xorg-video-nvidia linux-headers-$(uname -r)
Préférez la version des backports si elle est disponible !
(En 2015, vous auriez pu subir ce bogue 735049 …)
INFORMATION : Il semble nécessaire d’installer le binaire VirtualGL, requis par Optirun ; malheureusement il n’est pas dans les dépôts Debian.
Téléchargez-le à partir de la page de téléchargement du projet…
ne téléchargez pas l’archive .tar.gz ; cliquez sur le répertoire portant
le nom de la dernière version en cours, puis vous trouverez parmi les
différents fichiers un fichier portant le nom suivant virtualgl_num-version_arch.deb
(où ’num-version’ est le numéro de version en cours, et ‘arch’ est à choisir selon votre architecture…)…
puis installez-le à l’aide de l’outil dpkg
…
Avec les droits administrateur, il vous faut ensuite ajouter votre utilisateur
au groupe bumblebee :
# adduser ID_USER bumblebee
Pensez à redémarrer votre session, voire votre machine !
Les configurations ci-dessous ne sont normalement pas nécessaires !
Ces informations sont utiles au cas où se pose un souci relatif à l’utilisation .
Il peut être utile d’informer Bumblebee d’utiliser le module nvidia, au lieu du module nouveau. Par défaut, il utilise le pilote nouveau.
Avec des droits administrateur, il faut d’abord modifier le fichier /etc/bumblebee/bumblebee.conf
pour configurer la ligne DRIVER=
, telle que :
DRIVER=nvidia
nvidia
ne fonctionne pas, changez pour DRIVER=nvidia-current
.Pensez à redémarrer le service !
Cela peut être intéressant de “blacklister” le module nouveau, si et seulement si, vous voulez n’utiliser que le pilote privatif Nvidia. (afin d’être sûr que ce ne sera pas ce module qui gérera la carte Nvidia, mais bien le pilote Nvidia !)
Créez, avec vos droits administrateur, le fichier /etc/modprobe.d/nouveau-blacklist.conf
,
et ajoutez ces écritures :
blacklist nouveau
blacklist lbm-nouveau
options nouveau modeset=0
alias nouveau off
alias lbm-nouveau off
Si le système ne le fait pas tout seul, comme un grand, pensez à faire courir à nouveau le module pour votre kernel, avec vos droits administrateur !
Avec la commande dkms
, telle que :
# dpkg-reconfigure nvidia-kernel-dkms
Pour gérer correctement l’énergie de la batterie lors de l’usage de la
carte Nvidia, il peut être nécessaire de créer le fichier /etc/modprobe.d/bbswitch.conf
et d’y ajouter ceci - normalement le projet Bumblebee installe le paquet
bbswitch et le gère correctement - :
options bbswitch load_state=0 unload_state=0
Ensuite, il vous faut modifier le fichier /etc/bumblebee/bumblebee.conf
et configurer les lignes PMMethod
ainsi :
PMMethod=bbswitch
Pensez à redémarrer le service !
Ensuite, testez le bon fonctionnement de la gestion de la batterie.
OPTIMUS_PREFIX
# sh -c 'echo OPTIMUS_PREFIX=\"primusrun\" >> /etc/environment'
$OPTIMUS_PREFIX %command%
Une solution plus simple est d’éditer les propriétés de lancement et d’ajouter
directement : primusrun %command%
Toutes les étapes précédentes de vérifications
,
d’installations
et de configurations
,
ayant été faites, vous pouvez être sûr que Bumblebee fonctionne grâce au
binaire optirun.
Donc, pour activer la gestion du GPU Nvidia, il faut faire précéder toute
commande par l’usage de la commande optirun
.
$ optirun [optirun-options] <application> [application-parameters]
Pour trouver la liste des options de optirun, vous pouvez, soit :
man optirun
,$ optirun --help
Le premier test que vous pouvez faire est :
$ optirun glxgears -info
Ne cherchez pas à l’utiliser en cliquant sur l’icône correspondante, dans votre menu, cela ne fonctionnera pas.
Il vous faut le lancer ainsi - c’est le seul moyen ! - :
$ optirun nvidia-settings -c :8
Selon votre version de debian :
/etc/init.d/bumblebeed restart
service bumblebeed restart
systemctl restart bumblebeed
ATTENTION : Depuis Janvier 2014, lors de l’installation du package bumblebee-nvidia, il est possible que vous ayez droit à un fenêtre d’avertissement vous demandant de créer le fichier xorg.conf !
Bogue 735049 qui semble être résolu depuis octobre 2015 !
Vérifiez le journal de dmesg pour savoir si vous trouvez la référence suivante :
Refused to change power state, currently in D3
Cela semble être dû à un problème de gestion de l’ACPI (souvent retrouvés dans des portables de marque Dell) avec le noyau 4.8 et plus récent.
Éditez /etc/bumblebee/bumblebee.conf
pour paramétrez PMMethod=none
.
Si vous utilisez le pilote nvidia, il peut être utile de modifier le
fichier /etc/default/grub
pour ajouter la désactivation suivante : pcie_port_pm=off
Mettez-à-jour votre grub et redémarrez votre ordinateur :
# update-grub
# shutdown -r now
Ouvrez le fichier /etc/bumblebee/bumblebee.conf
, avec les droits administrateur,
et modifiez la ligne Driver=
par Driver=nvidia
.
Ouvrez le fichier /etc/bumblebee/bumblebee.conf
, avec les droits administrateur,
et dans la section [Driver-nvidia]
, vérifiez la ligne KernelDriver=
qu’elle soit bien ainsi KernelDriver=nvidia-current
.
Pour vérifier le nom du module nvidia, exécutez les deux commandes suivantes :
# modinfo nvidia
# modinfo nvidia-current
Normalement vous devriez avoir ces retours :
# modinfo nvidia
modinfo: ERROR: Module nvidia not found.
ou, par exemple :
# modinfo nvidia-current
filename: /lib/modules/3.16.0-4-amd64/updates/dkms/nvidia-current.ko
alias: char-major-195-*
version: 340.96
supported: external
license: NVIDIA
(…)
Si jamais, vous avez un résultat sur modinfo nvidia
, modifiez la ligne
KernelDriver=
ainsi KernelDriver=nvidia
<= ce qui ne devrait pas avoir lieu !
Si aucune des deux commandes ne retourne rien, vous avez eu un souci lors de l’installation <= ce n’est pas normal ; cherchez la raison !
Bogue 717687
Vérifiez l’installation du paquet “xserver-xorg-video-nvidia” - s’il n’est pas installé, faites-le !
Ouvrez le fichier /etc/bumblebee/xorg.conf.nvidia
, et ajoutez les informations suivantes :
Section "Screen"
Identifier "Default Screen"
Device "DiscreteNvidia"
EndSection
Bogue 756522 qui touche Debian Jessie, à-propos des Bumblebee versions : 3.2.1-5, 3.2.1-7 et nvidia versions : 340.*,
Profitez-en pour vérifier l’écriture de l’identifiant du Bus PCI relatif à votre carte graphique Nvidia.
ATTENTION : L’identifiant de Bus PCI doit bien être écrit ainsi : BusID “PCI:01:00:0” - et non pas BusID “PCI:01:00.0”.
Parfois il peut être nécessaire de mettre en commentaire l’identifiant de Bus PCI, pour que cela puisse fonctionner correctement… ce qui normalement est le cas d’une installation par défaut !
Si le serveur X est >= 1.18 et que votre Debian est une Testing, ou une Sid, il semble exister une incompatibilité entre le projet Bumblebee et le paquet xserver-xorg-legacy, donc virez ce dernier, s’il est installé !
Vérifiez l’installation du paquet xserver-xorg-input-mouse, si ce n’est pas le cas, faites-le !
Vérifiez le fichier /etc/bumblebee/xorg.conf.nvidia
.
Vérifiez que votre identifiant de Bus PCI soit correctement écrit !
Ouvrez le fichier /etc/bumblebee/xorg.conf.nvidia
, et modifiez l’option BusID.
Vous trouverez cette information par l’usage de la commande lsusb
…
voir le chapitre Vérification !
Vérifiez le fichier de configuration que vous venez de modifier !!!
Que ce soit /etc/bumblebee/xorg.config.nvidia
ou /etc/bumblebee/xorg.config.nouveau
,
vous avez créé/modifié une section, et oublié/supprimé par erreur, de fermer
correctement la section, voire une section est mal écrite !
Vérifiez que le service Bumblebee soit fonctionnel !
Le “pont” (‘bridge’ en anglais) que vous cherchez à utiliser avec
l’option -b
d’optirun n’existe pas. Modifiez votre commande !!!
Ce message d’erreur vous informe que votre identifiant utilisateur semble ne pas être ajouté groupe bumblebee .
Ajoutez-le !
Vérifiez la sortie dmesg !
Si dmesg
vous informe du souci GPU suivant fallen off the bus
, il y a
deux manières de régler le problème :
Testez la commande suivante, avant le lancement d’optirun :
# tee /sys/module/rcutree/parameters/rcu_idle_gp_delay <<<1
Si cela fonctionne en effet correctement, modifiez le fichier /etc/default/grub
pour ajouter l’information suivante à la ligne de commande GRUB_CMDLINE_LINUX_DEFAULT : rcutree.rcu_idle_gp_delay=1
.
Mettez-à-jour votre grub et redémarrez votre ordinateur :
# update-grub
# shutdown -r now
L’autre solution est de vérifier votre version de kernel linux - en effet ce problème concerne les noyaux versions 3.10 à 3.19 !
Soit vous choisissez un noyau antérieur, soit vous upgradez sur un noyau plus récent !
Il semble que ce soit surtout un bogue Nvidia… cf Bumblebee issue 445
L’erreur complète est la suivante :
error while loading shared libraries: libturbojpeg.so: cannot open shared object file: No such file or directory
Si vous avez une architecture 32 ou 64 bits :
Si votre architecture est 32 bits, tapez dans votre terminal console préférée,
cette commande avec les droits administrateur :
# ln -s /usr/lib/i386-linux-gnu/libturbojpeg.so.0 /usr/lib/i386-linux-gnu/libturbojpeg.so
Si votre architecture est 64 bits, tapez cette commande-ci, toujours avec
les droits administrateur :
# ln -s /usr/lib/x86_64-linux-gnu/libturbojpeg.so.0 /usr/lib/x86_64-linux-gnu/libturbojpeg.so
Lors de l’installation, au tout début, il vous est dit de décharger le module
nouveau. Si le système vous répond l’erreur suivante : modprobe:FATAL:Module nouveau in use
,
il est intéressant de le désactiver lors du démarrage du noyau.
Ne vous inquiétez pas trop de ce message d’erreur, mais plutôt paramétrez
le fichier de configuration de grub /etc/default/grub
afin de rajouter
les paramètres noyau suivants nouveau.modeset=0
et modprobe.blacklist=nouveau
dans la ligne de configuration relative à GRUB_CMDLINE_LINUX_DEFAULT
,
telle que, par exemple :
GRUB_CMDLINE_LINUX_DEFAULT="quiet nouveau.modeset=0 modprobe.blacklist=nouveau"
Mettez-à-jour votre grub… et redémarrez votre station.
Lorsque vous exécutez optirun, vous avez le retour d’erreur suivant :
$ primus: fatal: failed to load any of the libraries: /usr/lib/x86_64-linux-gnu/nvidia/libGL.so.1:/usr/lib/i386-linux-gnu/nvidia/libGL.so.1:/usr/lib/nvidia/libGL.so.1
/usr/lib/x86_64-linux-gnu/nvidia/libGL.so.1: cannot open shared object file: No such file or directory
/usr/lib/i386-linux-gnu/nvidia/libGL.so.1: cannot open shared object file: No such file or directory
/usr/lib/nvidia/libGL.so.1: cannot open shared object file: No such file or directory
ou :
$ primus: fatal: failed to load any of the libraries: /usr/lib/x86_64-linux-gnu/ nvidia/libGL.so.1:/usr/lib/i386-linux-gnu/nvidia/libGL.so.1:/usr/lib/nvidia/libGL.so.1
/usr/lib/x86_64-linux-gnu/nvidia/libGL.so.1: wrong ELF class: ELFCLASS64
/usr/lib/i386-linux-gnu/nvidia/libGL.so.1: cannot open shared object file: No such file or directory
/usr/lib/nvidia/libGL.so.1: cannot open shared object file: No such file or directory
$ primusrun glxgears
primusrun
._GLVND_DISALLOW_PATCHING=1
,
tel que : _GLVND_DISALLOW_PATCHING=1 primusrun glxgears
- (cf, la réponse 22)/usr/bin/primusrun
, pour modifier la ligne PRIMUS_libGL=${PRIMUS_libGL:-'/usr/$LIB/primus'}
par PRIMUS_libGL=${PRIMUS_libGL:-"/usr/$LIB/primus"}
-
c’est-à-dire changer les simples quotes en doubles quotes - (cf, la réponse 59)Il existe plusieurs raisons pour lesquelles le portable peut “freezer”, essayez les solutions proposées - en anglais :
Pour tester le fonctionnement :
$ cat /proc/acpi/bbswitch
0000:01:00.0 OFF
$ optirun glxgears > /dev/null &
[1] 4785
$ cat /proc/acpi/bbswitch
0000:01:00.0 ON
[VGL] ERROR: in readback--
[VGL] 246: Window has been deleted by window manager
[1]+ Termine 1 optirun glxgears > /dev/null
$ cat /proc/acpi/bbswitch
0000:01:00.0 OFF
Sous OpenBSD, il existe différents moyens de monter un disque dur USB, ou une clé USB…
À partir d’OpenBSD 6.0 et supérieures, il semble préférable de se
diriger vers l’usage du démon hotplugd
et du binaire ‘hotplug-diskmount’.
Il faut modifier l’option kern.usermount
.
# sysctl kern.usermount=1
Par sécurité, ce paramétrage retrouve sa valeur par défaut au redémarrage.
Malgré tout, si vous souhaitez qu’il soit pris en compte de façon
permanente, ajoutez ceci au fichier /etc/sysctl.conf
:
kern.usermount=1
Cette méthode est à recommander que si et seulement si les méthodes automatiques ci-dessus ne fonctionnent pas, ou si vous préférez vous en passer !
Tout d’abord, repérez le nom de votre clé USB avec la commande dmesg
juste après l’avoir insérée :
umass1 at uhub2 port 2 configuration 1 interface 0 "SanDisk Cruzer Edge" rev 2.00/1.27 addr 3
umass1: using SCSI over Bulk-Only scsibus5 at umass1: 2 targets, initiator 0
sd2 at scsibus5 targ 1 lun 0: <SanDisk, Cruzer Edge, 1.27> SCSI4 0/direct removable serial.0781556b42119B2141E2
sd2: 15267MB, 512 bytes/sector, 31266816 sectors
Ici, la clé est donc sd2
!
Ensuite, avec la commande disklabel, vous pouvez repérer les partitions contenues sur la clé :
$ disklabel sd2
# /dev/rsd2c:
type: SCSI
disk: SCSI disk
label: Cruzer Edge
duid: 0000000000000000
flags:
bytes/sector: 512
sectors/track: 63
tracks/cylinder: 255
sectors/cylinder: 16065
cylinders: 1946
total sectors: 31266816
boundstart: 0
boundend: 31266816
drivedata: 0
16 partitions:
# size offset fstype [fsize bsize cpg]
c: 31266816 0 unused
i: 31264768 2048 MSDOS
Enfin, il suffit de monter la clé dans un dossier qui vous appartient.
Ici, la partition intéressante est la i
. Par exemple pour la monter
dans le dossier ~/usb
qui se trouve dans votre répertoire :
# mount /dev/sd2i ~/usb
Il reste un problème à régler. Si vous jetez un oeil aux droits d’accès de votre clé :
$ ls -la /dev/sd2i
brw-r----- 1 root operator 4, 24 Apr 30 2016 10:29 /dev/sd2i
Vous remarquez que seul root et les membres du groupe operator
ont
les droits requis.
Ajout de votre utilisateur au groupe operator
:
# usermod -G operator toto
$ groupinfo operator
name operator
passwd *
gid 5
members root toto
Donner au groupe operator
les droits adéquats sur votre device, ici
/dev/sd2
:
# chmod g=rw /dev/sd2*
Pour démonter un périphérique cela se réalise avec la commande
umount
(8).
On peut soit démonter à partir du périphérique :
# umount /dev/sd2i
Soit à partir de son point de montage :
# umount ~/usb
Si jamais on obtient une erreur concernant l’utilisation du point de montage (occupé), il faut vérifier que les divers terminaux / logiciels n’utilisent plus le répertoire en question.
La commande fstat
(1) peut aider
pour voir rapidement quel logiciel y est attaché :
# umount ~/usb
umount: ~/usb: Device busy
# fstat -f ~/usb/
USER CMD PID FD MOUNT INUM MODE R/W SZ|DV
toto pcmanfm 21084 114 ~/usb 4 drwxr-xr-x r 32768
Dans l’exemple ci-dessus on peut voir que pcmanfm occupe le point de
montage ~/usb
, ayant pour PID 21084.
On peut alors soit changer de répertoire à partir de pcmanfm, soit le
fermer, voire le tuer avec la commande kill
(1).
C’est ce dernier cas qu’on va utiliser dans l’exemple suivant.
On va tuer le processus de pcmanfm, vérifier à nouveau avec fstat pour
savoir si le point de montage est bien libre, puis démonter le
périphérique avec umount
:
# kill 21084
# fstat -f ~/usb/
USER CMD PID FD MOUNT INUM MODE R/W SZ|DV
# umount –/usb
J’ai écrit historiquement cette documentation de manière collaborative sur le wiki de la communauté “OpenBSD Pour Tous”.