27 февраля 2012, 04:41 от António P. P. Almeida [email protected]:
non-www…right? I’m still getting: nginx: [emerg] unknown “domain”
server_name ^~(?<domain_name>[^.]).(?[^.])$;
listen 80;
nginx: [emerg] invalid server name or wildcard
proxy_pass http://$domain_name.$tld;
}
}
This should work [1].
Your solution, while syntactically correct, is wrong by design.
What you created there is an open anonymizing proxy that will pass
any request from anyone to any host:port combination that contains
only the domain name and the TLD, if a functional resolver has been
set up using the resolver directive. Take a guess what this would do:
$ nc frontend 80
GET /a/clue HTTP/1.0
Host: fbi.gov:22
You should never pass unsanitized user input to pass_proxy, unless
you want people to abuse your open anonymizing proxy for illegal
activities that will get you in trouble. Good luck convincing
the FBI that your incompetence was the real culprit.
Moreover, the frontend server will pass all requests for
“http://$domain_name.$tld” that would have normally been passed
on to the backend server on to itself to create a nasty loop,
unless you happen to have split horizon DNS set up with the
resolver set to the internal DNS server that maps the value
of “$domain_name.$tld” to an internal IP. But if you had that kind
of setup, you’d use it to do the mapping in the first place instead
of doing what you’ve been trying to do.
This is what your solution does if a functional resolver has been
set up:
http://www.domain.tld -> status code 301 with “Location:
http://domain.tld”
http://own-domain.tld -> proxy_pass LOOP to http://own-domain.tld
http://foreign-domain.tld:port -> OPEN ANONYMIZING PROXY to
foreign-domain.tld:port
If no resolver has been set up, proxy_pass will fail due to being
unable to resolve the value of “$domain.$tld” for any request
that contains only the domain name and the TLD.
Here’s one of the correct ways to do what the OP wants to do:
map $http_host $wwwless_http_host {
hostnames;
default $http_host;
~^www.(?P.*)$ $domain;
}
server {
listen 80 default_server;
server_name _;
location / {
proxy_set_header Host $wwwless_http_host;
proxy_pass http://backend;
}
}
It would be a good idea to also allow only hosts and domains that you
actually host, which could be done like this:
map $http_host $own_http_host {
hostnames;
default 0;
include nginx.own-domains.map;
}
server {
listen 80 default_server;
server_name _;
if ($own_http_host = 0) {
# Not one of our hosts / domains, so terminate the connection
return 444;
}
location / {
proxy_set_header Host $own_http_host;
proxy_pass http://backend;
}
}
The nginx.own-domains.map file would contain entries such as:
.domain.org domain.org; # map *.domain.org to domain.org
www.another.net another.net; # map only www.another.net to
another.net
This file could be generated automatically from DNS zone files,
so it would be easy to maintain.
Max