1 Configuration prosody
kitoy edited this page 2022-08-13 04:02:33 +02:00

Voici un exemple de configuration du serveur prosody avec pywallter

Configuration de prosody

Vous avez préalablement :

  • Configuré correctement votre zone DNS
  • Générer votre certificat ssl

On edite en premier le fichier /etc/prosody/prosody.cfg.lua

admins = { "admin@mondomaine.net" }

-- Drop privileges
prosody_user = "_prosody"
prosody_group = "_prosody"

-- Enable POSIX-only options
pidfile = "/var/prosody/prosody.pid"

plugin_paths = { "/var/prosody/plugins" }

modules_enabled = {

    -- Generally required
            "roster"; -- Allow users to have a roster. Recommended ;)
            "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
            "tls"; -- Add support for secure TLS on c2s/s2s connections
            "dialback"; -- s2s dialback support
            "disco"; -- Service discovery

    -- Not essential, but recommended
            "carbons"; -- Keep multiple clients in sync
            "pep"; -- Enables users to publish their avatar, mood, activity, playing music and more
            "bidi";
            "private"; -- Private XML storage (for room bookmarks, etc.)
            "blocklist"; -- Allow users to block communications with other users
            "vcard4"; -- User profiles (stored in PEP)
            --"vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard
            "limits"; -- Enable bandwidth limiting for XMPP connections
            "smacks";
    -- Nice to have
            "version"; -- Replies to server version requests
            "uptime"; -- Report how long server has been running
            "time"; -- Let others know the time here on this server
            "ping"; -- Replies to XMPP pings with pongs
            "register"; -- Allow users to register on this server using a client and change passwords
            "mam"; -- Store messages in an archive and allow users to access it
            "csi_simple"; -- Simple Mobile optimizations

    -- HTTP modules
            "bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
            "websocket"; -- XMPP over WebSockets
            "http_files"; -- Serve static files from a directory over HTTP
    -- Other specific functionality
            "groups"; -- Shared roster support
            -- "proxy65"; -- Enables a file transfer proxy service which clients behind NAT can use
}

allow_registration = false

-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.

c2s_require_encryption = true

-- Force servers to use encrypted connections? This option will
-- prevent servers from authenticating unless they are using encryption.

s2s_require_encryption = true

-- Enable rate limits for incoming client and server connections

limits = {
  c2s = {
    rate = "10kb/s";
  };
  s2sin = {
    rate = "30kb/s";
  };
}

-- Select the authentication backend to use. The 'internal' providers
-- use Prosody's configured data storage to store the authentication data.                                                                                                                             
                                                                                                                                                                                                   
authentication = "internal_hashed"    

archive_expires_after = "1w" -- Remove archived messages after 1 week

log = {                                                                                                                                                                                                
    info = "/var/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging                                         
    error = "/var/prosody/prosody.err";
    -- "*syslog"; -- Uncomment this for logging to syslog 
    -- "*console"; -- Log to the console, useful for debugging with daemonize=false                                                   } 
    

certificates = "/var/prosody/"

- WebSocket configuration (mod_websocket)
consider_websocket_secure = true
cross_domain_websocket = true


------ Components ------
-- You can specify components to add hosts that provide special services,
-- like multi-user conferences, and transports.
include "virtualHosts/*.conf"

Puis ensuite on créé le dossier virtualHosts :

# mkdir /etc/prosody/virtualHosts

Et on édite le fichier correspondant à notre domaine (mondomaine.net dans cet exemple) donc le fichier virtualHosts/mondomaine.net.conf :

VirtualHost "mondomaine.net"
  enable = true


  ssl = {
        key = "/etc/prosody/certs/mondomaine.net.key";
        certificate = "/etc/prosody/certs/mondomaine.net.crt";
        -- Configuration Avancé
        protocol = "tlsv1_2+";
        dhparam = "/etc/prosody/certs/dh-2048.pem";
        ciphers = "HIGH+kEECDH:!RSA:!SRP:!PSK:!3DES:!aNULL";
        options = { cipher_server_preference = true, no_compression = true, cipher_server_preference = true };

}

archive_expires_after = "15d";

  -- Discovery items
  disco_items = {
  { "muc.mondomaine.net" },
  { "pubsub.mondomaine.net" },
  { "jabber.mondomaine.net" },
  { "upload.mondomaine.net" },
  };

--  contact_info = {
--    abuse = { "mailto:abuse@mondomaine.net", "xmpp:admin@mondomaine.net" };
--    admin = { "mailto:root@mondomaine.net", "xmpp:admin@mondomaine.net" };
--  };

-- BOSH configuration (mod_bosh)
consider_bosh_secure = true
cross_domain_bosh = true

bosh_ports = {
                 {
                    port = 5280;
                    path = "http-bind";
                 },
                 {
                    port = 5281;
                    path = "http-bind";
                    ssl = {
                            certificate = "/etc/ssl/mondomaine.net.crt";
                            key = "/etc/ssl/private/mondomaine.net.key";
                          }
                 }
             }
 
    http_ports = { 5280 }
    http_interfaces = { "localhost" }

    https_ports = { 5281 }
    https_interfaces = { "localhost" }

    https_ssl = {
        certificate = "/etc/prosody/certs/mondomaine.net.crt";
        key = "/etc/prosody/certs/mondomaine.net.key";
    }


Component "muc.mondomain.net" "muc"
   name = "mondomaine.net Chatrooms"

  modules_enabled = {
     "muc_limits";
     "muc_log";
     "muc_log_mam";
     "muc_log_http";
     "muc_vcard";
  }

  muc_event_rate = 0.5
  muc_burst_factor = 10
  room_default_config = {
     logging = true,
    persistent = true
};


---Set up a PubSub server
Component "pubsub.mondomaine.net" "pubsub"
  name = "mondomaine.net Publish/Subscribe"
  unrestricted_node_creation = true -- Anyone can create a PubSub node (from any server)

---Set up a HTTP Upload service
Component "upload.mondomaine.net" "http_upload_external"
  name = "mondomaine.net Sharing Service"
  http_upload_external_base_url = "https://upload.mondomaine.net/share.php/"
  http_upload_external_secret = "Mettre une phrase de passe ici"

Configuration Nginx pour l'envoie d'images:

server {
    listen 80;
    listen [::]:80;
    server_name upload.mondomaine.net;

    #include snippets/acme-challenge.conf;

    return 301 https://$http_host$request_uri;

    access_log /var/log/nginx/upload.mondomaine.net-access.log;
    error_log /var/log/nginx/upload.mondomaine.net-error.log;
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name upload.mondomaine.net;

  ssl_certificate /etc/ssl/upload.mondomaine.net.crt;
  ssl_certificate_key /etc/ssl/private/upload.mondomaine.net.key;
  root /htdocs/;

  include snippets/secure-ssl.conf;

  include snippets/secure-headers.conf;
  #custom headers
  add_header 'Access-Control-Allow-Origin' '*';
  add_header 'Access-Control-Allow-Methods' 'HEAD, GET, PUT, OPTIONS';
  add_header 'Access-Control-Allow-Headers' 'Authorization';
  add_header 'Access-Control-Allow-Credentials' 'true';
  add_header x-robots-tag "noindex, follow";
  client_max_body_size 105M; # Choose a value a bit higher than the max upload configured in XMPP server


#add_header Strict-Transport-Security " max-age=63072000; includeSubDomains; preload";


  include snippets/acme-challenge.conf;
  location ~ share.php(?:$|/) {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        set $path_info $fastcgi_path_info;

        try_files $fastcgi_script_name =404;

        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $path_info;
        fastcgi_param HTTPS on;

        fastcgi_param modHeadersAvailable true;         # Avoid sending the security headers twice
        fastcgi_param front_controller_active true;     # Enable pretty urls
        fastcgi_pass php-handler;

        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    access_log /var/log/upload.mondomaine.net-access.log;
    error_log /var/log/upload.mondomaine.net-error.log;
}

Puis dans notre dossier /htdocs nous mettrons nous éditerons notre fichier share.php :

<?php

/*
  PHP script to handle file uploads and downloads for Prosody's mod_http_upload_external

  Tested with Apache 2.2+ and PHP 5.3+

  ** Why this script?

  This script only allows uploads that have been authorized by mod_http_upload_external. It
  attempts to make the upload/download as safe as possible, considering that there are *many*
  security concerns involved with allowing arbitrary file upload/download on a web server.

  With that said, I do not consider myself a PHP developer, and at the time of writing, this
  code has had no external review. Use it at your own risk. I make no claims that this code
  is secure.

  ** How to use?

  Drop this file somewhere it will be served by your web server. Edit the config options below.

  In Prosody set:

    http_upload_external_base_url = "https://your.example.com/path/to/share.php/"
    http_upload_external_secret = "this is your secret string"

  ** License

  (C) 2016 Matthew Wild <mwild1@gmail.com>

  Permission is hereby granted, free of charge, to any person obtaining a copy of this software
  and associated documentation files (the "Software"), to deal in the Software without restriction,
  including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:

  The above copyright notice and this permission notice shall be included in all copies or substantial
  portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
  BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

    */

    /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/
    /*         CONFIGURATION OPTIONS                   */
    /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/
/* Change this to a directory that is writable by your web server, but is outside your web root */
$CONFIG_STORE_DIR = '/xmpp-upload/mondomaine.net/upload';
/* On met la même passephrase quand dans le fichier de conf de prosody */
$CONFIG_SECRET = "Mettre une phrase de passe ici"
/* For people who need options to tweak that they don't understand... here you are */
$CONFIG_CHUNK_SIZE = 4096;

/*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/
/*         END OF CONFIGURATION                    */
/*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/

/* Do not edit below this line unless you know what you are doing (spoiler: nobody does) */

$upload_file_name = substr($_SERVER['PHP_SELF'], strlen($_SERVER['SCRIPT_NAME'])+1);
$store_file_name = $CONFIG_STORE_DIR . '/store-' . hash('sha256', $upload_file_name);

$request_method = $_SERVER['REQUEST_METHOD'];

/* Set CORS headers */
header('Access-Control-Allow-Methods: GET, PUT, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
header('Access-Control-Max-Age: 7200');
header('Access-Control-Allow-Origin: *');

if(array_key_exists('v', $_GET) === TRUE && $request_method === 'PUT') {
        $upload_file_size = $_SERVER['CONTENT_LENGTH'];
        $upload_token = $_GET['v'];

        $calculated_token = hash_hmac('sha256', "$upload_file_name $upload_file_size", $CONFIG_SECRET);
        if(function_exists('hash_equals')) {
                if(hash_equals($calculated_token, $upload_token) !== TRUE) {
                        error_log("Token mismatch: calculated $calculated_token got $upload_token");
                        header('HTTP/1.0 403 Forbidden');
                        exit;
                }
        }
        else {
                if($upload_token !== $calculated_token) {
                        error_log("Token mismatch: calculated $calculated_token got $upload_token");
                        header('HTTP/1.0 403 Forbidden');
                        exit;
              }
        }
        /* Open a file for writing */
        $store_file = fopen($store_file_name, 'x');

        if($store_file === FALSE) {
                header('HTTP/1.0 409 Conflict');
                exit;
        }

        /* PUT data comes in on the stdin stream */
        $incoming_data = fopen('php://input', 'r');
      
        /* Read the data a chunk at a time and write to the file */
        while ($data = fread($incoming_data, $CONFIG_CHUNK_SIZE)) {
                fwrite($store_file, $data);
        }

        /* Close the streams */
        fclose($incoming_data);
        fclose($store_file);

        // https://xmpp.org/extensions/xep-0363.html#upload
        // A HTTP status Code of 201 means that the server is now ready to serve the file via the provided GET URL.
        header('HTTP/1.0 201 Created');
        exit;
        } 
        else if($request_method === 'GET' || $request_method === 'HEAD') {
        // Send file (using X-Sendfile would be nice here...)
        if(file_exists($store_file_name)) {
                header('Content-Disposition: attachment');
                header('Content-Type: application/octet-stream');
                header('Content-Length: '.filesize($store_file_name));
                header("Content-Security-Policy: \"default-src 'none'\"");
                header("X-Content-Security-Policy: \"default-src 'none'\"");
                header("X-WebKit-CSP: \"default-src 'none'\"");
                if($request_method !== 'HEAD') {
                        readfile($store_file_name);
                }
        } else {
                header('HTTP/1.0 404 Not Found');
        }
} else if($request_method === 'OPTIONS') {
} else {
        header('HTTP/1.0 400 Bad Request');
}

exit;

Configuration de pywallter

Ensuite on edite le fichier config.py de pywallter pour activer la fonction XMPP :

XMPP_SERVER = True
# Doas or sudo
SETUID='doas'

On s'assure que la commande prosodyctl s'éxecute avec les bons droits et c'est bon on peut démarrer les services prosody et nginx et ensuite redemarrer pywallter:)