Serveur proxy universel C# avec support d'authentification FTP
Ce serveur proxy C# écoute sur un port local, détecte les types de trafic et les redirige avec une gestion intelligente. Pour FTP, il injecte automatiquement les identifiants en interceptant les commandes USER/PASS et en les remplaçant par vos propres informations de connexion. Il prend en charge HTTP, HTTPS (via CONNECT) et FTP en utilisant uniquement TcpClient et NetworkStream — aucune bibliothèque externe requise.
Architecture et initialisation
Le serveur utilise TcpListener pour surveiller l'interface loopback sur le port choisi. Les identifiants FTP sont stockés dans un ConcurrentDictionary pour un accès 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}");
}
}
Lancez-le depuis Program.Main :
static async Task Main(string[] args)
{
var proxy = new FullProxyServer(8888, "ftp.example.com", "my_username", "my_password");
await proxy.StartAsync();
}
Détection du type de requête
Après réception des données du client, le buffer est analysé :
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);
}
Cela route le trafic en fonction du protocole.
Gestion HTTPS via CONNECT
Pour HTTPS, il établit un tunnel direct :
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 copie de flux bidirectionnelle est entièrement asynchrone avec CancellationTokenSource pour des arrêts propres.
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 avec authentification automatique
La fonctionnalité phare : intercepter et modifier les commandes FTP. Quand le client envoie USER, il remplace par votre nom d'utilisateur. Sur la réponse 331 du serveur (mot de passe requis), il envoie PASS.
private async Task FtpTunnelWithAuth(NetworkStream clientStream, NetworkStream ftpStream,
string username, string password, string id)
{
bool authenticated = false;
// Intercepter les réponses du serveur FTP
if (!authenticated && response.Contains("331")) // Mot de passe requis
{
string passCmd = $"PASS {password}\r\n";
await ftpStream.WriteAsync(passBytes);
}
// Intercepter les commandes client
if (!authenticated && command.ToUpper().StartsWith("USER"))
{
// Remplacer par notre nom d'utilisateur
string userCmd = $"USER {username}\r\n";
await ftpStream.WriteAsync(userBytes);
}
}
Après authentification (réponse 230), toutes les commandes sont tunnelisées sans modification.
Configuration client
- Navigateur : Définir le proxy HTTP/HTTPS/FTP sur 127.0.0.1:8888
- FileZilla ou équivalent : Proxy générique, hôte 127.0.0.1, port 8888
Les logs capturent le flux :
[abc12345] Requête FTP
[abc12345] ->FTP: USER anonymous\r\n
[abc12345] FTP->: 331 Nom d'utilisateur correct, mot de passe requis\r\n
[abc12345] Envoi automatique du mot de passe
[abc12345] FTP->: 230 Utilisateur connecté\r\n
[abc12345] Authentification réussie
Avantages clés
Ce serveur léger tient dans un seul fichier et exploite async/await pour l'évolutivité. Idéal pour :
- Contourner les restrictions proxy en entreprise
- Automatiser l'accès FTP sans modifier les paramètres client
- Déboguer le trafic avec des logs détaillés
- Étendre à d'autres protocoles via l'analyse de commandes
Points clés à retenir
- Remplace automatiquement USER/PASS pour FTP sans que le client s'en rende compte.
- Tunnel bidirectionnel asynchrone avec NetworkStream.
- Stockage thread-safe des identifiants via ConcurrentDictionary.
- Support complet HTTPS CONNECT et HTTP de base.
- Multiplateforme sur .NET 5+.
— Editorial Team
Aucun commentaire pour le moment.