Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Letsencrypt acme-challenge on wordpress or asp.net mvc

I have been trying without success to generate security certificates for my company using Let's Encrypt. My company uses WordPress 3.9.7 for its main website and I am not allow to upgrade to a newer version since that is handled by a third party company. The website is running on top of Internet Information Services 7.5 on Windows Server 2008 R2. My question is: How can I make wordpress handle http://www.company.com/.well-known/acme-challenge/mftvrU2brecAXB76BsLEqW_SL_srdG3oqTQTzR5KHeA ? I have already created a new empty page and a new template that returns exactly what let's encrypt is expecting but wordpress keeps returning a 404 for that page. My guess is that the problem arise with the dot(.) at the beginning of the route (".well-known") but I don't know how to solve that on wordpress.

I am also able to use an asp.net mvc website and make IIS point to that website for a while. Not a good idea though since clients may not be able to reach our website for a few minutes, but still an option. Then the question is: How can I create a controller or a route with a dot(".") at the beginning of the name? Help will be really appreciated.

like image 285
zaidorx Avatar asked Jan 13 '16 15:01

zaidorx


1 Answers

For ASP.Net MVC or Web Forms, with certain Routing configs, you'll end up treating this URL as something for the Routing Engine to hand off to the MVC/Forms Handler, not a static file return. The result will be a 404 or a 503. The solution is surprisingly very simple:

If you haven't already, place the Challenge file:

  1. Create the necessary dirs - .well-known is tricky mostly because Microsoft is lazy, but you can either do it from cmdline or create the folder as .well-known. and Windows Explorer will notice the workaround and remove the trailing period for you.
  2. Inside \.well-known\acme-challenge place the challenge file with the proper name and contents. You can go about this part any way you like; I happen to use Git Bash like echo "oo0acontents" > abcdefilename

Then make a Web.Config file in the acme-challenge dir with these contents:

<?xml version = "1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <staticContent>
            <clear />
            <mimeMap fileExtension = ".*" mimeType="text/json" />
        </staticContent>

        <handlers>
            <clear />
            <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule" 
            resourceType="Either" requireAccess="Read" />  
        </handlers>
    </system.webServer>
</configuration>

Source: https://github.com/Lone-Coder/letsencrypt-win-simple/issues/37

Done. The file will start returning instead of 404/503 allowing the Challenge to complete - you can now Submit and get your domain validated.

Aside: The above code snippet sets the content-type to json, a historical requirement that is no longer relevant to letsencrypt. The current requirement is there is no requirement - you can send a content-type of pantsless/elephants and it'll still work.

More for Asp.Net

I like to redirect all HTTP requests back to HTTPS to ensure users end up on a secure connection even if they didn't know to ask. There are a lot of easy ways to do that, until you're using LetsEncrypt - because you're going to break requests for .well-known. You can setup a static method in a class, like this:

public static class HttpsHelper
{
    public static bool AppLevelUseHttps =
#if DEBUG
        false;
#else
        true;
#endif

    public static bool Application_BeginRequest(HttpRequest Request, HttpResponse Response)
    {
        if (!AppLevelUseHttps)
            return false;

        switch (Request.Url.Scheme)
        {
            case "https":
                return false;

#if !DEBUG
            case "http":
                var reqUrl = Request.Url;
                var pathAndQuery = reqUrl.PathAndQuery;
                // Let's Encrypt exception
                if (pathAndQuery.StartsWith("/.well-known"))
                    return false;
                // http://stackoverflow.com/a/21226409/176877
                var url = "https://" + reqUrl.Host + pathAndQuery;

                Response.Redirect(url, true);
                return true;
#endif
        }

        return false;
    }
}

Now that can do a great job of redirecting to HTTPS except when LetsEncrypt comes knocking. Tie it in, in Global.asax.cs:

    protected void Application_BeginRequest(object sender, EventArgs ev)
    {
        HttpsHelper.Application_BeginRequest(Request, Response);
    }

Notice that the bool returned is discarded here. You can use it if you like to decide whether to end the request/response immediately, true meaning, end it.

Finally, if you like, you can use the AppLevelUseHttps variable to turn off this behavior if need-be, for example to test if things are working without HTTPS. For example, you can have it set to the value of a Web.Config variable.

like image 141
Chris Moschini Avatar answered Nov 15 '22 00:11

Chris Moschini