[Détails techniques] Idée de fichier de config

Vu que j’ai du mal à voir les trucs abstraits et mieux le concret, j’ai commencé à me faire un fichier de config TOML d’un serveur SM2TP potentiel, qui ferait ce dont j’ai envie.

C’est peut-être un peu tôt, car on n’a pas les retours du sondage, mais vu que j’en causais dans la discussion sur les providers de protection ça m’a semblé pertinent.

Je le met ci-dessous pour partager. Ça ne veut pas dire que c’est ce qu’il faut qu’il y ait au final, ni que je suis super attaché à la syntaxe, ou que je trouve le vocabulaire parfait, c’est juste une première idée, en essayant d’être le plus lisible possible.

# Local node configuration
[node.self]
# Name of node
name = "Me"

# Admin e-mail address
admin = "root@example.org"

# Public and private encryption keys
public_key = "XXX"
private_key = "XXX"

# Default relay policy from other federated servers
# Message type can be:
# - newsletter: message sent from a software or user to multiple recipients, who have subscribed to this message
# - list: message relayed from a person to a list of other persons (mailing list)
# - transactional: automated messages sent from a server to a recipient (eg. lost password)
# - private: message from one person to another (eg. mailbox)
# - mass: message originated from a private mailbox, but with more than 10 recipients
#   (eg. "manual newsletter")
#
# Values can be:
# - true (accept everything)
# - false (accept nothing)
# - "100/1d" (maximum number of messages accepted in a time period, period can be in [h]ours, [d]ays, [w]eeks, [m]onths, [y]ears)
#
# When the maximum number of messages is reached, this node will stop accepting messages.
# The remote node SHOULD also keep track of this limit and stop trying to send when it's reached.
accept.newsletter = false
accept.list = "500/1d"
accept.private = true
accept.transactional = true
accept.mass = true

# Default forward policy *TO* other servers
# This can either be:
# - false (forward nothing)
# - true (forward everything)
# - "X%" (percentage, forward this percentage of received messages to this node)
# - "auto" (automatically split messages between all nodes accepting this type of messages)
forward.private = false
forward.list = "auto"
forward.newsletter = "20%"
forward.transaction = "auto"
forward.mass = false

# Add a federated relay node
[node.framasoft]
public_key = "XXX"
admin = "root@framasoft.example.org"
url = "https://…"

# Bypass default policy, do not forward any mailing list messages to this relay
forward.list = false

# Bypass default policy, to accept newsletter emails from this node
accept.newsletter = true

# Configuration of a remote domain
[domain."orange.fr"]

# Limit maximum number of messages per connection for this recipient
max_messages_per_connection = 10

# Add a SMTP node
[node.scaleway]
type = "smtp"
host = "smtp.scaleway.com"
user = "XXX"
password = "XXX"
port = 587

# Do not send to this domain, instead forward to scaleway node
[domain."free.fr"]
forward = "scaleway"

# Configuration of a remote MX
# matching is done on the end of the DNS, eg. this will match ".*mailinblack\.com"
[mx."mailinblack.com"]

# Block any domain using this MX from receiving automated messages
bounce.newsletter = true
bounce.mass = true
bounce.list = true
bounce.transactional = true
bounce_message = "Ce destinataire utilise le service Mailinblack.com, qui ne peut recevoir de message automatisé."

# Example of a MX provider that blocked our IP
# Use another relay for all the messages
[mx."pphosted.com"]
relay = "framasoft"

# Block all emails to this domain, as it does not have a valid MX record
# (this is just an example, as MX record is checked before sending)
[domain."gmail.fr"]
bounce = true
bounce_message = "Vous avez fait une fait de frappe : le nom de domaine gmail.fr n'existe pas, remplacez-le par gmail.com dans l'adresse de votre destinataire."

[user.jane]
password = "XXX"
domains = ["example.org"]

# Call a webhook for bounces
webhook.bounce = "https://example.org/mail_bounce.php"

# Call a webhook for delivered messages
webhook.delivery = "https://example.org/mail_ok.php"

# To avoid sending thousands of requests, group events for this duration before calling the webhooks
# Can be in [m]inutes, [h]ours, or [d]ays
webhook.grouping = "1m"

On peut voir plusieurs trucs qui m’intéressent personnellement ici :

  • les webhooks sur les envois effectués / bounces
  • la possibilité de définir des règles pour des MX / domaines destinataires particuliers (exemple ici on bloque vers gmail.fr, on limite les envois vers orange, on bloque les mails automatisés vers mailinblack, etc.)
  • la possibilité de définir des relais « SM2TP »
  • la possibilité de définir des relais SMTP classiques
  • la possibilité de définir finement ce qu’on veut accepter comme trafic entrant, et ce qu’on accepte de sortir comme type de messages (en sachant qu’on s’attend à ce que si on n’a pas indiqué de limite aux noeuds de relais fédérés, ceux-ci nous refuseront les envois quand on aura atteint les limites qu’ils nous donnent : exemple le noeud framasoft peut avoir choisi de m’imposer une limite à 1000 messages / jour, si je dépasse alors le noeud me répondra 429 en HTTP par exemple, en indiquant la limite que j’ai atteint, et mon serveur SM2TP local arrêtera d’envoyer via ce relais)

Bon évidemment ça a l’air simple comme ça, mais l’implémentation derrière c’est une autre paire de manche.

Dans mon idée l’auth entre relais se fait avec libsodium : on s’échange nos clés publiques entre relais, et ensuite les messages transmis par mon relais sont chiffrés en utilisant la clé publique du relais destinataire, et signé avec ma clé privée. Le relais destinataire vérifie la signature avec ma clé publique, et déchiffre le message avec sa clé privée. Pas de login/mot de passe, pas d’OAuth. Bon cette logique est peut-être insuffisante, notamment si on doit révoquer sa paire de clés pour une raison X ou Y, je n’ai pas trop réfléchi aux détails pour le moment.

Du coup la config d’exemple reflète cette idée.

2 Likes