Rediriger les mails locaux sur son adresse email

Il suffit d’avoir un serveur de courriel (serveur de mail) installé, avec la configuration par défaut, si ce n’est pas le cas, on l’installe.

sudo yum install postfix

Bien évidemment, on s’assure que le service est démarré et activé.

sudo systemctl start postfix
sudo systemctl enable postfix

Ou sur les distributions ne prenant pas en charge systemd (centos6 ou rhel6)

sudo service postfix start
sudo chkconfig postfix on

On modifie le fichier /etc/aliases pour rediriger les messages locaux vers son adresse de courriel. Exemple de redirection des messages locaux de l’utilisateur root vers l’adresse de courriel mon-user@mon-domain

root:         <mon-user>@<mon-domain>

On lance la reconstruction du cache des redirections

sudo newaliases

Il n’y a plus qu’à tester

echo 'Test depuis la ligne de commande' | \
mail -s 'test redirection' root

On devrait avoir un courriel avec le sujet test redirection

Et la sécurité dans tout ça ?

Par défaut, le service de mail se branche sur localhost et n’est pas accessible depuis l’extérieur. Donc aucun soucis.

Découverte de docker swarm

Pour découvrir le swarm (la nuée ou l’essaim) de docker, on va partir de notre poste Fedora, avec une installation de libvirt fonctionnelle.

Installation

On va créer deux nouvelles machines virtuelles que l’on nommera worker1 et worker2: 2 vCPUs et 4Go de RAM.

Sur l’hôte servant de manager, on initialise le swarm (aka le poste Fedora), en précisant l’adresse IP sur la patte libvirt

docker swarm init --advertise-addr 192.168.122.1
Swarm initialized: current node (2kdz664ro2rpjh5pn1743gsez) is now a manager.
    
To add a worker to this swarm, run the following command:

docker swarm join \
       --token SWMTKN-1-5od9m6ccyazf6uqnopqv6f1p2xqu4saiul7yvbqvjkw5ryczyz-8mjxk1qv26isjnzzyzpf02w5e \
       192.168.122.1:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

Sur les deux hôtes servant de workers: worker1 et worker2

  1. On installe la version la plus récente de docker
    yum install docker docker-latest
  2. On lance le daemon docker
    systemctl start docker
  3. On se joint au swarm en précisant le token fourni à l’initialisation du swarm sur le manager.
    docker swarm join --token SWMTKN-1-54yhh9qjmwcsxb4jhp7p6a0isc4in0vykqu3ir4y06aq6xtpbb-8mspc4bbxh32nx8obni897fvn 192.168.122.1:2377
    This node joined a swarm as a worker.

Le swarm est en place, il ne reste plus qu’à l’utiliser.

Visualiseur

Pour faciliter la vision des choses, on va mettre en place un visualiseur, qui sera encore un conteneur docker.

docker run -it -d \
-p 5000:8080 \
-v /var/run/docker.sock:/var/run/docker.sock \
--name swarm_visualizer \
dockersamples/visualizer

On accède maintenant au visualizer en allant sur l’url http://192.168.122.1:5000/

Gestion des services

Docker swarm gère des services qui seront associés en interne à un ou plusieurs conteneurs. Dans cette exemple (phpmyadmin), on va le découper en deux services:

  • la base de données
  • le serveur web avec le module php

On aurait pu découper en trois, en n’installant pas le module php avec le serveur web et utiliser un service php-fpm, mais cela aurait complexifié inutilement l’exemple.

Afin que nos conteneurs puisse se parler entre eux, on va créer un réseau dédié (overlay)

docker network create --driver overlay --subnet 172.255.0.0/24 swarmnet

On démarre le conteneur embarquant la base de données. Quelques remarques sur la commande à lancer:

  • On fixe la contrainte d’exécution sur le manager, car le conteneur a un volume attaché et docker n’a pas de solution de synchonisation des volumes en natif. En effet si le conteneur s’exécutait sur une autre hôte (worker), il aurait un nouveau volume vierge et on oublie la persistance des données. Toutefois, on pourrait fixer la contrainte d’exécution sur un worker particulier avec --constraint node.hostname=worker1 afin de toujours se servir du même volume de données.
  • On monte le volume docker s’appelant pma-db-data en lieu et place du répertoire de travail mariadb.
  • On fixe le nom de la base de données, les identifiants utilisateur et le mot de passe du superutilisateur (root) via des variables d’environnement.
  • On précise que le conteneur est accessible via son nom d’hôte (accès par rotation DNS) et comme on n’a qu’un seul conteneur base de données, on est sûr de tomber toujours sur le même). Sans ce paramètre (accès par vip) il aurait fallut brancher le port 3306 sur l’hôte exécutant docker (le poste Fedora) et de connecter le conteneur web à l’adresse IP de l’hôte.
  • Évidemment, on le branche sur notre réseau dédié
docker service create --name pma-db \
--constraint node.role==manager \
--mount type=volume,src=pma-db-data,dst=/var/lib/mysql \
-e DB_NAME=pmadb \
-e DB_USER=pma \
-e DB_PASS=pmapasswd \
-e DB_ROOT_PASS=rootpasswd \
--endpoint-mode dnsrr \
--network swarmnet \
docker.io/didier13150/mariadb

On démarre maintenant le second conteneur qui contient le serveur web (avec le module php) et phpmyadmin sur un des workers

  • On fixe la contrainte d’exécution sur un worker
  • On lui communique le nom d’hôte, le nom de la base de données, ainsi que les identifiants utilisateur via des variables d’environnement.
  • On connecte le port 80 du conteneur sur le port 8080 du manager, même si le(s) conteneur(s) s’exécute(nt) sur le(s) worker(s)
  • On le branche également sur notre réseau dédié (pour la résolution du nom d’hôte pma-db)
docker service create --name pma-web \
--constraint node.role==worker \
-e DB_NAME=pmadb \
-e DB_USER=pma \
-e DB_PASS=pmapasswd \
-e DB_HOST=pma-db \
-p 8080:80 \
--network swarmnet \
docker.io/didier13150/phpmyadmin

On accède maintenant à phpmyadmin en allant sur l’url http://192.168.122.1:8080/

Rien de bien compliqué jusqu’à présent.

Mais imaginons qu’un seul serveur web ne puisse tenir la charge et qu’il faudrait le cloner (même plusieurs fois) pour absorber la charge, disons 4 instances de ce serveur web serait pas mal. La magie de swarm, c’est que c’est faisable à chaud, quasiment instantanément et en une seule petite commande:

docker service scale pma-web=4

Et encore plus fort, imaginons que le pic de charge est passé et que les clones ne servent plus à rien, et bien on peut les supprimer:

docker service scale pma-web=1

Pour arrêter les services, on les supprime

docker service rm pma-web
docker service rm pma-db

On arrête aussi notre réseau

docker network rm swarmnet

Gestion des nœuds

Étudions maintenant la gestion des nœuds au sein de notre essaim

  • Lister les nœuds du swarm
    docker node ls
    ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
    2kdz664ro2rpjh5pn1743gsez * manager1 Ready Active Leader
    0xj7x2kxmjuvyqj19ekdubs99 worker1 Ready Active
    7xqkaxxbzi4260b6drujhis1q worker2 Ready Active
  • Supprimer un nœud
    docker node rm 7xqkaxxbzi4260b6drujhis1q

Un petit point sur les options SSL et les en-têtes HTTP

Apache Logo

Options générales

  • ServerTokens définit ce qu’apache peut diffuser comme information à propos de lui-même. Le fanfaronnage est incompatible avec la sécurité.
    • Prod: c’est la valeur la plus sécurisée et le serveur n’enverra que son nom:
      Server: Apache
    • Major: le serveur n’enverra que son nom et son numéro de version majeur:
      Server: Apache/2
    • Minor: le serveur n’enverra que son nom et son numéro de version complet:
      Server: Apache/2.4.25
    • Os: le serveur n’enverra que son nom, son numéro de version complet et le nom du système d’exploitation:
      Server: Apache/2.4.25 (Fedora)
    • Full: le serveur enverra son nom, son numéro de version, le nom du système d’exploitation et la liste des modules actifs avec leur numéro de version:
      Server: Apache/2.4.25 (Fedora) OpenSSL/1.0.2k-fips mod_auth_kerb/5.4 mod_wsgi/4.4.23 Python/2.7.13 PHP/7.0.18 mod_perl/2.0.10 Perl/v5.24.1
  • ServerSignature définit la signature (pied de page) apposée par apache sur les page générées par lui-même (typiquement les pages d’erreurs)
    • Off: aucune signature sur les page générées
    • On: signature présente avec les mêmes informations défini par la directive ServerTokens, le domaine et le port
      <address>Apache/2.4.25 (Fedora) OpenSSL/1.0.2k-fips mod_auth_kerb/5.4 mod_wsgi/4.4.23 Python/2.7.13 PHP/7.0.18 mod_perl/2.0.10 Perl/v5.24.1 Server at www.tartarefr.eu Port 80</address>
    • Email: signature présente avec les mêmes informations défini par la directive ServerTokens, le domaine, le port et l’email de l’administrateur du domaine
      <address>Apache/2.4.25 (Fedora) OpenSSL/1.0.2k-fips mod_auth_kerb/5.4 mod_wsgi/4.4.23 Python/2.7.13 PHP/7.0.18 mod_perl/2.0.10 Perl/v5.24.1 Server at <a href="mailto:fake@tartarefr.eu">www.tartarefr.eu</a> Port 80</address>
      
  • TraceEnable définit si la méthode HTTP Trace est autorisée. Cette méthode sert surtout pour des tests ou des diagnostiques et n’a pas sa place sur un serveur en production. Elle peut prendre deux valeurs: On (la méthode est permise) ou Off (méthode désactivée)

Options SSL

Hormis les directives habituelles (SSLEngine, SSLCertificateFile, SSLCertificateKeyFile, SSLCertificateChainFile) pour le paramétrage SSL, il y en a quelques unes qui méritent une petite explication.

  • SSLCipherSuite définit la liste des ciphers autorisés. Actuellement, pour obtenir un A+ sur SSLlabs, il faut désactiver certains ciphers medium ou high.
    HIGH:MEDIUM:!aNULL:!eNULL:!MD5:!RC4:!EXP:!3DES:!LOW:!SEED:!IDEA:!CBC
  • SSLHonorCipherOrder définit si l’ordre des ciphers de la directive SSLCipherSuite doit être suivi. Il est recommandé de suivre l’ordre défini en mettant la valeur On. Typiquement ici, le serveur essaiera d’abord tous les ciphers HIGH avant d’essayer les MEDIUM.
  • SSLProtocol définit les protocoles autorisés: ici on accepte tous les protocoles sauf SSL version 2 et version 3. On peut commencer à envisager d’exclure aussi TLSv1 (TLSv1.0)
    SSLProtocol all -SSLv2 -SSLv3
  • SSLCompression active ou désactive la compression sur SSL. Comme la faille CRIME exploite une faille de la compression, on désactive cette fonctionnalité en mettant le paramètre à off.

En-têtes HTTP concernant la sécurité

  • Set-Cookie permet de sécuriser les cookies en ajoutant deux paramètres qui rendent les cookies non accessibles aux scripts du client (HttpOnly) et ils ne sont transmis que sur une connexion sécurisée (Secure), c’est à dire en HTTPS.
    Header always edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
  • X-Frame-Options autorise le navigateur à encapsuler ou non la page web dans une frame. En empêchant la page d’être encapsulée par un site externe, on se protège du clickjacking.
    Il y a 3 valeurs possibles:

    • DENY: aucune encapsulation possible
    • SAMEORIGIN: encapsulation uniquement en provenance du même domaine et du même protocole (HTTP ou HTTPS)
    • ALLOW-FROM: encapsulation uniquement en provenance de l’URI passée en argument
  • X-XSS-Protection active les filtres cross-site scripting embarqués dans la plupart des navigateurs. La meilleure configuration est d’activer la protection des navigateurs: “X-XSS-Protection: 1; mode=block“.
  • X-Content-Type-Options désactive la détection automatique du type MIME par le navigateur et force celui-ci à utiliser uniquement le type déclaré avec Content-Type. La seule valeur valide est nosniff.
  • Referrer-Policy définit la politique d’envoi d’information de navigation dans l’en-tête Referer
    • no-referrer: L’en-tête sera absente de la réponse à la requête.
    • no-referrer-when-downgrade: L’en-tête sera absente s’il y a une diminution de la sécurité (HTTPS->HTTP). Sinon elle sera envoyée.
    • same-origin: L’en-tête sera présente que si le domaine de destination est identique à celui d’origine.
    • origin: L’en-tête sera présente mais ne comprendra que le domaine de la page d’origine.
    • strict-origin: L’en-tête sera absente s’il y a une diminution de la sécurité (HTTPS->HTTP). Sinon elle ne comprendra que le domaine de la page d’origine.
    • origin-when-cross-origin: L’en-tête sera présente et l’URI sera complète si le domaine de destination est identique à celui d’origine, mais ne comprendra que le domaine de la page d’origine si le domaine de destination diffère de celui d’origine.
    • strict-origin-when-cross-origin: L’en-tête sera absente s’il y a une diminution de la sécurité (HTTPS->HTTP). Sinon elle sera complète si le domaine de destination est identique à celui d’origine, mais ne comprendra que le domaine de la page d’origine si le domaine de destination diffère de celui d’origine.
    • unsafe-url: L’en-tête sera présente et l’URI sera complète
  • Content-Security-Policy regroupe les sources autorisées à être incluses dans la page web. En listant uniquement les sources nécessaires, on empêche le téléchargement de sources malicieuses par le navigateur. Le mot clé self représente le domaine appelé.
    • default-src : Définit les sources autorisées par défaut de tous les types de ressources
    • script-src : Définit les sources autorisées pour les scripts
    • object-src : Définit les sources autorisées pour les objets
    • style-src : Définit les sources autorisées pour les feuilles de styles
    • img-src : Définit les sources autorisées pour les images
    • media-src : Définit les sources autorisées pour les médias (vidéo et audio)
    • frame-src : Définit les sources autorisées pour les frames
    • font-src : Définit les sources autorisées pour les polices de caractères
    • connect-src : Définit les sources autorisées à être chargée par les scripts
    • form-action : Définit les sources autorisées pour l’action d’un formulaire
    • plugin-types : Définit les sources autorisées pour les plugins
    • script-nonce : Définit les sources autorisées pour les scripts ayant le même argument nonce
    • sandbox : Définit la politique de bac-à-sable
    • reflected-xss : Active ou désactive les filtres des navigateurs pour la protection XSS
    • report-uri : Définit une URI vers laquelle envoyer un rapport en cas de violation de politique
  • HTTP-Strict-Transport-Security force le navigateur à modifier tous les liens non sécurisés par des liens sécurisés (HTTP->HTTPS) durant le temps indiqué par le paramètre max-age. Celui-ci doit donc être configuré pour être supérieur à la durée de navigation. La page ne sera pas affichée si le certificat SSL n’est pas valide.
  • Public-Key-Pins protège contre les attaques man-in-the-middle avec des certificats X.509 volés (mais valides). En spécifiant l’empreinte des certificats du site au navigateur, celui-ci ne fera pas
    confiance aux autres certificats valides non listés pour le site.
  • Expect-CT annonce le statut du site en rapport aux futurs pré-requis de Chrome. L’en-tête comporte le mot enforce s’il est prêt. Mais dans un premier temps il vaut mieux le mettre en test avec la directive max-age=0 et éventuellement le paramètre report-uri

Vérification

Exemple de configuration Apache

On peut mettre la définition de ces en-têtes dans le fichier /etc/httpd/conf.d/common.conf (On le créé s’il n’existe pas), il sera inclut par la directive IncludeOptional conf.d/*.conf

ServerTokens    Prod
ServerSignature Off

# Disable Trace
# Otherwise host is vulnerable to XST
TraceEnable Off

# Secure cookie with HttpOnly
Header always edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure

Header always set X-Frame-Options SAMEORIGIN
Header always set X-XSS-Protection: "1;mode=block"
Header always set X-Content-Type-Options nosniff
Header always set Referrer-Policy same-origin
Header always set Content-Security-Policy "default-src 'self' ; script-src 'self' report.tartarefr.eu https://s.w.org ; style-src 'self' fonts.googleapis.com fonts.gstatic.com ; report-uri https://report.tartarefr.eu/"
Header always set Strict-Transport-Security "max-age=31536000;includeSubDomains"
Header always set Expect-CT 'max-age=0; report-uri="https://report.tartarefr.eu/"'
Header always set Public-Key-Pins 'pin-sha256="YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg=";pin-sha256="1B/6/luv+TW+JQWmX4Qb8mcm4uFrNUwgNzmiCcDDpyY=";max-age=2592000;includeSubdomains; report-uri="https://report.tartarefr.eu/"'

Remplacement de sectool par openscap-content-sectool

Security Audit Icon
L’outil d’audit de sécurité sectool n’étant plus mis à jour, il ne sera plus disponible à partir de Fedora 25. Il est temps de changer d’outil. Une implémentation des tests a été faite dans un plugin open-scap et la migration est triviale.

dnf install openscap-content-sectool

Il ne reste plus qu’à lancer l’outil

/usr/bin/oscap xccdf eval --profile Server --results-arf sectool-arf.xml --report sectool.html /usr/share/openscap/sectool-sce/sectool-xccdf.xml

et de visualiser le fichier sectool.html dans un navigateur.

Certificats SSL avec letsencrypt

 

HTTPS Logo L’avantage avec letsencrypt, c’est que le seul pré-requis est d’être propriétaire du domaine (ou du sous domaine). Le nom DNS doit correspondre à l’hôte qui a lancé le processus de certification.

dnf install letsencrypt

On fait notre demande de certificat

letsencrypt --text --email admin@example.com --domains www.example.com,example.com,apache.example.com --agree-tos --webroot --webroot-path /var/www/html certonly

Il ne reste plus qu’à déclarer notre clé privée et notre certificat dans le fichier de configuration d’Apache: /etc/httpd/conf.d/ssl.conf

SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem

Maintenant il nous faut encore mettre en place le renouvellement automatique, cr ce certificat n’est valable que 90 jours (et des discussions sont en cours pour abaisser cette période).
On va se servir des timers de systemd:

  • /etc/systemd/system/letsencrypt-renewal.service
    [Unit]
    Description=Automatically renew the letsencrypt certificate
    
    [Service]
    Type=oneshot
    ExecStart=/usr/bin/letsencrypt renew --agree-tos --email admin@example.com --renew-by-default
    ExecStart=/usr/bin/systemctl reload httpd
  • /etc/systemd/system/letsencrypt-renewal.timer
    [Unit]
    Description=Trigger an automatic renewal every month
    
    [Timer]
    OnCalendar=monthly
    Persistent=true
    
    [Install]
    WantedBy=multi-user.target

On recharge systemd

systemctl daemon-reload

on active le timer

systemctl enable letsencrypt-renewal.timer

on le démarre

systemctl start letsencrypt-renewal.timer

et le tour est joué

Attention la modification de la configuration apache n’est valable que pour apache > 2.4.8
Pour les versions antérieures, il faut utiliser

SSLCertificateFile /etc/letsencrypt/live/www.example.com/cert.pem 
SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/www.example.com/chain.pem

 

Logguer l’IP/hôte distant quand on utilise mod_proxy

Par défaut, en passant par un proxy http, Apache loggue l’adresse IP du proxy et non celle à l’origine de la connexion dans les fichiers access.
Pour résoudre ce problème, on va utiliser le module apache mod_remoteip.
On active ce module en créant le fichier /etc/httpd/conf.modules.d/00-remoteip.conf

LoadModule remoteip_module modules/mod_remoteip.so

et on le configure dans le fichier /etc/httpd/conf.d/remoteip.conf

<IfModule mod_remoteip.c>
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 127.0.0.1
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
</IfModule>

On redémarre Apache et le tour est joué

systemctl restart httpd

On ne peut pas déclarer notre proxy de manière générique avec la directive

RemoteIPProxiesHeader X-Forwarded-By

car notre proxy fait partie d’un block IP privé: dixit la page de documentation officielle du module

Tous les blocs d’adresses internes 10/8, 172.16/12, 192.168/16, 169.254/16 and 127/8 (ainsi que les adresses IPv6 en dehors du bloc public 2000::/3 block) ne sont évaluées par mod_remoteip que lorsque des mandataires internes (intranet) RemoteIPInternalProxy sont enregistrés.

Partage NFS

Pour partager facilement des dossiers entre plusieurs ordinateurs *nix, on peut se servir de NFS. Il est vraiment très triviale à mettre en place

yum install nfs-utils

d’exporter les dossiers dans le fichier /etc/exports

/data/save 192.168.0.x(rw,sync,no_root_squash)

et de démarrer le server NFS

systemctl start nfs-server
systemctl enable nfs-server

Mais c’est surtout la partie configuration du firewall qui n’est pas précisement détaillée.
Celle-ci est grandement simplifiée avec firewalld car elle se résume à

firewall-cmd --permanent --add-service mountd
firewall-cmd --permanent --add-service rpc-bind
firewall-cmd --permanent --add-service nfs
firewall-cmd --reload

On peut maintenant lister les services autorisés par le firewall

firewall-cmd --list-all
FedoraServer (default, active)
interfaces: eth0
sources:
services: mountd nfs rpc-bind ssh
ports:
protocols:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:

Cette simplicité est rendue possible grâce aux fichiers situés dans /usr/lib/firewalld/services/:

  • Fichier nfs.xml
    <?xml version="1.0" encoding="utf-8"?>
    <service>
    <short>NFS4</short>
    <description>The NFS4 protocol is used to share files via TCP networking. You will need to have the NFS tools installed and properly configure your NFS server for this option to be useful.</description>
    <port protocol="tcp" port="2049"/>
    </service>
  • Fichier mountd.xml
    <?xml version="1.0" encoding="utf-8"?>
    <service>
    <short>mountd</short>
    <description>NFS Mount Lock Daemon</description>
    <port protocol="tcp" port="20048"/>
    <port protocol="udp" port="20048"/>
    </service>
  • Fichier rpc-bind.xml
    <?xml version="1.0" encoding="utf-8"?>
    <service>
    <short>rpc-bind</short>
    <description>Remote Procedure Call Bind</description>
    <port protocol="tcp" port="111"/>
    <port protocol="udp" port="111"/>
    </service>

Cross Compilation – cmake

Sources

On va cette fois se servir de deux fichiers sources, d’un fichier en-tête et d’un fichier cmake pour construire notre binaire cppdata:

  • Le fichier main.cpp
  • Le fichier data.cpp, qui est l’implémentation de la class Data
  • Le fichier en-tête data.hpp qui déclare notre class Data

Le fichier main.cpp

#include <iostream>
#include "data.hpp"

using namespace std;

int main()
{
Data data;
data.set( 99 );
cout << "data: " << data.get() << endl;
return 0;
}

Le fichier data.hpp

#ifndef _DATA_HPP_
#define _DATA_HPP_

#include

class Data
{
public:
Data();
~Data();
void set( int number );
int get() const;

protected:
int _number;
};

int get();

#endif //_DATA_HPP_

Le fichier data.cpp

#include "data.hpp"
Data::Data() :
_number( 0 )
{
}
Data::~Data()
{
}

void Data::set( int number )
{
_number = number;
}

int Data::get() const
{
return _number;
}

Le fichier CMakeLists.txt

cmake_minimum_required(VERSION 2.6)
project(testdata)
add_executable(cppdata main.cpp data.cpp)

La chaine de construction

Afin de se simplifier la tâche, on va écrire un fichier buildchain pour chaque architecture. Ces fichiers, utilisables uniquement par cmake, nous permettront de nous affranchir de longues ligne de définition cmake.

Le buildchain windows 32bits

set(CMAKE_SYSTEM_NAME Windows)

set( WIN_BUILD_ARCH "i686" )
set( WIN_ARCH_BITS "32" )
set( WIN_ARCH "x86" )
set(COMPILER_PREFIX "${WIN_BUILD_ARCH}-w64-mingw32")

# Which compilers to use for C and C++
set(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
set(CMAKE_RC_COMPILER ${COMPILER_PREFIX}-windres)

# Here is the target environment located
set(CMAKE_FIND_ROOT_PATH /usr/${COMPILER_PREFIX} /usr/${COMPILER_PREFIX}/sys-root/mingw)

# Adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Le buildchain windows 64 bits

set(CMAKE_SYSTEM_NAME Windows)

set( WIN_BUILD_ARCH "x86_64" )
set( WIN_ARCH_BITS "64" )
set( WIN_ARCH "x64" )
set(COMPILER_PREFIX "${WIN_BUILD_ARCH}-w64-mingw32")

# Which compilers to use for C and C++
set(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
set(CMAKE_RC_COMPILER ${COMPILER_PREFIX}-windres)

# Here is the target environment located
set(CMAKE_FIND_ROOT_PATH /usr/${COMPILER_PREFIX} /usr/${COMPILER_PREFIX}/sys-root/mingw)

# Adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Construction

Comme habituellement avec cmake, on créé un répertoire dédié à la construction.

Linux

mkdir linux
cd linux
cmake ..
make

Wind@uze

Version 32 bits

mkdir win32
cmake -D CMAKE_TOOLCHAIN_FILE=../win32.cmake ..
make

Version 64 bits

mkdir win64
cmake -D CMAKE_TOOLCHAIN_FILE=../win64.cmake ..
make

Cross Compilation – Premiers pas

Pour générer un exécutable windows depuis linux, il faut recourir à ce qu’on appelle la cross-compilation: compiler sur un système pour un autre système.
On va partir d’un simple “Hello world”. A ce propos, j’ai découvert une collection d’hello world sur Github.

Sources

Le fichier source en C sera main.c

#include<stdio.h>
int main()
{
  printf("Hello World !\n");
  return 0;
}

Le fichier source en C++ sera main.cpp

#include <iostream>
using namespace std;
int main()
{
  cout << "Hello World !" << endl;
  return 0;
}

Compilation

GNU/Linux

Pour GNU/Linux, le fichier C serait compilé avec la commande

gcc -O0 -Wall -g -o helloc main.c

et le fichier C++

g++ -O0 -Wall -g -o hellocpp main.cpp

Wind@uze

On va se servir des compilateurs mingw

dnf install mingw32-gcc mingw32-gcc-c++ mingw32-binutils mingw64-gcc mingw64-gcc-c++ mingw64-binutils

Version 32 bits

le fichier C sera compilé avec la commande

i686-w64-mingw32-gcc -O0 -Wall -g -o helloc32.exe main.c

et le fichier C++

i686-w64-mingw32-g++ -O0 -Wall -g -o hellocpp32.exe main.cpp

En testant le binaire généré à partir du C++ avec wine, on se rend compte qu’il ne fonctionne pas (absence de DLLs).

err:module:import_dll Library libstdc++-6.dll (which is needed by L"V:\\hello32.exe") not found

Pour résoudre ce problème, il va falloir copié quelques DLLs dans le même répertoire que l’exécutable

cp /usr/i686-w64-mingw32/sys-root/mingw/bin/libstdc++-6.dll .
cp /usr/i686-w64-mingw32/sys-root/mingw/bin/libgcc_s_sjlj-1.dll .
cp /usr/i686-w64-mingw32/sys-root/mingw/bin/libwinpthread-1.dll .

Version 64 bits

le fichier C sera compilé avec la commande

x86_64-w64-mingw32-gcc -O0 -Wall -g -o helloc64.exe main.c

et le fichier C++

x86_64-w64-mingw32-g++ -O0 -Wall -g -o hellocpp64.exe main.cpp

Pour résoudre le même problème que la version 32 bits, il va falloir copié quelques DLLs dans le même répertoire que l’exécutable.

cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/libstdc++-6.dll .
cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgcc_s_seh-1.dll .
cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/libwinpthread-1.dll .

Serveur SFTP

Tutorial de mise en place d’un service de transfert de fichier sécurisé (SFTP) avec possibilité de téléversement.

Pour donner un accès en téléversement à un tiers, la solution la plus logique serait d'utiliser ssh et de limiter ce tiers au serveur sFTP. Bien que ce ne soit obligatoire, celui-ci serait emprisonné dans son répertoire utilisateur (chroot)

Création du groupe et des utilisateurs

Création du groupe sftponly qui limiterait les utilisateurs à l'utilisation de sFTP (accès SSH interdit)

groupadd sftponly

Création d'un utilisateur dont l'accès serait uniquement via sFTP (pas d'ouverture de session possible, en local ou distant) et affectation d'un mot de passe.

useradd -m -s /bin/false -c 'sFTP User Only' sftptest
usermod -aG sftponly  sftptest
passwd sftptest

Modification de la configuration du démon SSH

Dans le fichier /etc/ssh/sshd_config Modifier le programme gérant le sFTP afin d'utiliser le wrapper interne à ssh pour lancer le programme sFTP. En effet le binaire ne sera pas accessible depuis le chroot.

Subsystem       sftp    internal-sftp

Ajouter à la fin du fichier, la configuration des utilisateurs ayant pour groupe sftponly afin de les emprisonner dans leur répertoire personnel et de leur permettre l'accès uniquement au service sFTP.

Match Group sftponly
   ChrootDirectory %h
   ForceCommand internal-sftp
   X11Forwarding no
   AllowTcpForwarding no

Le démon SSH (sshd) doit être rafraichi

service sshd reload

Ajuster les droits des répertoires utilisateurs créés

Le répertoire personnel des utilisateurs sFTP doit avoir pour propriétaire et groupe root et pour permission 755 (root:root rwxr-xr-x). Afin de pouvoir téléverser, il faut créer un répertoire ayant pour propriétaire l'utilisateur (sftptest ici). en effet l'utilisateur ne pourra pas téléverser à sa racine (son répertoire utilisateur).

chown root:sftponly /home/sftptest
chmod 755 /home/sftptest
mkdir /home/sftptest/upload
chown sftptest: sftponly /home/sftptest/upload
chmod 755 /home/sftptest/upload

SELinux

Par défaut, pour SELinux, le chroot sFTP est en lecture seule. Afin d'autoriser le téléversement, il faut qu'il soit en lecture/écriture. SELInux dispose d'un booléen pour ça.

setsebool -P ssh_chroot_rw_homedirs on

Test

Afin de ne pas perturber le démon SSH en cours d'utilisation, on peut lancer une seconde instance (sur un port différent) en mode debug

/usr/sbin/sshd -p 2222 -d

Depuis un autre poste, on test la connexion ssh (qui ne doit pas fonctionner) et le téléversement d'un fichier à la racine (qui doit rapporter une erreur) et dans le répertoire upload (seul ce dernier doit fonctionner).

ssh -p 2222 sftptest@monserver
sftptest@monserver's password:
This service allows sftp connections only.
Connection to monserver closed.
sftp -p 2222 sftptest@monserver
sftptest@monserver's password:
Connected to monserver.
sftp> ls
upload
sftp> put test.txt
Uploading test.txt to /test.txt
remote open("/test.txt"): Permission denied
sftp> cd upload
sftp> put test.txt
Uploading test.txt to /upload/test.txt
test.txt                    100%    5     0.0KB/s   00:00
sftp> exit
source: https://wiki.tartarefr.eu/index.php/Services/FTP/SFTP