嗨,我有一个非常奇怪的问题,托管公司告诉我不可能,我希望你们能提供帮助。

我有一个nginx /清漆,它充当负载平衡器和缓存,位于我的Web服务器前面。我的Web服务器是标准的Apache Web服务器。

我在检测连接到系统的用户的真实IP地址时遇到问题。 $ _SERVER [“ REMOTE_ADDR”]显示负载平衡器/缓存的IP地址,而不显示访问站点的用户的IP地址。

我们编写了一个技巧,以便使用HTTP流量通过具有正确IP地址的X-Forwarded-For标头发送邮件,但有人告诉我SSL无法实现。

不幸的是,由于严格的安全性要求,我们无法将SSL卸载到必须运行的负载均衡器/缓存中。

有没有人对使用SSL时如何检测IP地址有任何想法?

谢谢你的帮助

-VCL配置-

import std;

C{
        #include <stdlib.h>
}C



sub vcl_recv {
/* Add X-Forwarded-For header */
    if (req.restarts == 0) {
        if (req.http.X-Forwarded-For) {
            set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
        } else {
            set req.http.X-Forwarded-For = client.ip;
        }
    }



    /* Fix compression */
    if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(ico|png|jpe?g|gif|xpm|swf|flv|pdf|mp3|ogg|zip|gz|tgz|bz2|xz|7z)$") {
            remove req.http.Accept-Encoding;
        } else if (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } else if (req.http.Accept-Encoding ~ "deflate") {
            set req.http.Accept-Encoding = "deflate";
        } else {
            remove req.http.Accept-Encoding;
        }
    }

    /* Handle SSL offloading */
    if (client.ip == "127.0.0.1") {
        std.log("SSL offloading detected " + client.ip + " " + req.http.X-Real-IP);
        set client.identity = req.http.X-Real-IP;
    } else {
        set client.identity = client.ip;
    }

    if (req.http.Cookie) {
       set client.identity = req.http.Cookie;
    }


    set req.http.X-Varnish-XID = req.xid;
    set req.backend = lb231;

    if (req.backend.healthy) {
        set req.grace = 30s;
    } else {
        set req.grace = 1h;
    }

        call normalise_user_agent;

    if (req.request == "PURGE") {
        if (!client.ip ~ purge) {
            error 405 "Not allowed.";
        }
        return(lookup);
    }

    if (req.request != "GET" &&
       req.request != "HEAD" &&
       req.request != "PUT" &&
       req.request != "POST" &&
       req.request != "TRACE" &&
       req.request != "OPTIONS" &&
       req.request != "DELETE") {
        return (pipe);
    }

    if (req.http.Cookie) {
                set req.http.Cookie = ";" + req.http.Cookie;
                set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
                set req.http.Cookie = regsuball(req.http.Cookie, ";(PHPSESSID)=", "; \1="); # Cookies to keep here
                set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
                set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");

                if (req.http.Cookie == "") {
                        remove req.http.Cookie;
                }
    }

    if (req.request != "GET" && req.request != "HEAD") {
         return (pass);
    }


    if (req.url ~ "/nocache") {
        set req.http.X-No-Cache = "true";
        return (pass);
    }

    if (req.request == "BAN") {
        if (client.ip ~ purge) {
            error 401 "Forbidden";
        }
        ban("req.http.Host == " + req.http.X-VCL-Ban-Host + " && req.url ~ " + req.http.X-VCL-Ban-URL);
        error 200 "Ban OK " + req.url + " " + req.http.Host;
    }

    if (req.request == "REFRESH") {
        set req.request = "GET";
        set req.hash_always_miss = true;
    }

    if (req.request != "GET" && req.request != "HEAD") {
        return (pass);
    }

    return (lookup);
}


    if (beresp.status >= 400) {
        /* Cache error pages for a short amount of time */
        set beresp.ttl = 5s;
        set beresp.grace = 5s;
        set beresp.http.Cache-Control = "max-age=5, must-revalidate";
        unset beresp.http.Cookie;
        unset beresp.http.Set-Cookie;
    }

    if (beresp.status == 503) {
        /* Do not cache 503s at all */
        set beresp.ttl = 0s;
        set beresp.http.Cache-Control = "no-store, no-cache, must-revalidate";
        set beresp.http.Pragma = "no-cache";
    }

     if (beresp.http.X-Varnish-TTL) {
        C{
            char *ttl;
            ttl = VRT_GetHdr(sp, HDR_BERESP, "\016X-Varnish-TTL:");
            VRT_l_beresp_ttl(sp, atoi(ttl));
        }C
        #unset beresp.http.X-Varnish-TTL;
    } else {
        set beresp.ttl = 0s;
    }

    if (beresp.ttl <= 0s) {
        set beresp.http.X-Cacheable = "No, not cacheable.";
    } elsif (req.http.Cookie ~ "(UserID|_session)") {
        set beresp.http.X-Cacheable = "No, got session.";
        return(hit_for_pass);
    } elsif (beresp.http.Cache-Control ~ "private") {
        set beresp.http.X-Cacheable = "No, Cache-Control=private";
        return(hit_for_pass);
    } else {
        set beresp.http.X-Cacheable = "Yes.";
        set beresp.grace = 1h;
    }
}

sub vcl_deliver {
    if (resp.http.reset-client-side-age) {
       unset resp.http.reset-client-side-age;
       set resp.http.Age = "0";
    }

    if (obj.hits > 0) {
        set resp.http.X-Cache = "Hit";
        set resp.http.X-Cache-Hits = obj.hits;
    } else {
        set resp.http.X-Cache = "Miss";
    }

    if (resp.http.Server == "Varnish") {
        set resp.http.Server = "OnCommerce Framework Ltd";
    }

    unset resp.http.X-Varnish;
    unset resp.http.X-Scrubbed-For;
}

sub vcl_hit {
    if (req.request == "PURGE") {
        purge;
        error 200 "Purged.";
    }
}

sub vcl_miss {
    if (req.request == "PURGE") {
        purge;
        error 200 "Purged.";
    }
}

sub vcl_pipe {
    set bereq.http.Connection = "close";
}

sub vcl_error {

}

sub normalise_user_agent
{
                if(req.http.user-agent ~ "Mobile"){
                                set req.http.X-UA = "mobile";
                }
                else if (req.http.user-agent ~ "Android")
                {
                                set req.http.X-UA = "android";
                }
                else if (req.http.user-agent ~ "Opera Mini/")
                {
                                set req.http.X-UA = "mobile";
                }
                else if (req.http.user-agent ~ "Opera Mobi/")
                {
                                set req.http.X-UA = "mobile";
                }
                else if (req.http.user-agent ~ "iP(ad|od|hone)/")
                {
                                set req.http.X-UA = "iOS";
                }
                else if (req.http.user-agent ~ "MSIE/")
                {
                                if(req.http.user-agent ~ "MSIE\s[1-7]/")
                                {
                                                set req.http.X-UA = "desktop-old";
                                }
                                else
                                {
                                                set req.http.X-UA = "desktop";
                                }
                }
                else if (req.http.user-agent ~ "Chrome/")
                {
                                set req.http.X-UA = "desktop";
                }
                else if (req.http.user-agent ~ "Firefox/")
                {
                                set req.http.X-UA = "desktop";
                }
                else if (req.http.user-agent ~ "Waterfox/")
                {
                                set req.http.X-UA = "desktop";
                }
                else if (req.http.user-agent ~ "Safari/")
                {
                                set req.http.X-UA = "desktop";
                }
                else if (req.http.user-agent ~ "Opera/")
                {
                                set req.http.X-UA = "desktop";
                }
                else if (req.http.user-agent ~ "curl/")
                {
                                set req.http.X-UA = "desktop";
                }
                else
                {
                                set req.http.X-UA = req.http.user-agent;
                }
}

最佳答案

在我的default.vcl文件中,我以这种方式重写了“ X-Forwarded-For”标头:

sub vcl_recv {

    # your code

    remove req.http.X-Forwarded-For;
    set req.http.X-Forwarded-For = client.ip;

    # your code again
}


不知道这是否是您所指的hack,但是这种方式对我们有用。删除实际的标头很重要,这样它就不会像新标头那样被传输。

我们有CloudFlare + Varnish,一切似乎都正常!

08-04 14:57