使用共享 IP 地址从 IIS 站点发出出站 Web 请求时失败

outbound web requests fail when made from IIS sites using shared IP address

任何人对如何使这项工作或可能出现的问题有任何想法?

托管服务器上的网络跟踪:

来自具有非共享 IP 地址的站点的成功请求:

No.     Time            Source                Destination           Protocol Info
   6366 15:54:35.590463 192.168.1.76          173.194.77.121        HTTP     GET /key/value/one/two HTTP/1.1 
   6369 15:54:35.599879 173.194.77.121        192.168.1.76          TCP      http > 55407 [ACK] Seq=1 Ack=110 Win=344 Len=0
   6370 15:54:35.621587 173.194.77.121        192.168.1.76          HTTP     HTTP/1.1 200 OK  (application/json)
   6608 15:54:35.815774 192.168.1.76          173.194.77.121        TCP      55407 > http [ACK] Seq=110 Ack=357 Win=509 Len=0

使用共享 IP 地址的站点请求失败:

No.     Time            Source                Destination           Protocol Info
   9720 15:54:39.244192 192.168.1.80          173.194.77.121        HTTP     GET /key/value/one/two HTTP/1.1 
   9760 15:54:39.256958 173.194.77.121        192.168.1.80          TCP      [TCP segment of a reassembled PDU]
   9761 15:54:39.256962 173.194.77.121        192.168.1.80          HTTP     HTTP/1.1 404 Not Found  (text/html)
   9762 15:54:39.257027 192.168.1.80          173.194.77.121        TCP      55438 > http [ACK] Seq=212 Ack=1676 Win=512 Len=0

代码:

public static HttpWebRequest CreateWebRequest(string url, string method = "GET", string referer = null, string contentType = null, int timeout = 100000, string authentication = null, string bindToIpAddress = null, string host = null)
{
    var request = (HttpWebRequest)WebRequest.Create(url);

    if (!string.IsNullOrWhiteSpace(bindToIpAddress))
    {
        IPAddress bindIp;
        if (!IPAddress.TryParse(bindToIpAddress, out bindIp))
        {
            throw new ArgumentException("bindToIpAddress");
        }

        request.ServicePoint.BindIPEndPointDelegate = ((sp, rep, rc) =>
        {
            return new IPEndPoint(bindIp, 0);
        });
    }

    request.Accept = "*/*";
    request.ContentType = contentType;
    request.Referer = referer;
    request.Method = method;
    request.Timeout = timeout;

    if (!string.IsNullOrWhiteSpace(host))
    {
        request.Host = host;
    }

    return request;
}

string GetData()
{
    try
    {
        string result;

        var request = CreateWebRequest("http://jsonplaceholder.typicode.com/posts/1", 
                                       "GET", 
                                       "somedomain.com", 
                                       timeout: (10 * 1000), 
                                       bindToIpAddress: "192.168.27.133" /*site IP*/);

        request.Accept = "application/json";

        using (var response = request.GetResponse())
        {
            using (var sr = new StreamReader(response.GetResponseStream()))
            {
                result = sr.ReadToEnd();
            }
        }

        return result;
    }
    catch (Exception ex)
    {
        return null;
    }
}

404 响应从远程站点返回,因此远程站点无法处理您的请求,这与您本地服务器上发生的事情无关。

从远程站点的角度来看,唯一的区别是发件人的 IP 地址,因此必须将其配置为仅接受来自特定 IP 地址的请求。此限制可能在远程服务器或两者之间的任何防火墙、路由器或代理中。

这原来是我们应用程序中的一个错误。在某些情况下,主机 header(请求中的主机 属性)设置不正确(hosting/source 站点的主机名)。问题中精简的代码示例未显示。对于忽略 header 的 Web 服务来说很好,但对于其他 而不是 忽略 header 的服务来说是一个问题(404 响应)。该问题与 IIS 或共享 IP 地址无关。感谢大家的回复。