最近遇见的几个问题

某服务后端server时不时的connection refused

前面是Nginx,后面是uwsgi,日志中时不时出现下面的内容

[error] 54#54: *1644 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.5, server: _, request: "POST /log HTTP/1.1", upstream: "http://[::1]:10000/log", host: "mgt-api"

找了好久也没找到原因,比较确定的是不是后面的uwsgi挂掉了,之后tcpdump抓包,发现每次出现问题的都是一个IPV6的地址,结合上面的日志恍然大悟,原来是Nginx反向代理写的是localhost而不是127.0.0.1,而且在host文件中是

127.0.0.1   localhost
::1             localhost

gethostbyname在多个IP的情况下,返回结果是随机的,导致有时候被解析到了IPV6的地址上了。

Django在https下增强的CSRF防护

某Django系统在POST的时候一直提示CSRF验证失败,即使看到的CSRFToken是没问题的,后来打开DEBUG看到提示,原因摘抄Django源码。

if request.is_secure():
    # Suppose user visits http://example.com/
    # An active network attacker (man-in-the-middle, MITM) sends a
    # POST form that targets https://example.com/detonate-bomb/ and
    # submits it via JavaScript.
    #
    # The attacker will need to provide a CSRF cookie and token, but
    # that's no problem for a MITM and the session-independent
    # nonce we're using. So the MITM can circumvent the CSRF
    # protection. This is true for any HTTP connection, but anyone
    # using HTTPS expects better! For this reason, for
    # https://example.com/ we need additional protection that treats
    # http://example.com/ as completely untrusted. Under HTTPS,
    # Barth et al. found that the Referer header is missing for
    # same-domain requests in only about 0.2% of cases or less, so
    # we can use strict Referer checking.
    referer = force_text(
        request.META.get('HTTP_REFERER'),
        strings_only=True,
        errors='replace'
    )
    if referer is None:
        return self._reject(request, REASON_NO_REFERER)

    referer = urlparse(referer)

    # Make sure we have a valid URL for Referer.
    if '' in (referer.scheme, referer.netloc):
        return self._reject(request, REASON_MALFORMED_REFERER)

    # Ensure that our Referer is also secure.
    if referer.scheme != 'https':
        return self._reject(request, REASON_INSECURE_REFERER)

    # If there isn't a CSRF_COOKIE_DOMAIN, assume we need an exact
    # match on host:port. If not, obey the cookie rules.
    if settings.CSRF_COOKIE_DOMAIN is None:
        # request.get_host() includes the port.
        good_referer = request.get_host()
    else:
        good_referer = settings.CSRF_COOKIE_DOMAIN
        server_port = request.get_port()
        if server_port not in ('443', '80'):
            good_referer = '%s:%s' % (good_referer, server_port)

    # Here we generate a list of all acceptable HTTP referers,
    # including the current host since that has been validated
    # upstream.
    good_hosts = list(settings.CSRF_TRUSTED_ORIGINS)
    good_hosts.append(good_referer)

    if not any(is_same_domain(referer.netloc, host) for host in good_hosts):
        reason = REASON_BAD_REFERER % referer.geturl()
        return self._reject(request, reason)

添加新评论