{"tag":"letsencrypt","articles":{"blog\/technology\/cleaning-up-outdated-subdomains":{"key":"blog\/technology\/cleaning-up-outdated-subdomains","type":"article","published":true,"meta":{"createdAt":"2019-08-28T14:40:42+02:00","publishedAt":"2019-08-28T18:39:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"cleaning-up-outdated-subdomains"},"content":{"en":{"slug":"cleaning-up-outdated-subdomains","title":"Cleaning up outdated subdomains","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/askara-redirect_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022184.02266288952\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAANCAYAAADBo8xmAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABb0lEQVQ4jc2UTU8bMRCGn7E9m0AI0A\/1V8CF8v8R50rlzK23HqoiEbJBu2vP9BASbZKlqqKA+lw8tuzxOx+23P\/46eC4g6pSL2qqqiJIAGA0HgNQSmY2m3E0PqK\/P6liJTOmYzKZUMxIMXF8coyZ8ev3Iw+zOTEmqqoiqa79mTn6Ml8hbdu6quLuywWRvez+COxtSy7F+Y8QX4X6Qu46bm5uCSly\/fWKu2\/f+fD5nFiNyE2L46gmLi4u30aQme1kqJ7P0dGISpVFvcDciDHSNg2IEEJgOp0uHfTKdwjS9oK7kc0oz8+0TUvTNKSUyF1HCJHTs9ODi+izW7KceXqaE1OkdB2mE4yAsGw8c4hByOYY8OUkkOJOXK8272usm3pbkLu\/WfRDiMjGCx0sWV0vcDfMQAQESEkppQDLLJWcCcD5p48bwez77NcCtzM0xNDB\/j90CEErOwxd8jdhQ3sOWeK1oL7T9+6jDUH\/kpX35A+PhxaIl\/hdhgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/askara-redirect_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022184.02266288952\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFor quite a while my VPS was misconfigured \u2013 any HTTP requests it got but couldn\u2019t assign to a vhost, it redirected to the main website, \u003Ca href=\u0022https:\/\/avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E avris.it\u003C\/a\u003E. I didn\u2019t think it would be a big deal, until I recently found out that my post \u003Ca href=\u0022\/blog\/ungoogling\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Ungoogling\u003C\/a\u003E is indexed by Google under \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022\u003Ehttps:\/\/askara.avris.it\/blog\/ungoogling\u003C\/a\u003E\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EThis subdomain hadn\u2019t existed for a long time already, my server doesn\u2019t serve a certificate for it anymore, but it requires \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/HTTP_Strict_Transport_Security\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E HSTS\u003C\/a\u003E, so browsers end up showing users a scary error message.\u003C\/p\u003E\n\u003Cp\u003EI had to do something about it.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/askara-redirect_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022368.04532577904\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAANCAYAAADBo8xmAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABb0lEQVQ4jc2UTU8bMRCGn7E9m0AI0A\/1V8CF8v8R50rlzK23HqoiEbJBu2vP9BASbZKlqqKA+lw8tuzxOx+23P\/46eC4g6pSL2qqqiJIAGA0HgNQSmY2m3E0PqK\/P6liJTOmYzKZUMxIMXF8coyZ8ev3Iw+zOTEmqqoiqa79mTn6Ml8hbdu6quLuywWRvez+COxtSy7F+Y8QX4X6Qu46bm5uCSly\/fWKu2\/f+fD5nFiNyE2L46gmLi4u30aQme1kqJ7P0dGISpVFvcDciDHSNg2IEEJgOp0uHfTKdwjS9oK7kc0oz8+0TUvTNKSUyF1HCJHTs9ODi+izW7KceXqaE1OkdB2mE4yAsGw8c4hByOYY8OUkkOJOXK8272usm3pbkLu\/WfRDiMjGCx0sWV0vcDfMQAQESEkppQDLLJWcCcD5p48bwez77NcCtzM0xNDB\/j90CEErOwxd8jdhQ3sOWeK1oL7T9+6jDUH\/kpX35A+PhxaIl\/hdhgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/askara-redirect_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022368.04532577904\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFor quite a while my VPS was misconfigured \u2013 any HTTP requests it got but couldn\u2019t assign to a vhost, it redirected to the main website, \u003Ca href=\u0022https:\/\/avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E avris.it\u003C\/a\u003E. I didn\u2019t think it would be a big deal, until I recently found out that my post \u003Ca href=\u0022\/blog\/ungoogling\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Ungoogling\u003C\/a\u003E is indexed by Google under \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022\u003Ehttps:\/\/askara.avris.it\/blog\/ungoogling\u003C\/a\u003E\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EThis subdomain hadn\u2019t existed for a long time already, my server doesn\u2019t serve a certificate for it anymore, but it requires \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/HTTP_Strict_Transport_Security\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E HSTS\u003C\/a\u003E, so browsers end up showing users a scary error message.\u003C\/p\u003E\n\u003Cp\u003EI had to do something about it.\u003C\/p\u003E\n\u003Ch3\u003ECertificate\u003C\/h3\u003E\n\u003Cp\u003EFirst of all, users have to see \u003Cem\u003Eanything\u003C\/em\u003E other than a security warning. I need a wildcard certificate.\u003C\/p\u003E\n\u003Cp\u003EFortunately, Let\u2019s Encrypt offers them now, and it\u2019s totally free. I just followed \u003Ca href=\u0022https:\/\/medium.com\/@saurabh6790\/generate-wildcard-ssl-certificate-using-lets-encrypt-certbot-273e432794d7\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E an instruction\u003C\/a\u003E to obtain one, and then configured Apache to serve the \u003Ccode\u003E\/www\/default\u003C\/code\u003E directory with the \u003Ccode\u003E*.avris.it\u003C\/code\u003E certificate for all requests that don\u2019t fit to any vhost.\u003C\/p\u003E\n\u003Ch3\u003ERedirect for users\u003C\/h3\u003E\n\u003Cp\u003EOnce the users can see the website, I can show them things. Ideally, just a 404 with an information that it\u2019s not a valid domain, and a suggestion where they might have wanted to go (same request string, but with the base domain). Easy.\u003C\/p\u003E\n\u003Cp\u003EBtw, I used \u003Ca href=\u0022https:\/\/watercss.netlify.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Water.css\u003C\/a\u003E, a ridiculously simple CSS framework \u2013 I just added two lines, no classes, and the page already looks way better!\u003C\/p\u003E\n\u003Ch3\u003ERedirect for bots\u003C\/h3\u003E\n\u003Cp\u003EBut that doesn\u2019t solve the root cause: bots are confused about which domains they should be using. They don\u2019t care whether my certificate is working or not, they don\u2019t understand the message I left there for the users.\u003C\/p\u003E\n\u003Cp\u003EThey need a proper \u003Ccode\u003EHTTP 301 -- Moved permanently\u003C\/code\u003E. So I had to add a simple recognition whether I\u2019m serving a bot or a user, and adjust the response for each of them.\u003C\/p\u003E\n\u003Ch3\u003ESource\u003C\/h3\u003E\n\u003Cp\u003ESo, here\u2019s what I ended up with:\u003C\/p\u003E\n\u003Ch4\u003E.htaccess\u003C\/h4\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs border\u0022\u003EDirectoryIndex index.php\n\n\u0026lt;IfModule mod_rewrite.c\u0026gt;\n    RewriteEngine On\n\n    RewriteCond %{REQUEST_URI}::$1 ^(\/.+)\/(.*)::\\2$\n    RewriteRule ^(.*) - [E=BASE:%1]\n\n    RewriteCond %{ENV:REDIRECT_STATUS} ^$\n    RewriteRule ^index\\.php(\/(.*)|$) %{ENV:BASE}\/$2 [R=301,L]\n\n    RewriteCond %{REQUEST_FILENAME} -f\n    RewriteRule .? - [L]\n\n    RewriteRule .? %{ENV:BASE}\/index.php [L]\n\u0026lt;\/IfModule\u0026gt;\n\n\u0026lt;IfModule !mod_rewrite.c\u0026gt;\n    \u0026lt;IfModule mod_alias.c\u0026gt;\n        RedirectMatch 302 ^\/$ \/index.php\/\n    \u0026lt;\/IfModule\u0026gt;\n\u0026lt;\/IfModule\u0026gt;\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch4\u003Eindex.php\u003C\/h4\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n\n\u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EisBrowser\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($ua)\u003C\/span\u003E: \u003Cspan class=\u0022hljs-title\u0022\u003Ebool\u003C\/span\u003E\n\u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (!$ua) {\n                \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E;\n        }\n        $isProbablyBot = (bool) preg_match(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027#bot|crawler|baiduspider|80legs|ia_archiver|voyager|curl|wget|yahoo! slurp|mediapartners-google|facebookexternalhit|twitterbot|whatsapp|php|python#i\u0027\u003C\/span\u003E, mb_strtolower($ua));\n        $isProbablyBrowser = (bool) preg_match(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027#mozilla|msie|gecko|firefox|edge|opera|safari|netscape|konqueror|android#i\u0027\u003C\/span\u003E, mb_strtolower($ua));\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $isProbablyBrowser || !$isProbablyBot;\n}\n\n$url = \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027https:\/\/avris.it\u0027\u003C\/span\u003E . $_SERVER[\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027REQUEST_URI\u0027\u003C\/span\u003E];\n\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (!isBrowser($_SERVER[\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027HTTP_USER_AGENT\u0027\u003C\/span\u003E] ?? \u003Cspan class=\u0022hljs-keyword\u0022\u003Enull\u003C\/span\u003E)) {\n    http_response_code(\u003Cspan class=\u0022hljs-number\u0022\u003E301\u003C\/span\u003E);\n    header(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027Location: \u0027\u003C\/span\u003E . $url);\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Edie\u003C\/span\u003E;\n}\n\nhttp_response_code(\u003Cspan class=\u0022hljs-number\u0022\u003E404\u003C\/span\u003E);\n\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Eecho\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0026lt;\u0026lt;\u0026lt;HTML\n\n\u0026lt;!DOCTYPE html\u0026gt;\n\u0026lt;html lang=\u0022en\u0022\u0026gt;\n\u0026lt;head\u0026gt;\n    \u0026lt;meta charset=\u0022UTF-8\u0022\u0026gt;\n    \u0026lt;title\u0026gt;404 \u2013 Not found\u0026lt;\/title\u0026gt;\n    \u0026lt;meta name=\u0022viewport\u0022 content=\u0022width=device-width, initial-scale=1\u0022\u0026gt;\n\n    \u0026lt;link rel=\u0022shortcut icon\u0022 href=\u0022https:\/\/avris.it\/assetic\/gfx\/favicon.png\u0022 \/\u0026gt;\n    \u0026lt;link rel=\u0022stylesheet\u0022 href=\u0022https:\/\/cdn.jsdelivr.net\/gh\/kognise\/water.css@latest\/dist\/light.min.css\u0022\u0026gt;\n\u0026lt;\/head\u0026gt;\n\u0026lt;body\u0026gt;\n \u0026lt;h1\u0026gt;\n    404 \u2013 Not found\n\u0026lt;\/h1\u0026gt;\n\u0026lt;p\u0026gt;\n    This is not a valid subdomain.\n\u0026lt;\/p\u0026gt;\n\u0026lt;p\u0026gt;\n    Did you mean \u0026lt;a href=\u0022\u003Cspan class=\u0022hljs-subst\u0022\u003E$url\u003C\/span\u003E\u0022\u0026gt;\u003Cspan class=\u0022hljs-subst\u0022\u003E$url\u003C\/span\u003E\u0026lt;\/a\u0026gt; ?\n\u0026lt;\/p\u0026gt;\n\u0026lt;hr\/\u0026gt;\n\u0026lt;p\u0026gt;\n    \u0026lt;small\u0026gt;\n        You\u0027ll be redirected there in \u0026lt;span id=\u0022countdown\u0022\u0026gt;15\u0026lt;\/span\u0026gt; seconds anyway... \ud83e\udd37\n    \u0026lt;\/small\u0026gt;\n\u0026lt;p\u0026gt;\n\u0026lt;script\u0026gt;\n    const \\$el = document.getElementById(\u0027countdown\u0027);\n    seconds = 15;\n    setInterval(_ =\u0026gt; {\n        if (seconds === 0) {\n            window.location.href = \u0027\u003Cspan class=\u0022hljs-subst\u0022\u003E$url\u003C\/span\u003E\u0027;\n            return;\n        }\n        seconds--;\n        \\$el.innerHTML = seconds;\n    }, 1000);\n\u0026lt;\/script\u0026gt;\n\u0026lt;\/body\u0026gt;\n\u0026lt;\/html\u0026gt;\nHTML;\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["apache","bots","certbot","certificate","domain","https","letsencrypt","php","subdomain","wildcard"],"hasMore":true,"image":"https:\/\/avris.it\/image\/askara-redirect_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/askara-redirect_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/askara-redirect_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002292.011331444759\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFor quite a while my VPS was misconfigured \u2013 any HTTP requests it got but couldn\u2019t assign to a vhost, it redirected to the main website, \u003Ca href=\u0022https:\/\/avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E avris.it\u003C\/a\u003E. I didn\u2019t think it would be a big deal, until I recently found out that my post \u003Ca href=\u0022\/blog\/ungoogling.lite\u0022\u003E Ungoogling\u003C\/a\u003E is indexed by Google under \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022\u003Ehttps:\/\/askara.avris.it\/blog\/ungoogling\u003C\/a\u003E\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EThis subdomain hadn\u2019t existed for a long time already, my server doesn\u2019t serve a certificate for it anymore, but it requires \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/HTTP_Strict_Transport_Security\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E HSTS\u003C\/a\u003E, so browsers end up showing users a scary error message.\u003C\/p\u003E\n\u003Cp\u003EI had to do something about it.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/askara-redirect_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/askara-redirect_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002292.011331444759\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFor quite a while my VPS was misconfigured \u2013 any HTTP requests it got but couldn\u2019t assign to a vhost, it redirected to the main website, \u003Ca href=\u0022https:\/\/avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E avris.it\u003C\/a\u003E. I didn\u2019t think it would be a big deal, until I recently found out that my post \u003Ca href=\u0022\/blog\/ungoogling.lite\u0022\u003E Ungoogling\u003C\/a\u003E is indexed by Google under \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022\u003Ehttps:\/\/askara.avris.it\/blog\/ungoogling\u003C\/a\u003E\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EThis subdomain hadn\u2019t existed for a long time already, my server doesn\u2019t serve a certificate for it anymore, but it requires \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/HTTP_Strict_Transport_Security\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E HSTS\u003C\/a\u003E, so browsers end up showing users a scary error message.\u003C\/p\u003E\n\u003Cp\u003EI had to do something about it.\u003C\/p\u003E\n\u003Ch3\u003ECertificate\u003C\/h3\u003E\n\u003Cp\u003EFirst of all, users have to see \u003Cem\u003Eanything\u003C\/em\u003E other than a security warning. I need a wildcard certificate.\u003C\/p\u003E\n\u003Cp\u003EFortunately, Let\u2019s Encrypt offers them now, and it\u2019s totally free. I just followed \u003Ca href=\u0022https:\/\/medium.com\/@saurabh6790\/generate-wildcard-ssl-certificate-using-lets-encrypt-certbot-273e432794d7\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E an instruction\u003C\/a\u003E to obtain one, and then configured Apache to serve the \u003Ccode\u003E\/www\/default\u003C\/code\u003E directory with the \u003Ccode\u003E*.avris.it\u003C\/code\u003E certificate for all requests that don\u2019t fit to any vhost.\u003C\/p\u003E\n\u003Ch3\u003ERedirect for users\u003C\/h3\u003E\n\u003Cp\u003EOnce the users can see the website, I can show them things. Ideally, just a 404 with an information that it\u2019s not a valid domain, and a suggestion where they might have wanted to go (same request string, but with the base domain). Easy.\u003C\/p\u003E\n\u003Cp\u003EBtw, I used \u003Ca href=\u0022https:\/\/watercss.netlify.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Water.css\u003C\/a\u003E, a ridiculously simple CSS framework \u2013 I just added two lines, no classes, and the page already looks way better!\u003C\/p\u003E\n\u003Ch3\u003ERedirect for bots\u003C\/h3\u003E\n\u003Cp\u003EBut that doesn\u2019t solve the root cause: bots are confused about which domains they should be using. They don\u2019t care whether my certificate is working or not, they don\u2019t understand the message I left there for the users.\u003C\/p\u003E\n\u003Cp\u003EThey need a proper \u003Ccode\u003EHTTP 301 -- Moved permanently\u003C\/code\u003E. So I had to add a simple recognition whether I\u2019m serving a bot or a user, and adjust the response for each of them.\u003C\/p\u003E\n\u003Ch3\u003ESource\u003C\/h3\u003E\n\u003Cp\u003ESo, here\u2019s what I ended up with:\u003C\/p\u003E\n\u003Ch4\u003E.htaccess\u003C\/h4\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-htaccess\u0022\u003EDirectoryIndex index.php\n\n\u0026lt;IfModule mod_rewrite.c\u0026gt;\n    RewriteEngine On\n\n    RewriteCond %{REQUEST_URI}::$1 ^(\/.+)\/(.*)::\\2$\n    RewriteRule ^(.*) - [E=BASE:%1]\n\n    RewriteCond %{ENV:REDIRECT_STATUS} ^$\n    RewriteRule ^index\\.php(\/(.*)|$) %{ENV:BASE}\/$2 [R=301,L]\n\n    RewriteCond %{REQUEST_FILENAME} -f\n    RewriteRule .? - [L]\n\n    RewriteRule .? %{ENV:BASE}\/index.php [L]\n\u0026lt;\/IfModule\u0026gt;\n\n\u0026lt;IfModule !mod_rewrite.c\u0026gt;\n    \u0026lt;IfModule mod_alias.c\u0026gt;\n        RedirectMatch 302 ^\/$ \/index.php\/\n    \u0026lt;\/IfModule\u0026gt;\n\u0026lt;\/IfModule\u0026gt;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch4\u003Eindex.php\u003C\/h4\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E\u0026lt;?php\n\nfunction isBrowser($ua): bool\n{\n        if (!$ua) {\n                return false;\n        }\n        $isProbablyBot = (bool) preg_match(\u0027#bot|crawler|baiduspider|80legs|ia_archiver|voyager|curl|wget|yahoo! slurp|mediapartners-google|facebookexternalhit|twitterbot|whatsapp|php|python#i\u0027, mb_strtolower($ua));\n        $isProbablyBrowser = (bool) preg_match(\u0027#mozilla|msie|gecko|firefox|edge|opera|safari|netscape|konqueror|android#i\u0027, mb_strtolower($ua));\n\n        return $isProbablyBrowser || !$isProbablyBot;\n}\n\n$url = \u0027https:\/\/avris.it\u0027 . $_SERVER[\u0027REQUEST_URI\u0027];\n\nif (!isBrowser($_SERVER[\u0027HTTP_USER_AGENT\u0027] ?? null)) {\n    http_response_code(301);\n    header(\u0027Location: \u0027 . $url);\n    die;\n}\n\nhttp_response_code(404);\n\necho \u0026lt;\u0026lt;\u0026lt;HTML\n\n\u0026lt;!DOCTYPE html\u0026gt;\n\u0026lt;html lang=\u0022en\u0022\u0026gt;\n\u0026lt;head\u0026gt;\n    \u0026lt;meta charset=\u0022UTF-8\u0022\u0026gt;\n    \u0026lt;title\u0026gt;404 \u2013 Not found\u0026lt;\/title\u0026gt;\n    \u0026lt;meta name=\u0022viewport\u0022 content=\u0022width=device-width, initial-scale=1\u0022\u0026gt;\n\n    \u0026lt;link rel=\u0022shortcut icon\u0022 href=\u0022https:\/\/avris.it\/assetic\/gfx\/favicon.png\u0022 \/\u0026gt;\n    \u0026lt;link rel=\u0022stylesheet\u0022 href=\u0022https:\/\/cdn.jsdelivr.net\/gh\/kognise\/water.css@latest\/dist\/light.min.css\u0022\u0026gt;\n\u0026lt;\/head\u0026gt;\n\u0026lt;body\u0026gt;\n \u0026lt;h1\u0026gt;\n    404 \u2013 Not found\n\u0026lt;\/h1\u0026gt;\n\u0026lt;p\u0026gt;\n    This is not a valid subdomain.\n\u0026lt;\/p\u0026gt;\n\u0026lt;p\u0026gt;\n    Did you mean \u0026lt;a href=\u0022$url\u0022\u0026gt;$url\u0026lt;\/a\u0026gt; ?\n\u0026lt;\/p\u0026gt;\n\u0026lt;hr\/\u0026gt;\n\u0026lt;p\u0026gt;\n    \u0026lt;small\u0026gt;\n        You\u0027ll be redirected there in \u0026lt;span id=\u0022countdown\u0022\u0026gt;15\u0026lt;\/span\u0026gt; seconds anyway... \ud83e\udd37\n    \u0026lt;\/small\u0026gt;\n\u0026lt;p\u0026gt;\n\u0026lt;script\u0026gt;\n    const \\$el = document.getElementById(\u0027countdown\u0027);\n    seconds = 15;\n    setInterval(_ =\u0026gt; {\n        if (seconds === 0) {\n            window.location.href = \u0027$url\u0027;\n            return;\n        }\n        seconds--;\n        \\$el.innerHTML = seconds;\n    }, 1000);\n\u0026lt;\/script\u0026gt;\n\u0026lt;\/body\u0026gt;\n\u0026lt;\/html\u0026gt;\nHTML;\u003C\/code\u003E\u003C\/pre\u003E","words":651,"readTime":3,"lang":"en"}}}}}