返回首页

C# 上的 FTP 认证代理

C# 通用代理服务器支持 HTTP、HTTPS 和 FTP,带有自动认证。拦截 USER/PASS 命令,使用异步隧道。完整代码和为 IT 专家提供的设置说明。

使用 C# 创建带有自动认证的 FTP 代理
Advertisement 728x90

支持 FTP 认证的通用 C# 代理服务器

这个 C# 代理服务器监听本地端口,自动识别流量类型,并智能转发。对于 FTP,它会拦截 USER/PASS 命令,自动注入你的登录凭证。只需使用内置的 TcpClient 和 NetworkStream,无需外部库,支持 HTTP、HTTPS(通过 CONNECT)和 FTP。

架构与初始化

服务器使用 TcpListener 监听指定端口的回环接口。FTP 凭证存储在 ConcurrentDictionary 中,确保线程安全。

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}");
    }
}

从 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();
}

请求类型检测

接收客户端数据后,分析缓冲区:

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);
}

根据协议路由流量。

通过 CONNECT 处理 HTTPS

对于 HTTPS,建立直接隧道:

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);

双向流复制完全异步,使用 CancellationTokenSource 实现优雅关闭。

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 代理与自动认证

核心功能:拦截并修改 FTP 命令。客户端发送 USER 时,替换为你的用户名;服务器返回 331(需密码)时,自动发送 PASS。

private async Task FtpTunnelWithAuth(NetworkStream clientStream, NetworkStream ftpStream,
                                      string username, string password, string id)
{
    bool authenticated = false;
    
    // 拦截 FTP 服务器响应
    if (!authenticated && response.Contains("331")) // 请求密码
    {
        string passCmd = $"PASS {password}\r\n";
        await ftpStream.WriteAsync(passBytes);
    }
    
    // 拦截客户端命令
    if (!authenticated && command.ToUpper().StartsWith("USER"))
    {
        // 替换为我们的用户名
        string userCmd = $"USER {username}\r\n";
        await ftpStream.WriteAsync(userBytes);
    }
}

认证成功(230 响应)后,所有命令直接透传。

Google AdInline article slot

客户端配置

  • 浏览器:将 HTTP/HTTPS/FTP 代理设置为 127.0.0.1:8888
  • FileZilla 等工具:通用代理,主机 127.0.0.1,端口 8888

日志记录流程:

[abc12345] FTP 请求
[abc12345] ->FTP: USER anonymous\r\n
[abc12345] FTP->: 331 用户名正确,需要密码\r\n
[abc12345] 自动发送密码
[abc12345] FTP->: 230 用户登录成功\r\n
[abc12345] 认证成功

主要优势

这个轻量级服务器单文件实现,利用 async/await 确保高可扩展性。完美适用于:

  • 绕过企业网络代理限制
  • 无需修改客户端设置自动访问 FTP
  • 带详细日志的流量调试
  • 通过命令解析扩展其他协议

核心要点

  • FTP USER/PASS 自动替换,客户端无感知。
  • NetworkStream 异步双向隧道。
  • ConcurrentDictionary 线程安全凭证存储。
  • 完整支持 HTTPS CONNECT 和基本 HTTP。
  • .NET 5+ 跨平台。

— Editorial Team

Advertisement 728x90

继续阅读