仅凭证书是否可以确定是否使用了HTTPS代理吗?

3
由于HTTPS代理服务器会替换SSL证书,那么如何确定给定的HTTPS连接是否有代理在中间?我将使用这些信息来确定我的应用程序策略,因为有些情况下我希望拥有100%的端到端加密隧道,不允许任何第三方解密。如果您能告诉我如何通过C#在.NET应用程序或Silverlight中确定这一点,那就更好了。首先,此处是使用.NET验证证书的示例方法,但我仍然不确定如何使用它来确定要验证的证书的哪个部分。此外,我认为ServicePointManger更像是一个“全局”连接类。在测试单个HTTP连接时使用可能太广泛了,并且我不确定ServicePointManager是否可在Silverlight中使用。

http://msdn.microsoft.com/en-us/library/bb408523.aspx


你的应用程序如何建立安全连接?使用WCF?还是HttpWebRequest? - Andy Wilson
我正在寻找一个通用解决方案,可以解决所有基于.NET的通信方法。是的,我正在使用WCF和HTTPWebRequest。 - makerofthings7
1个回答

4
您有两种选择。第一种选择是使用ServicePointManager类。您是正确的,它可以管理所有服务点,但是您可以在回调方法中使用“sender”参数来区分不同的服务点:
void SomeMethod()
{
    ServicePointManager.ServerCertificateValidationCallback += 
        ValidateServerCertificate;

    var url = "https://mail.google.com/mail/?shva=1#inbox";
    var request = (HttpWebRequest)WebRequest.Create(url);
    request.GetResponse();
}

private static bool ValidateServerCertificate(object sender, 
        X509Certificate certificate, X509Chain chain, 
        SslPolicyErrors sslpolicyerrors)
{
    if(sender is HttpWebRequest)
    {
        var request = (HttpWebRequest) sender;
        if(request.RequestUri.ToString() == "https://mail.google.com/mail/?shva=1#inbox")
        {
            return (certificate.GetPublicKeyString() == "The public key string you expect");
        }
    }
    return true;
}

这个选项适用于手动创建的HttpWebRequest和WCF创建的请求,因为“sender”对于两者都是HttpWebRequest。我不确定“sender”是否会是除了HttpWebRequest之外的其他内容。

第二个选项是直接从服务点获取证书:

void SomeMethod()
{
    ServicePointManager.ServerCertificateValidationCallback += 
        ValidateServerCertificate;

    var url = "https://mail.google.com/mail/?shva=1#inbox";
    var request = (HttpWebRequest)WebRequest.Create(url);
    request.GetResponse();

    var serverCert = request.ServicePoint.Certificate;
    // Validate the certificate.
}

我不确定是否可以获取由WCF代理使用的ServicePoint。如果不行,这个选项对于WCF就行不通了。除此之外,最大的区别在于第一种选项在证书验证失败时防止连接,而第二种方法在连接建立后才进行验证。

如果你只需要确定请求是否经过代理:

var httpRequest = (HttpWebRequest)WebRequest.Create("someurl");
var isUsingProxy = DoesRequstUseProxy(request);

bool DoesRequestUseProxy(HttpWebRequest request)
{
    if(request.Proxy == null)
    {
        return false;
    }

    return request.Proxy.GetProxy(request.RequestUri) != request.RequestUri;
}

谢谢,但是当我得到证书时,我仍需要弄清楚该如何处理它。是否没有通用的方法可以通过证书检测代理?我必须在我的应用程序中硬编码预期的公钥字符串吗?此外,我不确定这种方法是否适用于Silverlight...我怀疑我能否在SLI沙箱内获取ServicePointManager访问权限 - makerofthings7
如果防火墙使用"WCCP",那么DoesRequestUseProxy的方法将无法使用。WCCP是一种透明代理,不需要客户端配置。BlueCoat是一个产品的例子,它将与来自防火墙的所有数据进行交互,并透明地代理HTTPS流量。正因为如此,我认为唯一通用的方法是分析证书本身。 - makerofthings7
我更新了我的答案,展示如何检测网络请求是否使用代理。不幸的是,我刚刚确认我的答案中的代码都无法在Silverlight中运行。 - Andy Wilson
感谢您关注Silverlight的方法 :) - makerofthings7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接