Why does example.com behave exactly as .example.com? - nginx

I don't know why server_name example.com matches also subdomains (at least when there's not a rule for those), if there's an specific syntax for doing so:
Nginx documentation states that you can define server_name in the following ways:
Sets names of a virtual server, for example:
server_name example.com;
Server names can include an asterisk (“*”) replacing the first or last
part of a name:
server_name *.example.com;
Such names are called wildcard names.
The first two of the names mentioned above can be combined in one:
server_name .example.com;
But I tested this, and example.com behaves just as .example.com is expected, matching also all the subdomains.
This is not a problem as I can override the subdomains by setting a server for *.example.com but it seems very odd to me that if the syntax of .example.com exists with the intention to match both other two, it should mean that the other two don't match to eachother...
Why is this?

If your subdomains don't match any rule, they will be called back to the rule tagged as default_server, which, by default, is the first one on the file. In this case, the example.com rule.
This is the answer to the right question:
https://stackoverflow.com/a/64742545/8719655

Related

nginx and redirect to varnish

I have nginx config like:
server {
listen *:443 ssl;
server_name ~^(.*\.)?domain.com$;
second
server {
listen *:443 ssl;
server_name ~^(.*\.)?test.domain.com$;
Problem is that domain.com works fine but test.domain.com not. Redirects it to domain.com
If I simply do:
server_name www.domain.com$ domain.com$;
and
server_name test.domain.com$;
Then I always get problem with SSL
Any ideas how to solve it?
Just a guess. Swap first server block with second server block. So test is not eaten by your first server block. Or make sure your first server block does not eat test like so: server_name ~^(.*?[^t]?[^e]?[^s]?[^t]\.)?domain.com$;. Or maybe better like so: server_name ~^(.*(?<!test)\.)?domain.com$; (negative lookbehind - supported by Nginx???)
Completly untested - but maybe you get the idea.
Make sure that you - in your regex - escape all dots . with backslash \. or brackets [.] to make them literally a dot character. Otherwise you serve also test-domain-com for example, which you don't want.
Im not sure if you can use regex dollar $ in server_name if you don't mark it as regex ~.

Nginx server_name 52.com - How to use numerical domain names?

Maybe I'm going crazy, but I can't get a numerical domain to load anything. It just ignores server_name and loads the first site.
server_name 52.com;

Nginx - get subdomain as variable

I have a couple of subdomains with the same behavior (based on subdomain name) and I am trying to find the best solution with less overhead for the nginx server.
On that domain there are also default www and non-www domains, also a wildcard (those "couple of" subdomains should not match the wildcard).
So far I've found 3 possible solutions:
define each subdomain in separate server block, and hardcode the subdomain
server {
server_name one.domain;
# config with "one"
}
server {
server_name two.domain;
# same config with "two"
}
... three, four etc.
this should be ok, but it's not DRY (don't repeat yourself)
also it's long and looks ugly
catch server_name in a regexp
server {
server_name ~^(?<subdomain>one|two|three|...)\.domain\.com$;
# config with $subdomain
}
config is cleaner, but there is a regexp overhead, also may interact with the wildcard virtual host, I'm not sure which will take precedence
static hostname plus map
server {
server_name one.domain two.domain three.domain ....;
# config with $subdomain, where $subdomain is a map based on $server_name, extracting all characters before .
}
this should be the best approach, vhost selection is based on string compare (no regexp), but I still have regexp usage in that "map"
The question is: can the third solution be improved ?
As in extracting part of a string (i.e. $subdomain from $server_name) without using a regexp ?
All subdomains are on the same level, and all end in .domain

Fourth-Level Subdomain Forwarding

I've recently been trying to set up a reverse proxy that would forward certain 4th-level subdomains to particular locations. So, for example, this is what I'm trying to accomplish (configuration in my nginx file):
server {
listen 80;
server_name *.server.domain.com;
rewrite ^ https://$server_name$request_uri;
}
The goal here being that if someone went to, for example, http://item1.server.domain.com, they would be re-routed to https://item1.server.domain.com. However, with this configuration, the URL gets rewritten to https://%2A.server.domain.com.
Is there a way to fix this so that the full domain (item1) gets added correctly to the rewritten URL? Ideally, I wanted it to eventually be able to rewrite any subdomain on server.domain.com directly to https.
Thanks!
The $server_name variable contains the text from the value of the server_name directive. The %2A is a URL encoded representation of the leading *.
Use $host or $http_host to obtain the hostname actually requested by the client. See this document for more.
For example:
server {
listen 80;
server_name *.server.domain.com;
return 301 https://$host$request_uri;
}
Note: Restart nginx and clear the browser cache between each test. Check the configuration using nginx -T.

Nginx Reverse Proxy non listening domain catch all

Using nginx as a reverse proxy I have noted that if a site is pointed at the server but does not actually exist you get served with an existing site on the server rather than a domain cannot be found message or similar.
ie say your config block is listening for portal.test.org the user points there cname to the nginx system but with the domain header of smartportal.test.org
or say the they point a site like portal.test2.org
Could someone direct me on the following
a. How nginx decides which site to return when it does not exist as a virtual host
b. How to catch any domain that are not specified and return a default page that tells users this domain does not exist on this host
Hope someone can help I have tried googling but I think sometimes its knowing the correct terms.
Many thanks
you should use default_server parameter of listen directive and server_name directive.
your questions
How nginx decides which site to return when it does not exist as a virtual host
listen [default_server]
If the directive has the default_server parameter, then the enclosing
server {...} block will be the default server for the address:port
pair. This is useful for name-based virtual hosting where you wish to
specify the default server block for hostnames that do not match any
server_name directives. If there are no directives with the
default_server parameter, then the default server will be the first
server block in which the address:port pair appears.
server_name
This directive performs two actions:
Compares the Host header of the incoming HTTP request against the
server { ... } blocks in the Nginx configuration files and selects the
first one that matches. This is how virtual servers are defined.
Server names are processed in the following order:
1.- full, static names
2.- names with a wildcard at the start of the name — *.example.com
3.- names with a wildcard at the end of the name — www.example.*
4.- names with regular expressions
If there is no match, a server { ... } block in
the configuration file will be used based on the following order:
1.- the
server block with a matching listen directive marked as
[default|default_server]
2.- the first server block with a matching listen
directive (or implicit listen 80;)
How to catch any domain that are not specified and return a default page that tells users this domain does not exist on this host
server {
listen 1.2.3.4:80 default_server;
server_name _ "";
location / {
alias /var/www/html/domain-does-not-exists.html;
}
}
server {
listen 1.2.3.4:80 ;
server_name portal.test.org;
location / {
... your site ...
}
}

Resources