Volver al inicio

Proxy en C# con autenticación FTP

Servidor proxy universal en C# compatible con HTTP, HTTPS y FTP con autenticación automática. Intercepta comandos USER/PASS, usa túnel asíncrono. Código completo e instrucciones de configuración para especialistas en TI.

Creación de proxy FTP en C# con autoautenticación
Advertisement 728x90

Servidor Proxy Universal en C# con Soporte para Autenticación FTP

Este servidor proxy en C# escucha en un puerto local, detecta los tipos de tráfico y los reenvía con un manejo inteligente. Para FTP, inyecta automáticamente las credenciales interceptando los comandos USER/PASS y sustituyéndolos por tus datos de login. Soporta HTTP, HTTPS (vía CONNECT) y FTP usando solo TcpClient y NetworkStream integrados, sin librerías externas.

Arquitectura e Inicialización

El servidor usa TcpListener para monitorear la interfaz de loopback en el puerto elegido. Las credenciales FTP se almacenan en un ConcurrentDictionary para acceso thread-safe.

public class FullProxyServer
{
    private readonly TcpListener _listener;
    private readonly ConcurrentDictionary<string, string> _ftpCredentials;
    
    public FullProxyServer(int proxyPort, string ftpServer, string ftpUser, string ftpPassword)
    {
        _listener = new TcpListener(IPAddress.Loopback, proxyPort);
        _ftpCredentials = new ConcurrentDictionary<string, string>();
        _ftpCredentials.TryAdd(ftpServer, $"{ftpUser}:{ftpPassword}");
    }
}

Lánzalo desde Program.Main:

Google AdInline article slot
static async Task Main(string[] args)
{
    var proxy = new FullProxyServer(8888, "ftp.example.com", "my_username", "my_password");
    await proxy.StartAsync();
}

Detección del Tipo de Solicitud

Tras recibir datos del cliente, se analiza el buffer:

string request = Encoding.ASCII.GetString(buffer, 0, bytesRead);

if (request.StartsWith("CONNECT"))
{
    await HandleConnectRequest(clientStream, request, id);
}
else if (request.Contains("FTP") || request.Contains("ftp"))
{
    await HandleFtpRequest(clientStream, buffer, bytesRead, id);
}
else
{
    await TunnelConnection(clientStream, buffer, bytesRead, id);
}

Esto enruta el tráfico según el protocolo.

Manejo de HTTPS vía CONNECT

Para HTTPS, establece un túnel directo:

Google AdInline article slot
var parts = connectLine.Split(' ');
string host = targetParts[0];
int port = int.Parse(targetParts[1]);

var targetClient = new TcpClient();
await targetClient.ConnectAsync(host, port);

string response = "HTTP/1.1 200 Connection Established\r\n\r\n";
await clientStream.WriteAsync(responseBytes);

await TunnelBidirectional(clientStream, targetStream, id);

La copia de streams bidireccional es completamente asíncrona con CancellationTokenSource para cierres limpios.

private async Task TunnelBidirectional(NetworkStream clientStream, NetworkStream targetStream, string id)
{
    var cts = new CancellationTokenSource();
    
    var clientToTarget = CopyDataAsync(clientStream, targetStream, id, "C->T", cts.Token);
    var targetToClient = CopyDataAsync(targetStream, clientStream, id, "T->C", cts.Token);
    
    await Task.WhenAny(clientToTarget, targetToClient);
    cts.Cancel();
}

Proxy FTP con Autenticación Automática

La función estrella: interceptar y modificar comandos FTP. Cuando el cliente envía USER, se sustituye por tu nombre de usuario. Ante la respuesta 331 del servidor (se necesita contraseña), se envía PASS automáticamente.

private async Task FtpTunnelWithAuth(NetworkStream clientStream, NetworkStream ftpStream,
                                      string username, string password, string id)
{
    bool authenticated = false;
    
    // Interceptar respuestas del servidor FTP
    if (!authenticated && response.Contains("331")) // Se solicita contraseña
    {
        string passCmd = $"PASS {password}\r\n";
        await ftpStream.WriteAsync(passBytes);
    }
    
    // Interceptar comandos del cliente
    if (!authenticated && command.ToUpper().StartsWith("USER"))
    {
        // Sustituir por nuestro usuario
        string userCmd = $"USER {username}\r\n";
        await ftpStream.WriteAsync(userBytes);
    }
}

Tras la autenticación (respuesta 230), todos los comandos se tunelizan sin cambios.

Google AdInline article slot

Configuración del Cliente

  • Navegador: Configura el proxy HTTP/HTTPS/FTP en 127.0.0.1:8888
  • FileZilla o similar: Proxy genérico, host 127.0.0.1, puerto 8888

Los logs capturan el flujo:

[abc12345] Solicitud FTP
[abc12345] ->FTP: USER anonymous\r\n
[abc12345] FTP->: 331 Nombre de usuario correcto, necesita contraseña\r\n
[abc12345] Envío automático de contraseña
[abc12345] FTP->: 230 Usuario conectado\r\n
[abc12345] Autenticación exitosa

Ventajas Principales

Este servidor ligero cabe en un solo archivo y aprovecha async/await para escalabilidad. Ideal para:

  • Saltarse restricciones de proxy en redes corporativas
  • Automatizar acceso FTP sin modificar configuraciones del cliente
  • Depurar tráfico con logs detallados
  • Extender a otros protocolos mediante análisis de comandos

Conclusiones Clave

  • Sustitución automática de USER/PASS para FTP sin que el cliente lo note.
  • Tunelización bidireccional asíncrona con NetworkStream.
  • Almacenamiento thread-safe de credenciales vía ConcurrentDictionary.
  • Soporte completo para HTTPS CONNECT y HTTP básico.
  • Multiplataforma en .NET 5+.

— Editorial Team

Advertisement 728x90

Leer después