ĞMixer – anonymiseur de transactions sûr et distribué

silkaj
python
duniterpy

#21

En effet, c’est rare que je termine un projet que j’ai commencé…

Mais là ça marche ! C’est très satisfaisant, la première transaction ĞMixée automatiquement en oignon a été réalisée entre mon compte et celui-ci. Bien sûr, il reste encore quelques fonctionnalités à ajouter dans le serveur, notamment le retour des transactions, et plein de tests de sécurité pour éviter un crash dû à une erreur.

Il reste aussi la rémunération des nœuds. Soit on se met d’accord sur une taxe fixe que chaque nœud prend sur la transaction (donc avec une taxe à 1 Ğ1, une transaction de 100 Ğ1 passant par 3 nœuds sera de 97 Ğ1 en sortie), mais cela peut poser des problèmes d’anonymat (on peut tracer plus facilement les transactions puisqu’on sait par combien de nœuds elle est passée, enfin peut-être que ça ne pose pas de problème) ; soit on n’applique pas de taxe mais on crée un double de Remuniter pour cela.


#22

En fait je comprend pas bien comment ça fonctionne… parce que là les junes ne sont pas anonymes :thinking:
on remonte facilement à la source via les transactions…


#23

On peut choisir le nombre minimal de transactions pour mixer, par défaut c’est 5 mais pour le test j’en ai mis une seule (parce qu’attendre 20 minutes que chaque transaction soit enregistrée c’est déjà long pour le test). Quand j’aurai réinstallé mon Raspberry Pi, j’y mettrais des instances de test publiques, et ça serait sympa si d’autres gens pouvaient en faire tourner aussi, pour tester avec plus de nœuds et plus de transactions.


#24

On peut en mettre 20, on pourra toujours remonter à la source, non ?


#25

Comment ?

Seuls le nœud A et le client d’origine savent associer une transaction que reçoit A et une qu’il envoie, grâce aux commentaires.


#26

Bonjour,

S’il y a une sorte de remu-Gmixer, est-ce possible d’appliquer une taxe une fois par transaction (p.ex entrée ou sortie) qui l’enverrait sur le compte de répartition ? Cela aurait-il des conséquences pour le “suivi” des transactions ?


#27

C’est une bonne idée. En fait, on peut toujours savoir si une transaction est en entrée ou en sortie, puisque l’envoyeur ou le récepteur n’est pas un nœud. Donc on peut toujours savoir où se situe une transaction (envoyeur-1 ou 1-2 ou 2-3 ou 3-receveur), la seule incertitude est quand elle est au milieu (1-2 ou 2-3). Cette incertitude offre 2 possibilités pour un chemin de 3 nœuds. Pour compliquer la chose, on pourrait faire aléatoirement un chemin de 3 ou de 4 nœuds (je n’ai pas calculé les probabilités donc je ne sais pas si ça serait significativement intéressant).

Comment choisir qui est rémunéré ? À quel montant ? Un propriétaire de nœud pourrait faire passer uniquement ses propres transactions et pas les autres par son nœud, donc recevoir la rémunération alors qu’il ne devrait pas.

Edit: Si vous voulez tester, vous pouvez ajouter cette ligne dans le fichier peers pour le connecter à mon nœud :

4QRZj4bHpXTdJajfX8mTf2RmYQhKX7BtiMiZL3z5Lo8F 86.234.239.147 10951

#28

Peut-être que tu pourrais déplacer le dépôt de ĞMIxer à l’adresse https://git.duniter.org/clients/python/ĞMixer
Car il utilise Silkaj et DuniterPy et est écrit en Python. De plus, c’est un client Duniter.

Je vois que tu utilises Silkaj 0.6.1 qui n’utilise pas DuniterPy.
À partir de Silkaj 0.7.0, ça utilise DuniterPy, et par conséquent, le code est asynchrone.
Dans ton code, je vois des parties, ou débuts d’asynchrone. Tu seras prêt pour l’y intégrer.

Autre, jette un coup d’œil à pipenv. Ça sera plus propre pour gérer les dépendances.

Si tu as besoin d’aide avec le code de Silkaj ou DuniterPy ou tout autre sujet relatif à l’environnement ou le langage Python n’hésite pas.


#29

Pour déplacer le dépôt c’est dans " Rename repository" ?

Je crois que je ne me servirai pas de l’asynchrone, du coup j’aurai juste besoin de mettre des await partout.

Je verrai plus tard pipenv…


#30

Voilà j’ai enfin réussi à configurer correctement mon réseau… Maintenant c’est compatible avec IPv6.

Si vous voulez héberger une instance, pour pouvoir tester à la fois la gestion des connexions et les transactions :

sudo apt install libsodium-dev python3 python3-pip
sudo pip3 install libnacl duniterpy silkaj
sudo pip3 install python2_secrets # seulement si Python < 3.6

git clone https://git.duniter.org/tuxmain/gmixer-py.git
cd gmixer-py
python3 server.py -i
nano ~/.gmixer/config.ini
# changez Host si nécessaire avec votre IP
echo "4QRZj4bHpXTdJajfX8mTf2RmYQhKX7BtiMiZL3z5Lo8F 2a01:cb19:982:f800:ec34:6087:5197:4752 10951" >> ~/.gmixer/peers
echo "FE4p3w7LvfDtat7pwNky5vZ9SPGKRrFid8gS2bg8Pjka 2a01:cb19:982:f800:ec34:6087:5197:4752 10952" >> ~/.gmixer/peers
python server.py -s

Le programme ne gère pas l’upnp donc il faudra probablement toucher aux NAT/PAT et pare-feu de votre box/routeur. C’est TCP et port par défaut 10951.

Pour voir les infos sur un nœud, il y a une magnifique API qui permet notamment d’avoir la liste des pairs : http://[2a01:cb19:982:f800:ec34:6087:5197:4752]:10951/list/pubkey/version (le forum ne veut pas reconnaître le lien à cause de l’IPv6)


#31

Voilà le compte-rendu de l’avancement :

  • Les données chiffrées sont désormais en binaire plutôt qu’en hexa (grâce à la màj de duniterpy) ;
  • Le client se connecte à un nœud pour récupérer la liste des nœuds et construit un chemin composé de n nœuds aléatoires ;
  • La liste des transactions est enregistrée dans une bdd LevelDB, donc si le nœud est redémarré il peut continuer de traiter les transactions en cours ;
  • Répondre un accusé de réception pour pouvoir renvoyer la requête si il y a un problème réseau ;
  • Utiliser ubjson plutôt que json partout. C’est du json en binaire donc c’est plus léger, rapide et on peut stocker du binaire sans conversion. (et oui il existe une bibli JS) ;
  • Le support des clés publiques à 43 caractères. Je viens de découvrir ça avec horreur, certaines clés publiques (très peu) font 43 caractères plutôt que 44 ;
  • Les requêtes trop vieilles sont supprimées de la bdd.

J’ai commencé à faire des jolis schémas avec Mermaid pour la doc du protocole, est-ce que vous trouvez ça clair ? (j’ai prévu un autre schéma pour le contenu des paquets à chaque étape mais mermaid est plutôt limité en fait)

Hier soir j’ai essayé de faire un test presque grandeur nature, en faisant tourner en local 4 serveurs et en lançant 7 requêtes de mixage, mais ce cher Destin©™ était contre moi : déjà la blockchain avait du retard donc les premières transactions ont mis 3 heures à s’écrire, et en plus j’avais pris un serveur BMA qui ne stockait pas les transactions, donc forcément ça marchait pas ! Alors ça serait effectivement une bonne chose qu’on puisse savoir via l’API le store-txs d’un nœud Duniter.


#32

Hop, une nouveauté :

  • Le support d’un proxy SOCKS5, donc la possibilité de faire tourner le nœud avec un hidden service. Parfait quand on a une IP dynamique comme moi.

Voici donc mes 2 instances publiques, vraiment publiques cette fois :

4QRZj4bHpXTdJajfX8mTf2RmYQhKX7BtiMiZL3z5Lo8F svetsae7j3usrycn.onion 10951
FE4p3w7LvfDtat7pwNky5vZ9SPGKRrFid8gS2bg8Pjka svetsae7j3usrycn.onion 10952

Du coup mon serveur HTTP avec Cesium, WorldWotMap et wotmap est accessible aussi en onion sur le port 80…

Edit: Page du projet sur mon site, avec explications (si quelqu’un veut aider pour traduire en anglais…)


#33

Les cloches de Pâques sont passées plus tôt cette année (enfin ce soir je n’arrive pas à pusher, problème de réseau) : :egg:

  • Le commentaire d’une transaction (servant d’identifiant unique) n’est désormais plus choisi par un seul nœud, mais à partir de trois graines aléatoires venant du client et des deux nœuds impliqués dans une transaction (dont le client pour la première et la dernière). Cela évite qu’un serveur triche en donnant le même commentaire à deux transactions proches dans le temps, ce qui lui permettrait de virer une seule fois l’argent tout en disant “mais si je l’ai faite la transaction avec le commentaire machin”.

C’est donc un petit correctif de sécurité pour le protocole. La prochaine étape est que le client vérifie que les transactions passent bien, et le cas contraire, qu’il puisse envoyer à des nœuds les confirmations non respectées et que les nœuds se les diffusent et les enregistrent, et refusent les transactions avec les nœuds fautifs.

Afin que le propriétaire d’un nœud qui a déjà volé un client ne recommence pas anonymement, en changeant juste la clé publique de son nœud, il serait envisageable de connecter le système à la WoT. Qu’en pensez-vous ? :question:

Aussi tout ce bazar est fonctionnel, donc je vous invite à l’installer si vous avez un serveur, pour qu’on puisse enfin le tester :yum: (les instructions d’installation sont là).


#34

J’ai essayé de l’installer, j’ai quelques problèmes. Hier soir, il ne détectait aucun peer. Et si j’essayais de remplir le fichier peers à la main il était tout de suite écrasé. On devrait pouvoir éditer les peers, non ? Ce matin, quand je le lance, il détecte les peers (ils ne devaient pas être lancés hier) mais ensuite il me crache une erreur à la figure, ce qui n’est pas très gentil :stuck_out_tongue: :

File “server.py”, line 494, in detectPeers
header, content = sdata((peer.host, peer.port), “POST”, “/list/new/”+self.keys.pubkey, message, proxy=self.conf[“client”][“proxy”], proxy_onion_only=self.conf[“client”][“proxy_onion_only”]) # Send
File “/jytoussd/git/gmixer-py/utils.py”, line 66, in sdata
sock.connect(host)
socket.gaierror: [Errno -2] Name or service not known

Des idées ?


#35

C’est normal qu’il ne détecte aucun pair, il n’y a pas de liste par défaut. On peut éditer la liste à la main (d’ailleurs il faut si on veut se rattacher à un réseau existant) et il la réécrit pour ajouter ceux qu’il détecte (mais il n’est pas sensé en supprimer).

J’ai deux nœuds qui tournent mais étant en vacance à un endroit où je n’arrive pas à me connecter à mon RPI en SSH, ils ne sont pas à jour alors ils ne seront pas compatibles à cause du dernier commit… (mais je vois que tu as l’ancienne version, aux numéros de lignes)

J’ai pas pris en compte toutes les erreurs comme tu peux le voir, j’ajoute une exception pour celle-ci.

Edit: voilà c’est corrigé (en même temps j’ai ajouté un timeout aux connexions sortantes).


#36

Ah ben oui, là c’est mieux ! :slight_smile:

Par contre, quand j’essaie de requêter directement par l’extérieur , ça part en timeout. En localhost ça passe mais pas avec gmix.jytou.fr:9016


#37

Tu as bien mis gmix.jytou.fr dans les deux champs Host de config.json ?


#38

Non, seulement dans la partie public host :

{
“server”: {
“bind_host”: “192.168.0.63”,
“bind_port”: 9016,
“public_host”: “gmix.jytou.fr”,
“public_port”: 9016
},

Le port est bien mappé côté box… t’as pas besoin d’UDP, juste TCP ?


#39

Oui c’est TCP (tout HTTP, pour la compatibilité avec un potentiel client JS).

public_host et public_port sont envoyés aux autres nœuds qui demandent la liste des nœuds connus. bind_host est l’adresse à laquelle le socket écoute. Donc si c’est localhost, il ne prendra que les requêtes adressées à localhost. Il faut mettre la même aux deux, sauf si on utilise un reverse proxy. Dans ce cas il faut mettre l’adresse locale à bind et la publique à public.


#40

Le problème c’est que bind_host est forcément l’adresse de la machine sur le réseau local ou localhost, sinon tu ne peux pas binder dessus à moins d’être en direct sur internet. Là, je suis en NAT et il ne démarre pas si je mets l’adresse publique dans bind_host.