Il s'agit d'une réimplémentation Go de mmproxy, créée pour améliorer la stabilité d'exécution de mmproxy tout en offrant des performances potentiellement supérieures en termes de connexion et de débit de paquets.
go-mmproxy
est une application autonome qui déballe le protocole PROXY de HAProxy (également adopté par d'autres projets tels que NGINX) afin que la connexion réseau au serveur final provienne de l'adresse IP et du numéro de port du client - au lieu du serveur proxy. Parce qu'ils partagent des mécanismes de base, le billet de blog de Cloudflare sur mmproxy constitue un excellent article sur le fonctionnement caché go-mmproxy
.
go install github.com/path-network/go-mmproxy@latest
Vous aurez besoin d'au moins go 1.21
pour construire le binaire go-mmproxy
. Consultez le guide de démarrage de Go si votre gestionnaire de packages ne propose pas une version suffisamment récente de Golang.
go-mmproxy
doit être exécuté :
CAP_NET_ADMIN
pour pouvoir définir l'option de socket IP_TRANSPARENT
. Acheminez tout le trafic provenant du bouclage vers le bouclage :
ip rule add from 127.0.0.1/8 iif lo table 123
ip route add local 0.0.0.0/0 dev lo table 123
ip -6 rule add from ::1/128 iif lo table 123
ip -6 route add local ::/0 dev lo table 123
Si l'option --mark
est donnée à go-mmproxy
, tous les paquets acheminés vers l'interface de bouclage auront la marque définie. Cela peut être utilisé pour configurer des règles de routage plus avancées avec iptables, par exemple lorsque vous avez besoin que le trafic du bouclage soit acheminé à l'extérieur de la machine.
Parce qu'UDP est sans connexion, si un socket est lié à 0.0.0.0
, la pile du noyau recherchera une interface afin d'envoyer une réponse à l'adresse source usurpée - au lieu d'utiliser simplement l'interface d'où elle a reçu le paquet d'origine. L'interface trouvée ne sera probablement pas l'interface de bouclage, ce qui évitera les règles spécifiées ci-dessus. Le moyen le plus simple de résoudre ce problème consiste à lier les écouteurs du serveur final à 127.0.0.1
(ou ::1
). Ceci est également généralement recommandé afin d’éviter de recevoir des connexions non proxy.
Usage of ./go-mmproxy:
-4 string
Address to which IPv4 traffic will be forwarded to (default "127.0.0.1:443")
-6 string
Address to which IPv6 traffic will be forwarded to (default "[::1]:443")
-allowed-subnets string
Path to a file that contains allowed subnets of the proxy servers
-close-after int
Number of seconds after which UDP socket will be cleaned up (default 60)
-l string
Address the proxy listens on (default "0.0.0.0:8443")
-listeners int
Number of listener sockets that will be opened for the listen address (Linux 3.9+) (default 1)
-mark int
The mark that will be set on outbound packets
-p string
Protocol that will be proxied: tcp, udp (default "tcp")
-v int
0 - no logging of individual connections
1 - log errors occurring in individual connections
2 - log all state changes of individual connections
Exemple d'invocation :
sudo ./go-mmproxy -l 0.0.0.0:25577 -4 127.0.0.1:25578 -6 [::1]:25578 --allowed-subnets ./path-prefixes.txt
Le benchmark a été exécuté sur Dell XPS 9570 avec un processeur Intel Core i9-8950HK à 2,90 GHz (12 cœurs logiques). Le service en amont vers lequel le proxy envoyait le trafic a été simulé par le serveur bpf-echo. Le trafic a été généré par tcpkali v1.1.1 .
La commande suivante a été utilisée pour la génération de charge dans tous les cas (50 connexions, exécution de 10 s, envoi d'un en-tête PROXYv1 pour chaque connexion, utilisation PINGrn
comme message TCP) :
tcpkali -c 50 -T 10s -e1 'PROXY TCP4 127.0.0.1 127.0.0.1 {connection.uid} 25578rn' -m 'PINGrn' 127.0.0.1:1122
⇅ Mbit/s | ↓ Mbit/s | ↑ Mbit/s | ↓ paquet/s | ↑ pkt/s | |
---|---|---|---|---|---|
cloudflare/mmproxy | 1524.454 | 756.385 | 768.069 | 70365.9 | 65921.9 |
go-mmproxy GOMAXPROCS=1 | 7418.312 | 2858.794 | 4559.518 | 262062.7 | 391334.6 |
aller-mmproxy | 45483.233 | 16142.348 | 29340.885 | 1477889.6 | 2518271.5 |
pas de procuration | 52640.116 | 22561.129 | 30078.987 | 2065805.4 | 2581621.3 |