.net 如何为Amazon简单电子邮件服务启用TLS 1.1/1.2

.net 如何为Amazon简单电子邮件服务启用TLS 1.1/1.2,.net,amazon-web-services,amazon-ses,.net,Amazon Web Services,Amazon Ses,多年来,我一直在使用亚马逊SES成功发送电子邮件。但是,出于PCI合规性原因,我们一直在尝试禁用TLS 1.0: System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; 但是,在尝试发送电子邮件时,这会导致异常: AuthenticationException: A call to SSPI failed, s

多年来,我一直在使用亚马逊SES成功发送电子邮件。但是,出于PCI合规性原因,我们一直在尝试禁用TLS 1.0:

System.Net.ServicePointManager.SecurityProtocol = 
    SecurityProtocolType.Tls11 | 
    SecurityProtocolType.Tls12;
但是,在尝试发送电子邮件时,这会导致异常:

AuthenticationException:
    A call to SSPI failed, see inner exception.
    The client and server cannot communicate, because they do not 
    possess a common algorithm
一旦我将SecurityProtocolType.Tls添加回,这再次成功。 在.NET4.5和4.6中都会发生。
使用AWSSDK SimpleMail(v3.1.1.1)和AWSSDK核心运行时(v3.1.2.1)

回答我自己的问题:
我们使TLS1.0客户端处于启用状态,而TLS1.0服务器处于禁用状态。这使得SSLLAB和PCI检查很开心,同时仍然允许我们连接到Amazon SES发送电子邮件。以下是我们使用的代码:

    private static Tuple<string, string, bool>[] s_ProtocolConfig = 
    {
        Tuple.Create("SSL 2.0", "client", false),
        Tuple.Create("SSL 2.0", "server", false),
        Tuple.Create("SSL 3.0", "client", false),
        Tuple.Create("SSL 3.0", "server", false),
        Tuple.Create("TLS 1.0", "client", true),    // Leave this to TRUE, so that we can send outgoing email.
        Tuple.Create("TLS 1.0", "server", false),   // Change this to disable incoming 1.0 TLS requests
        Tuple.Create("TLS 1.1", "client", true),
        Tuple.Create("TLS 1.1", "server", true),
        Tuple.Create("TLS 1.2", "client", true),
        Tuple.Create("TLS 1.2", "server", true),
    };

    /// <summary>
    /// Disable/Enable Protocole
    /// require a reboot if the values are changed.
    /// </summary>
    private static bool ConfigureProtocols(IEnumerable<Tuple<string, string, bool>> config)
    {
        bool rebootRequired = false;
        using (RegistryKey protocols = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols", true))
        {
            foreach (Tuple<string, string, bool> proto in config)
            {
                string protocol = proto.Item1;
                string clientServer = proto.Item2;
                bool enabled = proto.Item3;

                using (RegistryKey group = protocols.CreateSubKey(protocol))
                {
                    bool added = group.OpenSubKey(clientServer) == null;

                    using (RegistryKey newKey = group.CreateSubKey(clientServer))
                    {
                        bool updated = EnsureValue(newKey, "disabledbydefault", !enabled);
                        updated |= EnsureValue(newKey, "enabled", enabled);
                        newKey.Close();

                        if (!added && updated)
                        {
                            // the values have changed. Reboot is required to have them be reflected
                            rebootRequired = true;
                        }
                        if (added && !enabled)
                        {
                            // lack of added key is the same as enabled.
                            // therefore was enabled, but we need disabled = reboot required
                            rebootRequired = true;
                        }
                    }
                    group.Close();
                }
            }
            protocols.Close();
        }
        return rebootRequired;
    }

    private static bool EnsureValue(RegistryKey key, string name, bool value)
    {
        object currentValue = key.GetValue(name);
        object expectedValue = value ? 1 : 0;
        if (currentValue == null || !object.Equals(currentValue, expectedValue))
        {
            key.SetValue(name, expectedValue);
            return true;
        }
        return false;
    }
private static Tuple[]s\u ProtocolConfig=
{
Tuple.Create(“SSL 2.0”,“客户端”,false),
创建(“SSL 2.0”,“服务器”,false),
Tuple.Create(“SSL 3.0”,“客户端”,false),
Tuple.Create(“SSL 3.0”,“服务器”,false),
Create(“tls1.0”,“client”,true),//将其保留为true,以便我们可以发送传出电子邮件。
Create(“TLS 1.0”,“server”,false),//将其更改为禁用传入的1.0 TLS请求
Tuple.Create(“TLS1.1”,“客户机”,true),
Tuple.Create(“TLS1.1”,“server”,true),
Tuple.Create(“TLS1.2”,“客户机”,true),
Tuple.Create(“TLS1.2”,“server”,true),
};
/// 
///禁用/启用协议
///如果值发生更改,则需要重新启动。
/// 
专用静态布尔配置协议(IEnumerable配置)
{
bool REBOTOREQUIRED=错误;
使用(RegistryKey protocols=Registry.LocalMachine.OpenSubKey(@“SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\protocols”,true))
{
foreach(配置中的元组协议)
{
字符串协议=proto.Item1;
字符串clientServer=proto.Item2;
bool enabled=proto.Item3;
使用(RegistryKey组=protocols.CreateSubKey(protocol))
{
bool added=group.OpenSubKey(clientServer)==null;
使用(RegistryKey newKey=group.CreateSubKey(clientServer))
{
bool updated=重新评估(newKey,“disabledbydefault”,!enabled);
更新的|=重新评估(新键,“已启用”,已启用);
newKey.Close();
如果(!已添加和更新)
{
//值已更改。需要重新启动才能反映这些值
rebootRequired=true;
}
如果(添加并启用)
{
//缺少添加的密钥与启用的密钥相同。
//因此已启用,但我们需要禁用=需要重新启动
rebootRequired=true;
}
}
group.Close();
}
}
协议。关闭();
}
返回所需的重新引导;
}
私有静态bool值(注册表项、字符串名、bool值)
{
对象currentValue=key.GetValue(名称);
对象expectedValue=值?1:0;
if(currentValue==null | |!object.Equals(currentValue,expectedValue))
{
key.SetValue(名称,expectedValue);
返回true;
}
返回false;
}

Wild stab:如果只配置1.1或1.2,而不是两者都配置,会发生什么?好主意,但不幸的是,没有唯一的SecurityProtocolType.Tls似乎可以工作。我今天遇到了同样的问题,这是升级到最新的PayPal SDK导致的,它似乎关闭了.NET应用程序中的Tls v1.0支持(以影响其他SDK的方式)。我在AWS SES论坛上提出了这个问题,我希望这是一个很好的提问和获得AWS官方答复的地方@你找到解决办法了吗?我遇到了同样的问题。@我也遇到了同样的问题,你找到解决方案了吗?我知道我参加聚会迟到了,但我只是出于PCI合规性原因禁用了TLS 1.0,并且在尝试向SES发送电子邮件时遇到了这个问题。我已经为客户端启用了TLS 1.0,但我可能会通过使用以下页面在Amazon中禁用TLS 1.0永久禁用: