HAProxy + Acme Timeout Error



  • I have been trying to get this working all day with no luck. Hoping that posting here someone will be able to help me figure this out.

    Followed doktornotor's post https://forum.pfsense.org/index.php?topic=101186.msg690924#msg690924

    When I click renew/issue there is a timeout error in the logs. I also see an error in haproxy referencing the lua script.

    I tried to post as much information as possible; hoping someone has seen this before and can point me the right direction. I'm sure there is just some setting that I have wrong and it is something simple but I am not seeing it.

    Thanks for the help.

    acme_issuecert.log

    
    [Thu Nov 23 20:08:54 CST 2017] curl exists=0
    [Thu Nov 23 20:08:54 CST 2017] wget exists=127
    [Thu Nov 23 20:08:54 CST 2017] _CURL='curl -L --silent --dump-header /tmp/acme/pfsense.gateway//http.header '
    [Thu Nov 23 20:08:54 CST 2017] _ret='0'
    [Thu Nov 23 20:08:54 CST 2017] original='{
      "type": "urn:acme:error:malformed",
      "detail": "Unable to update challenge :: The challenge is not pending.",
      "status": 400
    }'
    [Thu Nov 23 20:08:54 CST 2017] responseHeaders='HTTP/1.1 100 Continue
    Expires: Fri, 24 Nov 2017 02:08:54 GMT
    Cache-Control: max-age=0, no-cache, no-store
    Pragma: no-cache
    
    HTTP/1.1 400 Bad Request
    Server: nginx
    Content-Type: application/problem+json
    Content-Length: 132
    Boulder-Requester: 5123731
    Replay-Nonce: lnZRLdr7724IkUOd53cly6xyTmn3z1-R2aoPk634CNM
    Expires: Fri, 24 Nov 2017 02:08:54 GMT
    Cache-Control: max-age=0, no-cache, no-store
    Pragma: no-cache
    Date: Fri, 24 Nov 2017 02:08:54 GMT
    Connection: close
    '
    [Thu Nov 23 20:08:54 CST 2017] response='{"type":"urn:acme:error:malformed","detail":"Unable to update challenge :: The challenge is not pending.","status": 400}'
    [Thu Nov 23 20:08:54 CST 2017] code='400'
    
    

    haproxy.cfg

    
    # Automaticaly generated, dont edit manually.
    # Generated on: 2017-11-23 19:46
    global
            maxconn                 1000
            stats socket /tmp/haproxy.socket level admin
            uid                     80
            gid                     80
            nbproc                  1
            chroot                  /tmp/haproxy_chroot
            daemon
            tune.ssl.default-dh-param       2048
            server-state-file /tmp/haproxy_server_state
            lua-load                /var/etc/haproxy/luascript_acme-http01-webroot.lua
    
    listen HAProxyLocalStats
            bind 127.0.0.1:#### name localstats
            mode http
            stats enable
            stats refresh 20
            stats admin if TRUE
            stats uri /haproxy/haproxy_stats.php?haproxystats=1
            timeout client 5000
            timeout connect 5000
            timeout server 5000
    
    frontend ACME-Challenege
            bind                    ###.###.###.### name ###.###.###.###:80
            mode                    http
            log                     global
            option                  http-keep-alive
            timeout client          30000
            acl                     url_acme_http01 path_beg -i /.well-known/acme-challenge/
            http-request use-service lua.acme-http01  if  METH_GET url_acme_http01
    
    

    acme-http01-webroot.lua

    
    -- ACME http-01 domain validation plugin for Haproxy 1.6+
    -- copyright (C) 2015 Jan Broer
    --
    
    acme = {}
    acme.version = "0.1.1"
    
    --
    -- Configuration
    --
    -- When HAProxy is *not* configured with the 'chroot' option you must set an absolute path here and pass
    -- that as 'webroot-path' to the letsencrypt client
    
    acme.conf = {
            ["non_chroot_webroot"] = ""
    }
    
    --
    -- Startup
    --
    acme.startup = function()
            core.Info("[acme] http-01 plugin v" .. acme.version);
    end
    
    --
    -- ACME http-01 validation endpoint
    --
    acme.http01 = function(applet)
            local response = ""
            local reqPath = applet.path
            local src = applet.sf:src()
            local token = reqPath:match( ".+/(.*)$" )
    
            if token then
                    token = sanitizeToken(token)
            end
    
            if (token == nil or token == '') then
                    response = "bad request\n"
                    applet:set_status(400)
                    core.Warning("[acme] malformed request (client-ip: " .. tostring(src) .. ")")
            else
                    auth = getKeyAuth(token)
                    if (auth:len() >= 1) then
                            response = auth .. "\n"
                            applet:set_status(200)
                            core.Info("[acme] served http-01 token: " .. token .. " (client-ip: " .. tostring(src) .. ")")
                    else
                            response = "resource not found\n"
                            applet:set_status(404)
                            core.Warning("[acme] http-01 token not found: " .. token .. " (client-ip: " .. tostring(src) .. ")")
                    end
            end
    
            applet:add_header("Server", "haproxy/acme-http01-authenticator")
            applet:add_header("Content-Length", string.len(response))
            applet:add_header("Content-Type", "text/plain")
            applet:start_response()
            applet:send(response)
    end
    
    --
    -- strip chars that are not in the URL-safe Base64 alphabet
    -- see https://github.com/letsencrypt/acme-spec/blob/master/draft-barnes-acme.md
    --
    function sanitizeToken(token)
            _strip="[^%a%d%+%-%_=]"
            token = token:gsub(_strip,'')
            return token
    end
    
    --
    -- get key auth from token file
    --
    function getKeyAuth(token)
            local keyAuth = ""
            local path = acme.conf.non_chroot_webroot .. "/.well-known/acme-challenge/" .. token
            local f = io.open(path, "rb")
            if f ~= nil then
                    keyAuth = f:read("*all")
                    f:close()
            end
            return keyAuth
    end
    
    core.register_init(acme.startup)
    core.register_service("acme-http01", "http", acme.http01)
    
    

    system.log

    
    Nov 23 19:46:51 gateway php-fpm[92184]: haproxy: reload old pid:39670
    Nov 23 19:46:51 gateway php-fpm[92184]: haproxy: started new pid:96805
    Nov 23 19:46:51 gateway php-fpm[92184]: haproxy: startup error output!: [info] 326/194651 (96259) : [acme] http-01 plugin v0.1.1
    
    

    Acme settings



  • Got it working today, firewall rule was blocking the traffic. Knew it would be something stupid that I missed.



  • @cplmayo:

    Got it working today, firewall rule was blocking the traffic. Knew it would be something stupid that I missed.

    Hello, im running in the exact same issue, could you so kind and share which firewall rule was blocking the traffic?