Esta es una reimplementación de mmproxy en Go, creada para mejorar la estabilidad del tiempo de ejecución de mmproxy y al mismo tiempo proporcionar un rendimiento potencialmente mayor en términos de conexión y rendimiento de paquetes.
go-mmproxy
es una aplicación independiente que desenvuelve el protocolo PROXY de HAProxy (también adoptado por otros proyectos como NGINX) para que la conexión de red al servidor final provenga de la dirección IP y el número de puerto del cliente, en lugar de la dirección IP del servidor proxy. Debido a que comparten mecanismos básicos, la publicación de blog de Cloudflare sobre mmproxy sirve como un excelente artículo sobre cómo funciona go-mmproxy
internamente.
go install github.com/path-network/go-mmproxy@latest
Necesitará al menos go 1.21
para compilar el binario go-mmproxy
. Consulte Introducción a Go si su administrador de paquetes no incluye una versión suficientemente nueva de golang.
Se debe ejecutar go-mmproxy
:
CAP_NET_ADMIN
para poder configurar la opción de socket IP_TRANSPARENT
. Enrute todo el tráfico que se origina desde el loopback hacia el loopback:
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 se le da la opción --mark
a go-mmproxy
, todos los paquetes enrutados a la interfaz loopback tendrán la marca establecida. Esto se puede utilizar para configurar reglas de enrutamiento más avanzadas con iptables, por ejemplo, cuando necesita que el tráfico del loopback se enrute fuera de la máquina.
Debido a que UDP no tiene conexión, si un socket está vinculado a 0.0.0.0
, la pila del kernel buscará una interfaz para enviar una respuesta a la dirección de origen falsificada, en lugar de simplemente usar la interfaz desde la que recibió el paquete original. Lo más probable es que la interfaz encontrada no sea la interfaz de bucle invertido, lo que evitará las reglas especificadas anteriormente. La forma más sencilla de solucionar este problema es vincular los oyentes del servidor final a 127.0.0.1
(o ::1
). Esto también se recomienda generalmente para evitar recibir conexiones no 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
Ejemplo de invocación:
sudo ./go-mmproxy -l 0.0.0.0:25577 -4 127.0.0.1:25578 -6 [::1]:25578 --allowed-subnets ./path-prefixes.txt
La prueba se ejecutó en Dell XPS 9570 con CPU Intel Core i9-8950HK a 2,90 GHz (12 núcleos lógicos). El servidor bpf-echo se burló del servicio ascendente al que el proxy enviaba tráfico. El tráfico fue generado por tcpkali v1.1.1.
El siguiente comando se usó para la generación de carga en todos los casos (50 conexiones, 10 segundos de tiempo de ejecución, enviar encabezado PROXYv1 para cada conexión, usar PINGrn
como mensaje 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
⇅Mbps | ↓Mbps | ↑ Mbps | ↓ paquete/s | ↑ paquete/s | |
---|---|---|---|---|---|
nubeflare/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 |
ir-mmproxy | 45483.233 | 16142.348 | 29340.885 | 1477889.6 | 2518271.5 |
sin proxy | 52640.116 | 22561.129 | 30078.987 | 2065805.4 | 2581621.3 |