Univerzální proxy server v C# s podporou FTP autentizace
Proxy server v C# přijímá připojení na lokálním portu, určuje typ trafficu a přesměruje jej s zpracováním. Pro FTP je implementována automatická substituce přihlašovacích údajů: přerušování příkazů USER/PASS a nahrazení předdefinovaným loginem/heslem. Podporovány jsou HTTP, HTTPS (metoda CONNECT) a FTP bez externích knihoven, pouze TcpClient a NetworkStream.
Architektura a inicializace
Server používá TcpListener pro naslouchání na Loopback na specifikovaném portu. Přihlašovací údaje FTP jsou uloženy v ConcurrentDictionary pro vláknově bezpečný přístup.
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}");
}
}
Spuštění v Program.Main:
static async Task Main(string[] args)
{
var proxy = new FullProxyServer(8888, "ftp.example.com", "my_username", "my_password");
await proxy.StartAsync();
}
Určení typu požadavku
Po přijetí dat od klienta je analyzován 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);
}
To umožňuje směrování trafficu podle protokolu.
Zpracování HTTPS přes CONNECT
Pro HTTPS je nastaven přímý tunel:
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);
Obousměrné kopírování proudů je implementováno asynchronně s CancellationTokenSource pro elegantní ukončení.
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();
}
FTP-proxy s automatickou autentizací
Klíčová funkčnost – přerušování a modifikace FTP příkazů. Po obdržení USER od klienta je substituováno specifikované uživatelské jméno, na 331 (password required) – je odeslán PASS.
private async Task FtpTunnelWithAuth(NetworkStream clientStream, NetworkStream ftpStream,
string username, string password, string id)
{
bool authenticated = false;
// Přerušujeme odpovědi FTP-serveru
if (!authenticated && response.Contains("331")) // Požadavek na heslo
{
string passCmd = $"PASS {password}\r\n";
await ftpStream.WriteAsync(passBytes);
}
// Přerušujeme příkazy klienta
if (!authenticated && command.ToUpper().StartsWith("USER"))
{
// Nahrazujeme login na náš
string userCmd = $"USER {username}\r\n";
await ftpStream.WriteAsync(userBytes);
}
}
Následující příkazy jsou tunelovány bez změn po úspěšné autentizaci (230).
Nastavení klientů
- Prohlížeč: HTTP/HTTPS/FTP proxy — 127.0.0.1:8888
- FileZilla nebo analog: Generic Proxy, host 127.0.0.1, port 8888
Logy zobrazují proces:
[abc12345] FTP požadavek
[abc12345] ->FTP: USER anonymous\r\n
[abc12345] FTP->: 331 User name okay, need password\r\n
[abc12345] Automatické odeslání hesla
[abc12345] FTP->: 230 User logged in\r\n
[abc12345] Autentizace úspěšná
Výhody implementace
Server je lehký, vejde se do jednoho souboru, používá async/await pro škálovatelnost. Vhodný pro:
- Obcházení proxy omezení v korporátních sítích
- Automatizaci přístupu k FTP bez změny nastavení klientů
- Debugování trafficu s logováním
- Rozšíření pro další protokoly s analýzou příkazů
Co je důležité
- Automatická náhrada USER/PASS pro FTP bez upozornění klienta.
- Asynchronní obousměrné tunelování s NetworkStream.
- Vláknově bezpečné ukládání credentials v ConcurrentDictionary.
- Podpora HTTPS CONNECT a jednoduchého HTTP.
- Křížová platformnost na .NET 5+.
— Editorial Team
Zatím žádné komentáře.