Cómo usar el calcetín proxy de vaca

parent_proxy.go
paquete principal

importar (
“codificación / base64”
“codificación / binario”
“errores”
“fmt”
ss “github.com/shadowsocks/shadowsocks-go/shadowsocks”
“io”
“matemáticas / rand”
“red”
“ordenar”
“strconv”
“sincronizar”
“hora”
)

// Interfaz que todos los tipos de proxies primarios deberían admitir.
escriba la interfaz ParentProxy {
connect (* URL) (net.Conn, error)
getServer () string // para usar en la actualización de la latencia del servidor
cadena GenConfig () // para actualizar la configuración
}

// Interfaz para diferentes estrategias de selección de proxy.
escriba la interfaz ParentPool {
agregar (ParentProxy)
vacío () bool
// Seleccione un proxy del grupo y conéctese. Puede probar varios proxies hasta
// uno que tenga éxito, devuelve nil y error si fallan todos los proxies principales.
connect (* URL) (net.Conn, error)
}

// Inicia parentProxy para que sea un grupo de respaldo. Entonces, el análisis de configuración tiene un grupo para agregar
// proxies principales.
var parentProxy ParentPool = & backupParentPool {}

func initParentPool () {
backPool, ok: = parentProxy. (* backupParentPool)
si! ok {
pánico (“el grupo primario inicial debe ser un grupo de respaldo”)
}
si depurar {
printParentProxy (backPool.parent)
}
if len (backPool.parent) == 0 {
info.Println (“sin servidor proxy padre”)
regreso
}
if len (backPool.parent) == 1 && config.LoadBalance! = loadBalanceBackup {
debug.Println (“solo 1 padre, sin necesidad de equilibrio de carga”)
config.LoadBalance = loadBalanceBackup
}

cambiar config.LoadBalance {
case loadBalanceHash:
debug.Println (“grupo padre hash”, len (backPool.parent))
parentProxy = & hashParentPool {* backPool}
case loadBalanceLatency:
debug.Println (“grupo primario de latencia”, len (backPool.parent))
ir a updateParentProxyLatency ()
parentProxy = newLatencyParentPool (backPool.parent)
}
}

func printParentProxy (parent [] ParentWithFail) {
debug.Println (“proxies padre disponibles:”)
para _, pp: = rango padre {
cambiar pc: = pp.ParentProxy. (tipo) {
caso * shadowsocks
debug.Println (“\ tshadowsocks:”, pc.server)
case * httpParent:
debug.Println (“\ thttp parent:”, pc.server)
estuche * calcetines
debug.Println (“\ tsocks parent:”, pc.server)
caso * vaca
debug.Println (“\ tcow parent:”, pc.server)
}
}
}

escriba ParentWithFail struct {
ParentProxy
fallar int
}

// Estrategia de equilibrio de carga de respaldo:
// Seleccione proxy en el orden en que aparecen en la configuración.
escriba backupParentPool struct {
padre [] ParentWithFail
}

func (pp * backupParentPool) empty () bool {
return len (pp.parent) == 0
}

func (pp * backupParentPool) add (parent ParentProxy) {
pp.parent = append (pp.parent, ParentWithFail {parent, 0})
}

func (pp * backupParentPool) connect (url * URL) (srvconn net.Conn, error de error) {
return connectInOrder (url, pp.parent, 0)
}

// Estrategia de equilibrio de carga de hash:
// Cada host usará un proxy basado en un valor hash.
escriba hashParentPool struct {
backupParentPool
}

func (pp * hashParentPool) connect (url * URL) (srvconn net.Conn, error de error) {
inicio: = int (stringHash (url.Host)% uint64 (len (pp.parent)))
debug.Printf (“hash host% s try% d parent first”, url.Host, start)
return connectInOrder (url, pp.parent, start)
}

func (parent * ParentWithFail) connect (url * URL) (srvconn net.Conn, error de error) {
const maxFailCnt = 30
srvconn, err = parent.ParentProxy.connect (url)
if err! = nil {
if parent.fail <maxFailCnt &&! networkBad () {
parent.fail ++
}
regreso
}
parent.fail = 0
regreso
}

func connectInOrder (url * URL, pp [] ParentWithFail, start int) (srvconn net.Conn, error de error) {
const baseFailCnt = 9
var omitió [] int
nproxy: = len (pp)

si nproxy == 0 {
return nil, errors.New (“sin proxy principal”)
}

para i: = 0; i <nproxy; i ++ {
proxyId: = (inicio + i)% nproxy
padre: = & pp [proxyId]
// omite el servidor fallido, pero pruébelo con cierta probabilidad
if parent.fail> 0 && rand.Intn (parent.fail + baseFailCnt)! = 0 {
omitido = agregar (omitido, proxyId)
continuar
}
si srvconn, err = parent.connect (url); err == nil {
regreso
}
}
// último recurso, intente omitir uno, no es probable que tenga éxito
para _, skippedId: = rango omitido {
si srvconn, err = pp [skippedId] .connect (url); err == nil {
regreso
}
}
volver nil, err
}

escriba ParentWithLatency struct {
ParentProxy
tiempo de latencia.
}

type latencyParentPool struct {
parent [] ParentWithLatency
}

func newLatencyParentPool (parent [] ParentWithFail) * latencyParentPool {
lp: = & latencyParentPool {}
para _, p: = rango padre {
lp.add (p.ParentProxy)
}
volver lp
}

func (pp * latencyParentPool) empty () bool {
return len (pp.parent) == 0
}

func (pp * latencyParentPool) add (parent ParentProxy) {
pp.parent = append (pp.parent, ParentWithLatency {parent, 0})
}

// Ordenar la interfaz.
func (pp * latencyParentPool) Len () int {
return len (pp. padre)
}

func (pp * latencyParentPool) Swap (i, j int) {
p: = pp.parent
p [i], p [j] = p [j], p [i]
}

func (pp * latencyParentPool) Less (i, j int) bool {
p: = pp.parent
devuelve p [i] .latency <p [j] .latency
}

const latencyMax = time.Hour

var latencyMutex sync.RWMutex

func (pp * latencyParentPool) connect (url * URL) (srvconn net.Conn, error de error) {
var lp [] ParentWithLatency
// Leer rebanada primero.
latencyMutex.RLock ()
lp = pp.parent
latencyMutex.RUnlock ()

var omitió [] int
nproxy: = len (lp)
si nproxy == 0 {
return nil, errors.New (“sin proxy principal”)
}

para i: = 0; i <nproxy; i ++ {
padre: = lp [i]
if parent.latency> = latencyMax {
omitido = agregar (omitido, i)
continuar
}
si srvconn, err = parent.connect (url); err == nil {
debug.Println (“proxy de latencia más baja”, parent.getServer ())
regreso
}
parent.latency = latencyMax
}
// último recurso, intente omitir uno, no es probable que tenga éxito
para _, skippedId: = rango omitido {
si srvconn, err = lp [skippedId] .connect (url); err == nil {
regreso
}
}
volver nil, err
}

func (parent * ParentWithLatency) updateLatency (wg * sync.WaitGroup) {
diferir wg.Done ()
proxy: = parent.ParentProxy
servidor: = proxy.getServer ()

host, puerto, err: = net.SplitHostPort (servidor)
if err! = nil {
pánico (“error del servidor principal del puerto de host dividido” + err.Error ())
}

// Primero se resuelve el nombre de host, por lo que la latencia no incluye el tiempo de resolución.
ip, err: = net.LookupHost (host)
if err! = nil {
parent.latency = latencyMax
regreso
}
ipPort: = net.JoinHostPort (ip [0], puerto)

const N = 3
var tiempo total. Duración
para i: = 0; i <N; i ++ {
ahora: = time.Now ()
cn, err: = net.DialTimeout (“tcp”, ipPort, dialTimeout)
if err! = nil {
debug.Println (“marcado de actualización de latencia:”, err)
total + = tiempo Minuto // 1 minuto como penalización
continuar
}
total + = tiempo.Ahora (). Sub (ahora)
cn.Close ()

time.Sleep (5 * time.Millisecond)
}
parent.latency = total / N
debug.Println (“latencia”, servidor, latencia principal)
}

func (pp * latencyParentPool) updateLatency () {
// Cree una copia, actualice la latencia para la copia.
latencia var cpParentPool
cp.parent = append (cp.parent, pp.parent …)

// cp.parent es valor en lugar de puntero, si usamos `_, p: = rango cp.parent`,
// el valor en cp.parent no se actualizará.
var wg sync.WaitGroup
wg.Add (len (cp.parent))
para i, _: = rango cp.parent {
cp.parent [i] .updateLatency (& wg)
}
wg.Wait ()

// Ordenar según la latencia.
sort.Stable (& cp)
debug.Println (“proxy más bajo de latencia”, cp.parent [0] .getServer ())

// Actualizar segmento principal.
latencyMutex.Lock ()
pp.parent = cp.parent
latenciaMutex.Unlock ()
}

func updateParentProxyLatency () {
lp, ok: = parentProxy. (* latencyParentPool)
si! ok {
regreso
}

para {
lp.updateLatency ()
time.Sleep (60 * time.Second)
}
}

// proxy padre http
escriba httpParent struct {
cadena de servidor
cadena userPasswd // para la configuración de actualización
authHeader [] byte
}

escriba httpConn struct {
net.Conn
padre * httpParent
}

func (s httpConn) String () string {
devuelve “proxy padre http” + s.parent.server
}

func newHttpParent (cadena del servidor) * httpParent {
return & httpParent {servidor: servidor}
}

func (hp * httpParent) getServer () cadena {
return hp.server
}

cadena func (hp * httpParent) genConfig () {
if hp.userPasswd! = “” {
return fmt.Sprintf (“proxy = http: //% [correo electrónico protegido] % s”, hp.userPasswd, hp.server)
} más {
return fmt.Sprintf (“proxy = http: //% s”, hp.server)
}
}

func (hp * httpParent) initAuth (cadena userPasswd) {
if userPasswd == “” {
regreso
}
hp.userPasswd = userPasswd
b64: = base64.StdEncoding.EncodeToString ([] byte (userPasswd))
hp.authHeader = [] byte (headerProxyAuthorization + “: Basic” + b64 + CRLF)
}

func (hp * httpParent) connect (url * URL) (net.Conn, error) {
c, err: = net.Dial (“tcp”, hp.server)
if err! = nil {
errl.Printf (“no se puede conectar al padre http% s para% s:% v \ n”,
hp.server, url.HostPort, err)
volver nil, err
}
debug.Printf (“conectado a:% s a través de http padre:% s \ n”,
url.HostPort, hp.server)
return httpConn {c, hp}, nil
}

// proxy principal shadowsocks
type shadowsocksParent struct {
cadena de servidor
cadena de método // método y passwd son para configuración de actualización
cadena passwd
cifrado * ss.Cipher
}

escriba shadowsocksConn struct {
net.Conn
padre * shadowsocksParent
}

func (s shadowsocksConn) String () string {
devuelve “shadowsocks proxy” + s.parent.server
}

// Para usar el proxy padre en el orden especificado en el archivo de configuración, nosotros
// inserte un proxy no inicializado en la lista de proxy padre e inicialícelo
// cuando se ha analizado toda su configuración.

func newShadowsocksParent (cadena del servidor) * shadowsocksParent {
return & shadowsocksParent {servidor: servidor}
}

func (sp * shadowsocksParent) getServer () string {
volver sp.server
}

func (sp * shadowsocksParent) genConfig () string {
método: = método sp.
si método == “” {
método = “tabla”
}
return fmt.Sprintf (“proxy = ss: //% s:% [correo electrónico protegido] % s”, método, sp.passwd, sp.server)
}

func (sp * shadowsocksParent) initCipher (método, cadena passwd) {
sp.method = método
sp.passwd = passwd
cifrado, err: = ss.NewCipher (método, contraseña)
if err! = nil {
Fatal (“crear cifrado shadowsocks:”, err)
}
sp.cipher = cifrado
}

func (sp * shadowsocksParent) connect (url * URL) (net.Conn, error) {
c, err: = ss.Dial (url.HostPort, sp.server, sp.cipher.Copy ())
if err! = nil {
errl.Printf (“no se puede conectar a shadowsocks parent% s para% s:% v \ n”,
sp.server, url.HostPort, err)
volver nil, err
}
debug.Println (“conectado a:”, url.HostPort, “a través de shadowsocks:”, sp.server)
return shadowsocksConn {c, sp}, nil
}

// proxy de padre vaca
tipo cowParent struct {
cadena de servidor
cadena de método
cadena passwd
cifrado * ss.Cipher
}

escriba cowConn struct {
net.Conn
padre * vaca
}

func (s cowConn) String () string {
devuelve “proxy de vaca” + s.parent.server
}

func newCowParent (srv, método, cadena passwd) * cowParent {
cifrado, err: = ss.NewCipher (método, contraseña)
if err! = nil {
Fatal (“crear cifrado de vaca:”, err)
}
return & cowParent {srv, method, passwd, cipher}
}

func (cp * cowParent) getServer () cadena {
return cp.server
}

func (cp * cowParent) genConfig () string {
método: = método cp.
si método == “” {
método = “tabla”
}
return fmt.Sprintf (“proxy = vaca: //% s:% [correo electrónico protegido] % s”, método, cp.passwd, cp.server)
}

func (cp * cowParent) connect (url * URL) (net.Conn, error) {
c, err: = net.Dial (“tcp”, cp.server)
if err! = nil {
errl.Printf (“no se puede conectar al padre de vaca% s para% s:% v \ n”,
cp.server, url.HostPort, err)
volver nil, err
}
debug.Printf (“conectado a:% s a través del padre de vaca:% s \ n”,
url.HostPort, cp.server)
ssconn: = ss.NewConn (c, cp.cipher.Copy ())
return cowConn {ssconn, cp}, nil
}

// Para la documentación de calcetines, consulte rfc 1928 http://www.ietf.org/rfc/rfc1928.txt

var socksError = […] cadena {
1: “Error general del servidor SOCKS”,
2: “Conexión no permitida por el conjunto de reglas”,
3: “Red inalcanzable”,
4: “Host inalcanzable”,
5: “Conexión rechazada”,
6: “TTL expiró”,
7: “Comando no compatible”,
8: “Tipo de dirección no compatible”,
9: “a X’FF ‘sin asignar”,
}

var socksProtocolErr = errors.New (“error de protocolo de calcetines”)

var socksMsgVerMethodSelection = [] byte {
0x5, // versión 5
1, // método n
0, // no se requiere autorización
}

// calcetines5 proxy padre
tipo calcetines Estructura paterna {
cadena de servidor
}

tipo calcetinesConn struct {
net.Conn
padres * calcetines
}

func (s socksConn) String () string {
return “calcetines proxy” + s.parent.server
}

func newSocksParent (cadena del servidor) * socksParent {
return & socksParent {servidor}
}

func (sp * socksParent) getServer () string {
return sp.server
}

func (sp * socksParent) genConfig () string {
return fmt.Sprintf (“proxy = socks5: //% s”, sp.server)
}

func (sp * socksParent) connect (url * URL) (net.Conn, error) {
c, err: = net.Dial (“tcp”, sp.server)
if err! = nil {
errl.Printf (“no se puede conectar a los calcetines padre% s para% s:% v \ n”,
sp.server, url.HostPort, err)
volver nil, err
}
hasErr: = falso
diferir func () {
si hasErr {
c. Cerrar ()
}
} ()

var n int
si n, err = c.Write (socksMsgVerMethodSelection); n! = 3 || err! = nil {
errl.Printf (“enviando selección de ver / método msg% vn =% v \ n”, err, n)
hasErr = verdadero
volver nil, err
}

// selección de versión / método
repBuf: = make ([] byte, 2)
_, err = io.ReadFull (c, repBuf)
if err! = nil {
errl.Printf (“leer ver / método error de selección% v \ n”, err)
hasErr = verdadero
volver nil, err
}
si repBuf [0]! = 5 || repBuf [1]! = 0 {
errl.Printf (“calcetines ver / método selección error respuesta ver% d método% d”,
repBuf [0], repBuf [1])
hasErr = verdadero
volver nil, err
}
// debug.Println (“Selección de versión de calcetines realizada”)

// enviar solicitud de conexión
host: = url.Host
puerto, err: = strconv.Atoi (url.Port)
if err! = nil {
errl.Printf (“no debería suceder, error de puerto% v \ n”, puerto)
hasErr = verdadero
volver nil, err
}

hostLen: = len (host)
bufLen: = 5 + hostLen + 2 // last 2 is port
reqBuf: = make ([] byte, bufLen)
reqBuf [0] = 5 // versión 5
reqBuf [1] = 1 // cmd: conectar
// reqBuf [2] = 0 // rsv: establecido en 0 al inicializar
reqBuf [3] = 3 // atyp: nombre de dominio
reqBuf [4] = byte (hostLen)
copia (reqBuf [5:], host)
binary.BigEndian.PutUint16 (reqBuf [5 + hostLen: 5 + hostLen + 2], uint16 (puerto))

si n, err = c. Escribir (reqBuf); err! = nil || n! = bufLen {
errl.Printf (“enviar solicitud de calcetines err% vn% d \ n”, err, n)
hasErr = verdadero
volver nil, err
}

// No estoy claro por qué el búfer está fijado en 10. El documento rfc no dice esto.
// Polipo estableció esto en 10 y también observé que la respuesta siempre es 10.
replyBuf: = make ([] byte, 10)
si n, err = c. Leer (replyBuf); err! = nil {
// Parece que el servidor de calcetines cerrará la conexión si no puede encontrar el host
if err! = io.EOF {
errl.Printf (“leer calcetines responder err% vn% d \ n”, err, n)
}
hasErr = verdadero
return nil, errors.New (“falló la conexión (por servidor de calcetines” + sp.server + “). ¿No hay tal host?”)
}
// debug.Printf (“Longitud de respuesta de calcetines% d \ n”, n)

if replyBuf [0]! = 5 {
errl.Printf (“los calcetines responden connect% s VER% d no son compatibles \ n”, url.HostPort, replyBuf [0])
hasErr = verdadero
return nil, socksProtocolErr
}
if replyBuf [1]! = 0 {
errl.Printf (“los calcetines responden conectan% s error% s \ n”, url.HostPort, socksError [replyBuf [1]])
hasErr = verdadero
return nil, socksProtocolErr
}
if replyBuf [3]! = 1 {
errl.Printf (“los calcetines responden connect% s ATYP% d \ n”, url.HostPort, replyBuf [3])
hasErr = verdadero
return nil, socksProtocolErr
}

debug.Println (“conectado a:”, url.HostPort, “a través del servidor de calcetines:”, servidor sp.)
// Ahora el socket se puede usar para pasar datos.
calcetines de retornoConn {c, sp}, nil
}

no sé cómo escribir el código correctamente. Intenté varias veces, así que te pregunto ahora … espero que puedas guiarme … escribí esto:

PERO NO FUNCIONA …

More Interesting

¿Cuáles son las tecnologías prometedoras para las redes celulares de próxima generación?

En mi universidad, los teléfonos inteligentes tienen restringido el uso de WiFi de la universidad, pero podemos usarlo en nuestras computadoras portátiles (no teléfonos) usando nuestro número de identificación y contraseña. Algunos teléfonos están conectados a la red, pero no pueden usar WiFi. ¿Cómo puedo conectarlo al WiFi de la universidad?

Cuando los ISP hablan de invertir en una mejor infraestructura, ¿qué quieren mejorar específicamente? ¿Cuáles son los cuellos de botella?

Para ser un buen administrador del sistema, ¿qué cosas debo saber (tanto prácticas como teóricas)?

¿Cómo puede un ingeniero de redes entrar en consultoría?

¿Qué está haciendo Google para acelerar la latencia de TCP y ampliar los límites de TCP / IP?

¿Cuáles son los recursos y qué camino debo seguir para convertirme en un profesional de seguridad ofensivo?

Cómo transferir archivos de una red privada a otra a través de la línea de comando

¿Cuál es el mejor libro para estudiar las redes inalámbricas de computadoras?

¿Por qué siempre usamos enlaces seriales entre dos enrutadores, a pesar de que tenemos puertos rápidos de Ethernet?

¿CCNA tiene valor en las redes o es innecesario?

¿Cuáles son los pros y los contras de la conmutación de paquetes versus la conmutación de circuitos en redes de comunicación?

¿Debería usar 2 ^ n - 2 para encontrar el número de subredes utilizables posibles?

Cómo encontrar la velocidad de WiFi que debo obtener, teniendo en cuenta la distancia y los obstáculos

¿Quién posee y opera todos los conmutadores de Internet, enrutadores y servidores DNS, y para qué beneficio?