-------------------------------------------------------------------------- -----------------------Protocolo Socks5 by MazarD------------------------- -------------------------------------------------------------------------- 1- Introducción 2- Negociación de método 3- Petición de conexión 4- Conexiones UDP 5- Algo de seguridad 6- Implementación de un cliente 7- Links de interes |--------------------------------------------------------------------------| |--------------------->1-Introducción--------------------------------------| |--------------------------------------------------------------------------| Hay muchas utilidades que permiten a cualquier programa conectar a través de proxy socks5 pero jode bastante tener que ejecutarlas cada vez que usas uno de tus "programitas que requieren privacidad" así que nos trabajamos una pequeña libreria y ya quando lo necesitemos la metemos y nos olvidamos. También puede serte útil para programar ircbots, falsear clicks en banners o cualquier cosa que necesite de muchos hosts, aunque resulta algo jodido encontrar buenas listas de Socks5. Además hay poca documentación sobre este protocolo en español, y como hace un tiempo me lo curré con la rfc he pensado en escribirlo. |--------------------------------------------------------------------------| |--------------------->2-Negociación de método-----------------------------| |--------------------------------------------------------------------------| Lo primero que debemos hacer al establecer la conexión con el proxy será enviarle los metódos que nuestro cliente puede soportar (un poco más adelante veremos cuales son estos métodos): +----+----------+----------+ |VER | NMETHODS | METHODS | +----+----------+----------+ | 1 | 1 | 1 to 255 | <--N Bytes +----+----------+----------+ El primer byte es la version del protocolo, en nuestro caso será 5. NMETHODS es un byte que determina el número de metodos que soporta nuestro cliente. En Methods enviaremos los métodos soportados, 1byte por método, teniendo coherencia, lógicamente con el número de métodos establecidos, de lo contrario el servidor nos enviará un GENERAL SOCKS SERVER FAILURE. Al haber enviado lo anterior el servidor nos responderá con el método que decide de los posibles que soportamos con la siguiente estructura: +----+--------+ |VER | METHOD | +----+--------+ | 1 | 1 | <--N Bytes +----+--------+ A esto se le llama select. El primer byte ver será el protocolo que soporta el servidor y deberá ser 5 seguido del byte que determina el método elegido. Los valores establecidos por la especificación del protocolo sobre los métodos són los siguientes: o X'00' Sin autenticación o X'01' GSSAPI o X'02' USERNAME/PASSWORD o X'03' hasta X'7F' Asignados por IANA o X'80' to X'FE' Reservados para métodos privados o X'FF' Métodos no aceptados por el servidor A nosotros el que nos interesará será el método 00, estamos buscando privacidad. Así que pasaremos directamente al siguiente punto, para los demás metódos deberiamos entrar en una subnegociación que dependería del método seleccionado. |--------------------------------------------------------------------------| |--------------------->3-Peticion de conexión------------------------------| |--------------------------------------------------------------------------| Después de la subnegociación de método y haber-nos autenticado en el server en los casos pertinentes o simplemente después de ser aceptado el método sin autenticación el cliente ya puede realizar peticiones al servidor del siguiente modo. +----+-----+-------+------+----------+----------+ |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | +----+-----+-------+------+----------+----------+ | 1 | 1 | X'00' | 1 | Variable | 2 | <--N Bytes +----+-----+-------+------+----------+----------+ Donde: o VER protocolo version: X'05' o CMD o CONNECT X'01' o BIND X'02' o UDP ASSOCIATE X'03' o RSV Reservado o ATYP Tipo de dirección o IP V4 address: X'01' o Nombre de dominio: X'03' o IP V6 address: X'04' o DST.ADDR Dirección Ip de destino o DST.PORT Puerto de destino El comando connect nos conectará al host de destino, el comando BIND es utilizado en los casos en los que nuestro proxy deberá recibir conexiones del host de destino y por último el comando UDP nos dá la posibilidad de realizar conexiones UDP. En el caso que especificaramos como tipo de dirección el nombre de dominio el primer byte deberá ser el número de bytes siguientes que definiran el nombre. El servidor nos responderá de la forma siguiente +----+-----+-------+------+----------+----------+ |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | +----+-----+-------+------+----------+----------+ | 1 | 1 | X'00' | 1 | Variable | 2 | <--N Bytes +----+-----+-------+------+----------+----------+ Where: o VER protocol version: X'05' o REP Campo de respuesta: o X'00' Conectado perfectamente o X'01' Error general del servidor socks (Normalmente debido a errores de protocolo) o X'02' Conexión no permitida por el servidor o X'03' Red inalcanzable o X'04' Host inalcanzable o X'05' Conección denegada o X'06' Tiempo de vida agotado o X'07' Comando no soportado o X'08' Tipo de dirección no aceptado o X'09' to X'FF' No asignados o RSV RESERVADO o ATYP Tipo de dirección BND.ADDR: Dirección BND.PORT: Puerto Si se ha conectado correctamente al host ya podemos enviar datos al proxy como si fuera nuestro host de destino, él se encargará de redireccionar el trafico. Resumiendo todo lo anterior para una conexión tcp típica sin autenticación nos quedaría así (lo expongo en décimal para no liar el asunto): Cliente: 510 -->Proto 5, 1 método, método 0 (sin autenticación) Servidor: 50 -->Proto 5, nos acepta el método 0 Cliente: 5101123421 -->Proto 5, 01 Conectar, 0 reservado, Direc Ipv4, Host destino: 1.2.3.4, puerto 21 Servidor: 5001123421 -->Proto 5, 0 Conectado al objetivo, 0 reservado, Direc Ipv4, Ip 1.2.3.4, puerto 21 Que no te extrañe si el servidor te responde una ip distinta a la que le hemos dicho que conecte, suele ocurrir pero la qüestión és que ya está conectado donde queriamos. A partir de ahora ya podemos enviarle datos como si fuera la víctima, digo el host objetivo :P |--------------------------------------------------------------------------| |--------------------->4-Conexiones UDP------------------------------------| |--------------------------------------------------------------------------| En el caso de que hayamos enviado una asociación UDP y esta haya sido aceptada por el servidor deberemos mandar la información con la estructura siguiente: +----+------+------+----------+----------+----------+ |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | +----+------+------+----------+----------+----------+ | 2 | 1 | 1 | Variable | 2 | Variable | +----+------+------+----------+----------+----------+ o RSV Reservado X'0000' o FRAG Número de paquete actual o ATYP Tipo de dirección o IP V4 address: X'01' o DOMAINNAME: X'03' o IP V6 address: X'04' o DST.ADDR Dirección destino o DST.PORT Puerto de destino o DATA Datos a enviar De este modo enviará el propio paquete al objetivo y las respuestas tendran la misma estructura. No tiene complicación lo dejo al aire para que pruebes para no hacer todavía mas aburrido el artículo. |--------------------------------------------------------------------------| |--------------------->5-Algo de seguridad---------------------------------| |--------------------------------------------------------------------------| És posible provocar un DOS a un servidor Socks5 estableciendo muchas conexiones al servidor y indicando como host objetivo el propio servidor. Para solucionar esto debes impedir las conexiones a tu propio host o limitar el número de conexiones des de una misma ip. Tambien seria aconsejable evitar conexiones des de otros proxys escaneando al cliente en busca de puertos abiertos comunes, estos suelen ser el 8080,1080 y 3128. Y evitar tambien conexiones a ellos, de este modo evitamos que el cliente construya cadenas de proxys. Si ya es extraño que un usuario sin animo de jodienda conecte a un proxy anónimo todavia más si necesita una cadena. Aparte de lo anterior lo típico, los overflows. La mayoria de bugs en servidores de este tipo que he podido ver són en el select enviando que sólo hay un método y enviar una larga lista de métodos o en la autenticación user/password. |--------------------------------------------------------------------------| |--------------------->5-Implementación de un cliente----------------------| |--------------------------------------------------------------------------| El siguiente módulo programado en visualbasic és el caso más simple de un cliente Socks5, es decir, sin autenticación y método connect. 'Socks5 Client '-Sin autenticación '-Sólo método connect '-Sólo ipv4 o hostname (hostname no testeado) ' 'Programmed by MazarD 'MazarD@gmail.com 'Puede modificar y redistribuir este codigo libremente siempre que haga referencia a la autor del mismo '-1..-9= Error '00=Conectando '01=Conectado y enviando método '02=Método aceptado '03=Enviando connect objetivo '04=Conectado al objetivo Type Socks5 'Estructura de datos que contendrá el estado de la conexión Estado As Integer 'Estado DescEstado As String 'Descripción End Type Public Sub Conectar_Proxy(ByRef Socket As Winsock, ByVal Proxy As String, ByVal port As Long, ByRef SocksEstado As Socks5) Dim Metodos(2) As Byte SocksEstado.Estado = 0 SocksEstado.DescEstado = "Cerrado" Socket.Connect Proxy, port 'Conectamos al proxy While Socket.State < 7 'Mientras esté conectando esperamos DoEvents Wend If Socket.State = 7 Then 'Si estamos conectados Metodos(0) = 5 'Proto 5 Metodos(1) = 1 '1 método Metodos(2) = 0 'Método 00=Sin autenticación Socket.SendData Metodos 'Enviamos el paquete SocksEstado.Estado = 1 'Cambiamos el estado y su descripción SocksEstado.DescEstado = "Method 0 sent" End If If Socket.State > 7 Then 'Si se ha producido un error lo decimos en la estructura SocksEstado.Estado = -1 SocksEstado.DescEstado = "Proxy Down" End If End Sub 'Esta función deberá estar en el evento data_arrival del socket Public Sub Conectar_Target(ByRef Socket As Winsock, ByVal DatoS As Variant, ByVal Hostip As String, ByVal EsDominio As Boolean, ByVal Puerto As Integer, ByRef SocksEstado As Socks5) Dim PacketC() As Byte Dim ip As Variant Dim ByteMen, ByteMay As Byte Dim n, n1 As Long If DatoS(1) = &H0 And SocksEstado.Estado < 3 Then 'Si se ha aceptado el método y no hemos enviado el comando connect SocksEstado.Estado = 2 SocksEstado.DescEstado = "Metode OK" 'Método aceptado If Puerto < 65535 And Puerto >= 0 Then 'Si el puerto está en el rango ByteMen = Puerto And &HFF 'Codificamos los dos bytes del puerto en orden de red ByteMay = (Puerto And &HFF00) / &H100 End If If not EsDominio Then 'Si no se trata de un nombre de dominio ReDim PacketC(9) 'Dimensionamos el tamaño del paquete ip = Split(Hostip, ".") 'Separamos los octetos de la ip PacketC(0) = 5 'proto v5 PacketC(1) = 1 'cmd Connect PacketC(2) = 0 'Rsv PacketC(3) = 1 'Type ipv4 PacketC(4) = ip(0) 'ip PacketC(5) = ip(1) PacketC(6) = ip(2) PacketC(7) = ip(3) PacketC(8) = ByteMay 'puerto PacketC(9) = ByteMen Socket.SendData PacketC 'Enviamos el paquete SocksEstado.Estado = 3 SocksEstado.DescEstado = "CmdConnect type 1 Sent" Else ReDim PacketC(Len(Hostip) + 7) As Byte 'Redimensionamos el paquete al nombre del dominio+ los bytes de control PacketC(0) = 5 'proto PacketC(1) = 1 'Cmd connect PacketC(2) = 0 'rsv PacketC(3) = 3 'Ipv4 PacketC(4) = Len(Hostip) 'Tamaño del nombre de dominio que sigue n1 = 5 For n = 1 To Len(Hostip) 'Pasamos a ascii el nombre de dominio PacketC(n1) = Asc(Mid(Hostip, n, 1)) n1 = n1 + 1 Next n PacketC(n1) = ByteMay 'puerto PacketC(n1 + 1) = ByteMen Socket.SendData PacketC SocksEstado.Estado = 3 SocksEstado.DescEstado = "CmdConnect type 3 Sent" End If End If End Sub La siguiente función nos informará de la respuesta del servidor y debe estar en el Data_arrival del socket Public Sub Socks5Reply(ByVal DatoS As Variant, ByRef SocksEstado As Socks5) On Error GoTo nostatE If SocksEstado.Estado = 3 Then 'Si ya hemos enviado el connect Select Case DatoS(1) 'REP del paquete de respuesta Case &H0 SocksEstado.Estado = 4 SocksEstado.DescEstado = "Target OK" Case &H1 SocksEstado.Estado = -2 SocksEstado.DescEstado = "General Socks Server Failure" Case &H2 SocksEstado.Estado = -3 SocksEstado.DescEstado = "Ruleset Proxy Error" Case &H3 SocksEstado.Estado = -4 SocksEstado.DescEstado = "Network Unreachable" Case &H4 SocksEstado.Estado = -5 SocksEstado.Estado = "Host Unreachable" Case &H5 SocksEstado.Estado = -6 SocksEstado.Estado = "Connection to target failed" Case &H6 SocksEstado.Estado = -7 SocksEstado.Estado = "TTL expired" Case &H7 SocksEstado.Estado = -8 SocksEstado.Estado = "Cmd not supported" Case &H8 SocksEstado.Estado = -9 SocksEstado.Estado = "Address not supported" End Select End If Exit Sub nostatE: SocksEstado.Estado = -10 SocksEstado.DescEstado = "Reply Error" End Sub |--------------------------------------------------------------------------| |--------------------->7-Links de interes----------------------------------| |--------------------------------------------------------------------------| ftp://ftp.rfc-editor.org/in-notes/rfc1928.txt -->El rfc del Socks5 http://www.aliveproxy.com --> Listas de Socks5 http://www.samair.ru/proxy/socks.htm --> Listas de Socks5 Para cualquier duda que te salga mandame un e-mail. ___ ___ _________ _______ ______ |_ \ / _| /\ /_____ _/ /\ |_ __ | |_ __ \ | \ / | / \ / / / \ | |__| | | | \ \ ____|_|\ \/ /|_|____/ /__\_______/_/_____/__\ \___|__ __|__|_|___\ \___ \_______\ /_______/ /__________//___________\ \_____\ \__________/ /__/ _| | \/ | |__/ /____\ \ _/ /_____/ /____\ \_| | \ \___| |__/ / |___| |___/__________\/________/__________\__| \___|______/ 11 No existe la verdad absoluta, cada uno elige su camino. MazarD [arroba] gmail [punto] com -----------------------------------------------------------------------------