Fourth-level domain fails routing

A customer reported some issues when working on 4th-level domains, which for some reason kept redirecting to main domain.

The setup was something like this:

  • domain.tld
  • a.sub.domain.tld
  • b.sub.domain.tld

DNS records were properly set and even SSL was properly issued, but when visiting either a.sub.domain.tld or b.sub.domain.tld you’ll be served whatever domain.tld should have.

The issues doesn’t seems to be replicable on 3rd-level domains, so a-sub.domain.tld and b-sub.domain.tld will work properly.

I managed to replicate the same on:

  • dev.fz.nicolae.at
  • dev-fz.nicolae.at

I already had a wildcard here, so I just created the subdomains and they both should “Your site is live, but now it needs some content” as the default index.html is the only thing in those docroots with no .htaccess whatsoever.

Should I be looking for some specific Apache flag/config that introduces this behaviour?

Subdomains need to be local, i.e. explicitly named with the domain, past third level. The following works for me:

IP=$(cpcmd -d abc.test site:ip-address)

# Create local subdomains
cpcmd -d abc.test web:add-subdomain lvl1.abc.test /var/www/lvl1
cpcmd -d abc.test web:add-subdomain lvl2.lvl1.abc.test /var/www/lvl1-2
cpcmd -d abc.test file:put-file-contents /var/www/lvl1/index.php '<?php echo __FILE__;'
cpcmd -d abc.test file:put-file-contents /var/www/lvl1-2/index.php '<?php echo __FILE__;'

curl --resolve lvl1.abc.test:80:$IP  http://lvl1.abc.test/index.php
# Reports /var/www/lvl1
curl --resolve lvl2.lvl1.abc.test:80:$IP  http://lvl2.lvl1.abc.test/index.php
# Reports /var/www/lvl1-2

# Create global subdomain
cpcmd -d abc.test web:add-subdomain lvl2-global.lvl1 /var/www/lvl1-3
cpcmd -d abc.test file:put-file-contents /var/www/lvl1-3/index.php '<?php echo __FILE__;'

# Boom! Falls through to lvl1
curl --resolve lvl2-global.lvl1.abc.test:80:$IP  http://lvl2-global.lvl1.abc.test/index.php
1 Like

Let me summarize this for others: if you want a lvl2.lvl1.abc.test subdomain, you first need to create the lvl1.abc.test subdomain.

This is unnecessary. When working with subdomain subdomains, they must be fully qualified instead of global; this is how the subdomain component is looked up (to the first dot).

IP=$(cpcmd -d abc.test site:ip-address)
cpcmd -d abc.test web:add-subdomain local.does-exist.abc.test /var/www/exists
cpcmd -d abc.test web:add-subdomain global.no-exist /var/www/no-exists
cpcmd -d abc.test file:put-file-contents /var/www/exists/index.php '<?php echo __FILE__;'
cpcmd -d abc.test file:put-file-contents /var/www/no-exists/index.php '<?php echo __FILE__;'

# Works
curl --resolve local.does-exist.abc.test:80:$IP  http://local.does-exist.abc.test/index.php
# Fails
curl --resolve global.no-exist.abc.test:80:$IP  http://global.no-exist.abc.test/index.php

If DNS isn’t working for secondary levels, it may be a quirk with your DNS provider. * applies to all n+1 hostnames for a zone, for example:

cpcmd -d futz.net dns:add-record futz.net '*' A 127.0.0.1
dig @ns1.apisnetworks.com +norec a.b.futz.net
dig @ns1.apisnetworks.com +norec a.futz.net