PROJET AUTOBLOG


Planet-Libre

source: Planet-Libre

⇐ retour index

Simon Vieille : Courier-imap vers Dovecot : "Renaming not supported across conflicting directory permissions"

samedi 12 janvier 2019 à 16:15

Il y a des années de ça, je me suis lancé dans l'aventure de l'hébergement à la maison avec notamment la gestion de mes mails. Dès le départ, je suis parti sur de la Debian GNU/Linux et j'ai installé les outils Postfix et Courier pour gérer les couches SMTP et IMAP.

Cette semaine, j'ai remplacé Courier par Dovecot qui est plus complet, plus simple à configurer et au cœur de beaucoup de documentations. J'avais également besoin d'intégrer Sieve pour gérer des règles de tri coté serveur.

Je ne détaillerai pas la procédure de migration car j'ai pioché dans pas mal d'articles. Globalement, tout s'est très bien passé et ça été transparent pour les quelques utilisateurs du serveur. Cependant, je me suis confronté à une erreur lorsque qu'ai voulu supprimer un dossier via mon client Thunderbird :

[CANNOT] Renaming not supported across conflicting directory permissions

Après quelques recherches, il s'avère que les répertoires Maildir des utilsateurs, générés avec la commande maildirmake ~/Maildir, ont un chmod 700 et que par défaut, lors de la création d'un répertoire, son chmod est 755. Dans la version 2.2.*, Dovecot vérifie que les chmod des dossiers correspondent pour valider la suppression et comme ce n'est pas le cas, cette erreur apparait.

Ainsi, quand un répertoire est créé dans l'arborescence de la boite mail, il ne peut plus être supprimé sans faire un chmod 700 ~/Maildir/.LeRepertoire. Pour résoudre le souci et faire en sorte que le chmod soit le bon, j'ai simplement joué avec les ACL. Pour chaque utilisateur hébergé, j'ai lancé cette commande :

$ setfacl -d --set u::rwx,g::-,o::- ~/Maildir/

Ainsi, lorsqu'un répertoire est créé dans ~/Maildir, son chmod est par défaut en 700 et je peux le supprimer via Dovecot au travers de mon client Thunderbird !

J'en ai également profité pour faire un wrapper sur le serveur :

#!/bin/sh

maildirmake.dovecot "$1"
setfacl -d --set u::rwx,g::-,o::- "$1"

Gravatar de Simon Vieille
Original post of Simon Vieille.Votez pour ce billet sur Planet Libre.

Articles similaires

blog-libre : openpyn, surcouche à OpenVPN pour NordVPN

samedi 12 janvier 2019 à 13:00

J’ai pris un abonnement NordVPN de 2 ans fin décembre 2017. Il me sert principalement à télécharger et parfois à changer/masquer mon adresse IP réelle pour un besoin ou un autre. J’utilise toujours le même petit script pour contrôler la connexion VPN. J’ai constaté quelques soucis dans mon utilisation.

Des défauts à corriger

Voici l’alias que j’utilisais avant dans ~/.bash_aliases (vous pouvez le mettre directement dans ~/.bashrc).

alias vpn='(sudo openvpn --config $(find /etc/openvpn/ovpn_udp -type f | shuf -n 1) --auth-user-pass ~/.config/nordvpn_auth >/dev/null 2>&1 &); while ! ip a show dev tun0 up >/dev/null 2>&1; do sleep 0.5; done && ~/Scripts/myip.sh'
--config $(find /etc/openvpn/ovpn_udp -type f | shuf -n 1) # Je prends un fichier de config au hasard dans le dossier /etc/openvpn/ovpn_udp
--auth-user-pass ~/.config/nordvpn_auth # J'indique mes identifiants NordVPN dans le fichier ~/.config/nordvpn_auth (chmod 600)
>/dev/null 2>&1 # Je redirige les flux de sortie standard et d'erreur vers /dev/null
while ! ip a show dev tun0 up >/dev/null 2>&1; do sleep 0.5; done # Tant que l'interface tun0 (VPN) n'est pas up, on boucle
&& ~/Scripts/myip.sh # Dès que l'interface tun0 est up (&&) on lance le script myip.sh

Évidemment cet alias est le résultat de choix personnels : 1/ Je lance un fichier de config au hasard (donc je me connecte à un serveur random chez NordVPN) afin d’avoir une IP différente à chaque fois. Dans les faits j’ai bien une IP différente mais je me retrouve souvent avec une bande passante en download minable, je dois donc relancer 3-4 fois le VPN pour arriver à une vitesse de téléchargement convenable 2/ Parfois la connexion VPN ne se faisait pas, j’utilisais alors pko (alias pko='sudo pkill openvpn') pour tuer le VPN puis je relancais vpn. Je n’ai jamais creusé pourquoi (flemme) et puis j’envoie les flux de sortie et d’erreur vers /dev/null 3/ J’aurais pu affiner mon find pour lancer uniquement des connexions VPN us ou uk par exemple (mais ça ne garantit en rien que la vitesse de téléchargement soit correcte)

Le DNS leak (fuite DNS) est un autre gros morceau/problème, OpenVPN laisse fuiter les requêtes DNS. Concrètement votre VPN est up, vous surfez et votre adresse IP est différente de celle de votre domicile. Tout va bien ! Sauf que pour les requêtes DNS, vous interrogez le serveur DNS de votre fournisseur internet. C’est mieux expliqué ici (en Anglais), le schéma suivant me semble explicite (ISP = Internet Service Provider = Fournisseur d’accès à Internet = FAI).

openpyn pour vous servir

Au bout d’un moment le souci 1/ a commencé à me gonfler et je me suis mis en recherche d’une solution (je pensais initialement jeter un œil aux infos proposées par l’API de NordVPN comme la latence). Je suis tombé sur openpyn un petit programme Python3 en GPLv3 qui propose pas mal de choses mais pour NordVPN :

Après un pip3 install openpyn (éventuellement précédé de apt install openvpn unzip wget python3-setuptools python3-pip), on lance un openpyn --init qui va vous demander les identifiants de connexion à NordVPN et votre pays par défaut (si j’ai bien compris pour le service systemd, moi je m’en sers pas donc je m’en fous). Maintenant il suffit juste de openpyn uk pour qu’il se connecte au « meilleur » serveur VPN du Royaume-Uni (United Kingdom) par exemple. Voici la sortie.

openpyn uk
According to NordVPN, Least Busy 10 Servers in UK With 'Load' Less Than 70 Which Support OPENVPN-UDP Are: [['uk464', 4], ['uk477', 4], ['uk862', 4], ['uk563', 5], ['uk569', 5], ['uk842', 5], ['uk859', 5], ['uk322', 6], ['uk441', 6], ['uk562', 6]]

Pinging Server uk464 min/avg/max/mdev = [12, 12, 12, 0] 

Pinging Server uk477 min/avg/max/mdev = [11, 11, 12, 0] 

Pinging Server uk862 min/avg/max/mdev = [11, 11, 11, 0] 

Pinging Server uk563 min/avg/max/mdev = [9, 10, 11, 0] 

Pinging Server uk569 min/avg/max/mdev = [10, 10, 10, 0] 

Pinging Server uk842 min/avg/max/mdev = [10, 11, 13, 1] 

Pinging Server uk859 min/avg/max/mdev = [10, 11, 11, 0] 

Pinging Server uk322 min/avg/max/mdev = [10, 10, 11, 0] 

Pinging Server uk441 min/avg/max/mdev = [10, 10, 11, 0] 

Pinging Server uk562 min/avg/max/mdev = [9, 10, 10, 0] 

Top 10 Servers with Best Ping Are: ['uk563', 'uk569', 'uk322', 'uk441', 'uk562', 'uk477', 'uk862', 'uk859', 'uk842', 'uk464']

Out of the Best Available Servers, Chose uk563

2019-01-12 10:34:26 [SUCCESS] CONNECTING TO SERVER uk563 ON PORT udp
2019-01-12 10:34:26 [SUCCESS] Your OS 'linux' has systemd-resolve running, using it to update DNS Resolver Entries

Les logs openpyn se trouvent dans /var/log/openpyn. Les identifiants de connexion sont stockés dans /usr/local/lib/python3.6/dist-packages/openpyn/credentials.

Quelques tests et vérifications plus tard

Je suis en fibre 100M, j’étais satisfait à partir de 50M une fois la connexion VPN effectuée et mesurée avec mon petit script. Maintenant avec openpyn je tourne régulièrement à 90M, certes le changement d’IP n’est plus d’actualité mais il me suffit de lancer openpyn avec un autre pays si besoin. Concernant le point 2/ (parfois la connexion VPN ne se faisait pas), résolu. Je pense que c’est lié au fait que openpyn relance automatiquement une connexion VPN en cas d’erreurs, il gère également une sorte de failover si la connexion VPN s’arrête il passe au « meilleur » serveur suivant.

Deux sites de référence pour « vérifier » les fuites DNS et les infos vues par les sites que l’on visite : IPLEAK et DNS leak. Je vous conseille de tester un « avant » openpyn et un « après » pour confirmer que ça fonctionne et comprendre ce qui change. openpyn fait le job, OpenVPN seul non.

Afin d’être plus précis sur le DNS leak d’OpenVPN, il est possible de fixer les fuites DNS mais je résumerais en disant que c’est compliqué sur Linux. L’option block-outside-dns existe mais « Block DNS servers on other network adapters to prevent DNS leaks. This option prevents any application from accessing TCP or UDP port 53 except one inside the tunnel. It uses Windows Filtering Platform (WFP) and works on Windows Vista or later. This option is considered unknown on non-Windows platforms and unsupported on Windows XP, resulting in fatal error ». Beaucoup de solutions sont proposées sur le net, certaines avec iptables, d’autres en modifiant le fichier de config .ovpn, des scripts, utiliser votre propre serveur DNS… bref un peu de boulot à prévoir pour trier les bonnes solutions (et ensuite celles qui sont simples à mettre en œuvre par rapport à nos cas d’utilisation).

Config actuelle et prochaine étape

Mon alias dorénavant est alias vpn='(openpyn uk >/dev/null 2>&1 &); while ! ip a show dev tun0 up >/dev/null 2>&1; do sleep 0.5; done && ~/Scripts/myip.sh'.

Dans la sphère privée (pas pro), je considère que le couple OpenVPN + openpyn + NordVPN est ce qu’il y a de mieux actuellement (pour des usages comme le téléchargement, d’autres problèmatiques comme l’anonymat strict trouveront une solution avec Tor). Je vous rappelle que WireGuard est l’OpenVPN killer (ce que je confirme même si il ne fait pas « autant » de choses) mais qu’il est toujours en Work in Progress. Il devrait être intégré au noyau probablement cette année.

Oh tiens NordVPN bosse sur le support de WireGuard, quelle bonne idée ;)

Tcho les filles !

Gravatar de blog-libre
Original post of blog-libre.Votez pour ce billet sur Planet Libre.

genma : Vorta, interface graphique à Borg

mercredi 9 janvier 2019 à 09:00

Présentation de Vorta

Vorta est une interface graphique / un client du logiciel de sauvegarde Borg pour les postes de travail sous macOS X et différentes distributions GNU/Linux. Le but est donc d'intégrer BorgBackup à votre environnement de bureau

Dit autrement, Vorta est à Borg ce que GRsync est à Rsync : une interface graphique complète pour lancer graphiquement une sauvegarde avec Borg.

Le prérequis à son usage et bien évidemment d'avoir compris comment Borg marchait, pour savoir quels champs remplir et le pourquoi de tel ou tel option dans cette interface graphique. Le présent billet n'est ni un tutoriel sur Borg, ni un tutoriel sur Vorta. Je me contente de faire un retour d'expérience sur Vorta.

Le projet est disponible sur Github : https://github.com/borgbase/vorta

Dans la documentation il est indiqué qu'un simple

pip3 install vorta


suffit à l'installer.

Sur mon Ubuntu 18.04, j'ai rencontré des erreurs et il semble que les prérequis à l'installation soit de faire :


pip3 install PyQt5
pip3 install keyring==12.0.0 --force-reinstall

C'est donc encore en beta, la peinture n'est pas fraîche...

Quelques astuces

Pour le lancer, il faut le faire via la commande

vorta --foreground

car sinon aucun interface graphique n'apparaît à l'écran.

Quelques tests que j'ai fait

Par défaut, Vorta ne marche pas sur un répertoire Borg existant pour lequel on n'a pas de phrase de passe (pas de chiffrement de la sauvegarde) : le chiffrement est donc obligatoire en utilisant Vorta.

La création d'un nouveau dépôt depuis l'interface et les sauvegardes dans ce dernier marchent.

J'ai fait une comparaison de l'espace pris pour une même sauvegarde (de /home) avec une commande Borg manuelle versus une sauvegarde faite avec Vorta et on arrive à la même taille. Ce qui est parfaitement logique car on aura alors les mêmes options... Vorta n'est donc bien qu'une interface graphique à Borg.

Quelques captures d'écran ?

Une version en français ?

Comme indiqué dans l'issue ici https://github.com/borgbase/vorta/issues/99, les administrateurs systèmes ont la nécessité de parler anglais et cela ne pose pas de soucis que l'interface du logiciel soit en anglais. Par contre un logiciel conçu comme étant une interface graphique à Borg pour un usage bureautique a pour cible un plus large publique non forcément anglophone.

Pour l'instant, l'interface graphique est en anglais avec des chaînes de caractères codées en dur, mais comme l'interface graphique est en QT, elle doit pouvoir facilement être internationalisée et internationalisable. Je me suis proposé pour faire la version française (traduction des chaînes de caractères), vu que c'est du logiciel libre.

Gravatar de genma
Original post of genma.Votez pour ce billet sur Planet Libre.

Miamondo : Un environnement de bureau tout en Python (1ère partie : le menu principal)

mardi 8 janvier 2019 à 19:46

Bonjour et bonne année 2019! Malgré toutes les incertitudes qui pèsent sur nos têtes, explosion de la bulle financière, écroulement de notre système économique, conflit nucléaire généralisé, emballement incontrôlable du climat, malgré toutes les horreurs auxquelles nous sommes confrontés quotidiennement, je pense en particulier à la destruction de la porte du ministère de Benjamin Griveaux... Lire la Suite →

Gravatar de Miamondo
Original post of Miamondo.Votez pour ce billet sur Planet Libre.

genma : Rsync Checker petit script Python sans prétention

lundi 7 janvier 2019 à 09:00

Après mon billet Borg Checker, petit script Python sans prétention, voici un autre billet d'un petit outil simple mais effiace, là encore en deux étapes.

Les besoins

Nous avons un Rsync qui se fait dans le sens "Machine distance" en source, "Machine locale" en cible, le tout à travers SSH, lancé avec sudo - pour avoir les droits root et donc aller où on veut et s'affranchir des problèmes de permission.

Nous aimerions valider que les commandes rsync exécutées sont valables /se sont bien déroulées / ne sont pas tombées en erreur. Sachant que nous avons un script shell global qui lance plusieurs scripts shells différents qui eux-même lancent plusieurs commandes Rsync au sein du même script.

SSH

Les connexions SSH se font depuis la machine Backup en tant que client du serveur SSH qui est sur la machine à sauvegarder.

La connexion se fait via une connexion par clef (la clef publique de la machine de sauvegarde, Backup, a été ajoutée sur la machine à sauvegarder.

Rsync avec Sudo à travers SSH

Pour pouvoir copier les fichiers en rsync avec sudo, sans avoir à saisir de mot de passe, il faut faire un sudo visudo ce qui va permettre d'éditer le fichier /etc/sudoers et d'autoriser le lancement de la commande sudo rsync sans avoir à saisir de mot de passe pour l'utilisateur désigné, ici Genma.

sudo visudo

On ajoute en bas de fichier la ligne

genma ALL= NOPASSWD:/usr/bin/rsync

Astuce pour enregister / quitter dans le cas où l'éditeur par défaut est VI :

:wq!

La sauvegarde via Rsync

Exemple de script lançant des commandes Rsync la nuit via une tâche Cron. On écrit des traces / des logs dans un fichier en local. Ce fichier de log permettra de valider l'exécution des commandes (cf section ultérieure dans le fichier).

#!/bin/bash

LOG=/Backup/Machine_distante_A/Sauvegarde_rsync_ssh_`date +%Y-%m-%d`.log

# Fonction qui permet d'écrire des logs dans le fichier de log
# Le texte en paramètre de la fonction sera écrit à la suite de la date et heure
Inlog()
{
echo `date +'%Y-%m-%d %H:%M:%S'`": $1" >> $LOG
}

# La variable "$?" contient le code de retour de la dernière opération.
# Ici c'est le code d'execution de la commande "rsync".
# "0" - la commande "rsync" s'executé correctement,
# Autre valeur en cas échéant, c'est que l'on a donc une erreur
check_rsync()
{
result_rsync=$(echo $?)
# La variable "result_rsync" recupere la valeur de "$?"
# Si "result_rsync" "0" alors il avait une erreur lors d'execution de la commande "rsync" et le script s'arrête
if [ "$result_rsync" == "0" ]; then
Inlog "$1 Rsync OK"
else
Inlog "$1 Rsync KO"
fi
}

Inlog "Début Rsync Machine_distante_A /var_www sur Serveur_Sauvegarde"
rsync -avz --rsync-path="sudo rsync" -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress --ignore-existing genma@IP_Machine_Distante:/var/www /Backup/Machine_distante_A/var/www/
# Pour appeler la fonction de check du retour de la commande Rsync
check_rsync "Rsync Machine_distante_A /var_www sur Serveur_Sauvegarde"
Inlog "Fin Rsync Machine_distante_A /var_www sur Serveur_Sauvegarde"

Inlog "Début Rsync Machine_distante_A /data/sql sur Serveur_Sauvegarde"
rsync -avz --rsync-path="sudo rsync" -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress --ignore-existing genma@IP_Machine_Distante:/Backup/mysql/ /Backup/Machine_distante_A/data/sql/
# Pour appeler la fonction de check du retour de la commande Rsync
check_rsync "Rsync Machine_distante_A /data/sql sur Serveur_Sauvegarde"
Inlog "Fin Rsync Machine_distante_A /data/sql sur Serveur_Sauvegarde"

Un peu de Python

Un peu comme on avait plusieurs commandes Borg lancées et qu'on vérifiait que chacune d'elles était correctes (cf Borg Checker, petit script Python sans prétention), on vérifiera que les différents scripts et les différentes commandes Rsync se sont déroulées sans soucis.

Le besoin est donc de savoir quelles sont les Rsync qui ont posés soucis pour ensuite traiter manuellement ces erreurs / cas particuliers.

Pour ce faire, la machine de sauvegarde lance un script Python (via une tâche cron à une heure bien postérieure à celles du déroulement des sauvegardes).

Dans ce script Python, on vérifie la présence du fichier de log à la date du jour : cela valide qu'au moins la commande Cron a bien lancé le script Shell contenant les commandes rsync. Le nom du fichier de log est standardisé (cf script Shell ci-dessus) et se trouve dns un dossier. Le fichier est récupéré via la dernière commande de rsync dans un dossier local du serveur.

Le fichier de log étant présent, on parcourt le fichier de logs à la recherche d'une ligne KO et on affiche la dite ligne si besoin. Cf le script Shell et sa fonction check_rsync() qui teste le retour de la commande rsync.

**Fichier Config.ini** : contient les chemins vers les fichiers de logs de chaque machine sauvegardée.

Un script de sauvegarde Shell contenant des commandes rsync génère un fichier de log par exécution, fichier de log ayant dans son nom la date du jour.

[FichiersLogsRsyncSsh]
Machine_distante_A = /Backup/Machine_distante_A/
Machine_distante_B = /Backup/Machine_distante_B/

**Fichier CheckRsyncSSH.py**

#!/usr/bin/python
# -*-coding:Utf-8 -*
import configparser
import sys
import os.path
import datetime

# Initialisation des chemins
# On a un fichier avec
# * en clef : la sauvegarde à valider
# * en valeur : le chemin dans lequel on vérifie la présence d'un fichier de log
config = configparser.ConfigParser()
config.optionxform = str
config.read('./Config.ini')
configRsync = config['FichiersLogsRsyncSsh']

# Code de la fonction
def fctFichierLogRsynsSSH():
print(" ")
print(--------------------------------------------")
print(" CHECK DES RSYNC QUOTIDIENS")
print(" via un check de présence des fichiers logs")
print("-------------------------------------------")

now = datetime.datetime.now().strftime('%Y-%m-%d')

# Vérification qu'on a bien un fichier de log à la date du jour
for key,value in config.items('FichiersLogsRsyncSsh'):
fichierAtrouver = key + "_" + now + ".log"
found = 0;
for fileName in os.listdir(value):
if (fichierAtrouver == fileName):
found = 1;
break;
if (found == 0):
print(key + ': statut ' + '\\x1b[6;31m' + 'KO' + '\\x1b[0m' + ' Fichier absent : ' + fichierAtrouver + "!!!")
if(found == 1):
print(key + ': statut ' + '\\x1b[6;32m' + 'OK' + '\\x1b[0m' ' Fichier trouvé : ' + fichierAtrouver);

# Vérification du contenu du fichier
chemin = value + fichierAtrouver
f = open(chemin,'r')
lignes = f.readlines()
f.close()
ligneKO = 0;
for ligne in lignes:
# est ce que la ligne contient un KO
# KO inscrit car le rsync a renvoyé une erreur (cf script Shell)
# si oui, la ligne est KO
if "KO" in ligne:
# On s'arrête au 1er KO, vu qu'on ira voir le fichier en détail du coup
ligneKO = 1;
break
if (ligneKO == 0):
print(key + ': statut ' + '\\x1b[6;32m' + 'OK' + '\\x1b[0m' + ' Tous les Rsync sont OK.')
if (ligneKO == 1):
print(key + ': statut ' + '\\x1b[6;31m' + 'KO' + '\\x1b[0m' ' Au moins un rsync contient un KO !!!')
print("La ligne concernée par un KO est : " +ligne)
ligneKO = 0;
found = 0;
print (" ")
return 0;

# Appel de la fonction principal
fctFichierLogRsynsSSH()

Pour le lancer le script :

python3 CheckRsyncSSH.py

Quel résultat ?

Si on lance le script manuellement, la sortie est donc sur la ligne de commande.

On aura donc un OK en vert ou un KO en rouge qui apparait dans le terminal ce qui permet de facilement distinguer / voir les lignes à analyser. Le Nom du fichier (et par conséquence de la sauvegarde) en échec apparaît. Il faut alors analyser ensuite plus finement en allant relancer le script global ou la commande rsync incriminée, en regardant les logs dans le terminal...

Gravatar de genma
Original post of genma.Votez pour ce billet sur Planet Libre.