Universal C# Proxy Server with FTP Authentication Support
This C# proxy server listens on a local port, detects traffic types, and forwards them with smart handling. For FTP, it automatically injects credentials by intercepting USER/PASS commands and swapping in your login details. It supports HTTP, HTTPS (via CONNECT), and FTP using only built-in TcpClient and NetworkStream—no external libraries needed.
Architecture and Initialization
The server uses TcpListener to monitor the loopback interface on your chosen port. FTP credentials are stored in a ConcurrentDictionary for thread-safe access.
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}");
}
}
Launch it from Program.Main:
static async Task Main(string[] args)
{
var proxy = new FullProxyServer(8888, "ftp.example.com", "my_username", "my_password");
await proxy.StartAsync();
}
Request Type Detection
After receiving client data, the buffer is analyzed:
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);
}
This routes traffic based on protocol.
Handling HTTPS via CONNECT
For HTTPS, it sets up a direct tunnel:
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);
Bidirectional stream copying is fully async with CancellationTokenSource for clean shutdowns.
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 with Auto-Authentication
The star feature: intercepting and tweaking FTP commands. When the client sends USER, it swaps in your username. On the server's 331 (password needed) response, it fires off PASS.
private async Task FtpTunnelWithAuth(NetworkStream clientStream, NetworkStream ftpStream,
string username, string password, string id)
{
bool authenticated = false;
// Intercept FTP server responses
if (!authenticated && response.Contains("331")) // Password requested
{
string passCmd = $"PASS {password}\r\n";
await ftpStream.WriteAsync(passBytes);
}
// Intercept client commands
if (!authenticated && command.ToUpper().StartsWith("USER"))
{
// Swap in our username
string userCmd = $"USER {username}\r\n";
await ftpStream.WriteAsync(userBytes);
}
}
Post-auth (230 response), all commands tunnel unchanged.
Client Configuration
- Browser: Set HTTP/HTTPS/FTP proxy to 127.0.0.1:8888
- FileZilla or similar: Generic Proxy, host 127.0.0.1, port 8888
Logs capture the flow:
[abc12345] FTP request
[abc12345] ->FTP: USER anonymous\r\n
[abc12345] FTP->: 331 User name okay, need password\r\n
[abc12345] Auto-sending password
[abc12345] FTP->: 230 User logged in\r\n
[abc12345] Authentication successful
Key Benefits
This lightweight server fits in a single file and leverages async/await for scalability. Perfect for:
- Bypassing proxy restrictions in corporate networks
- Automating FTP access without tweaking client settings
- Traffic debugging with detailed logging
- Extending to other protocols via command parsing
Key Takeaways
- Auto-swaps USER/PASS for FTP without client awareness.
- Async bidirectional tunneling with NetworkStream.
- Thread-safe credential storage via ConcurrentDictionary.
- Full HTTPS CONNECT and basic HTTP support.
- Cross-platform on .NET 5+.
— Editorial Team
No comments yet.