How does a web server recognize which URL to serve when there are multiple web sites (hostnames) associated with the same IP address?
With the Apache web server, a set of virtualhosts is defined that contain parameters to match a request to a directory. Using a basic, default set up for an Ubuntu web server, you would have a file in the /etc/apache2/sites-enabled directory like this:
<VirtualHost>
ServerName example.com
DocumentRoot /var/www/example.com/httpdocs
</VirtualHost>
This tells apache that all requests to example.com that arrive at this machine should be routed to the /var/www/example.com/httpdocs folder. Another entry to example.org could point it to a different folder.
Also relevant is the /etc/hosts file and the apache a2ensite command.
This is done in apache by using NameVirtualHost
You first declare what IP and port in httpd.conf to use like:
NameVirtualHost 127.0.0.1:80
Then in your virtual host block, you do:
<VirtualHost 127.0.0.1:80>
ServerName your_domain
DocumentRoot path_to_your_app
....
</VirtualHost>
This will allow you to have multiple hosts on one IP. But be warned that if you access the IP directly, it will direct the request to the first virtual host.
Through the use of virtual hosts.
This is an example configuration from nginx
http {
index index.html;
server {
server_name www.domain1.com;
access_log logs/domain1.access.log main;
root /var/www/domain1.com/htdocs;
}
server {
server_name www.domain2.com;
access_log logs/domain2.access.log main;
root /var/www/domain2.com/htdocs;
}
}
Essentially, when a user requests a resource the server checks the host field of the request and responds accordingly.
HTTP 1.1 defines a header called the "Host" header.
Before Apache or any other server sees the request, the client browser creates the http 1.1 request headers and sends the request to the server you are asking for your browser to contact.
Once the request hits apache the server looks at the Host header portion of the HTTP request headers. You can observe this by using wireshark, liveHttpHeaders, HTTPfox or whatever http dissecting/packet capturing tool you like. The host header in HTTP 1.1 (Host: header is not defined for HTTP 1.0 or 0.9) is formatted as follows:
Host: www.example.com\r\n
When apache looks at this header it parses it and goes through the existing VirtualHosts table that is used for mapping matching host headers to directories or actions defined.
That is to say if you had a NameVirtualHost for www.example.com that points to /some/path/example.com/
NameVirtualhost stuff here
<VirtualHost 127.0.0.1:80>
ServerName www.example.com
DocumentRoot /some/path/example.com
....
</VirtualHost>
your apache would take the following request:
GET /index.html HTTP/1.1\r\n <-- version is a key part
Connection: close\r\n
Host: www.example.com\r\n <-- key part
Accept: blah\r\n
Another: blah\r\n
read the wiki page for more on header format.
Apache would see that the host header contains www.example.com and serve up the file
/some/path/example.com/index.html because that directory and filename matches the requested resource and it is the directory that is to be used for serving requests with the host header containing www.example.com.
That is how it works.
Depends on the type of server. Apache uses a .htaccess file and you could also configure virtual hosts. If you're trying to do something specific, you may want to edit your question to include exactly what you're looking for and what software you're using to host.
Related
(This SO thread seems to be very similar, but does not answer my problem)
I have a loadbalancer listening on https://loadbalancerurl:443/
which terminates SSL and forwards requests to the IHS (IBM HTTP Server) on port 80.
I need to configure the IHS as a reverse proxy, such that requests get forwarded to https://targeturl:443/
browser --443--> loadbalancer --80--> IHS --443--> target
The reason we need to do this on the IHS, is because on that server we have direct and quick access to change the target url on demand, whereas the loadbalancer is out of our control.
This means, that i need to activate SSL in the IHS, but only for the outgoing requests to the targeturl, but not for the incoming requests.
Pages like
this from IBM
or this blog post
assume that SSL is incoming and outgoing.
Here is the relevant code block of the httpd.conf file:
LoadModule ibm_ssl_module modules/mod_ibm_ssl.so
SSLProxyEngine on
<VirtualHost *:80>
# ServerName webserverhostname # not needed so far
SSLEnable # without this i get "SSL0263W: SSL Connection attempted when SSL did not initialize."
KeyFile store.kdb # without this i get "SSL0170E: GSK could not initialize, no keyfile specified."
SSLStashFile store.sth
ProxyPass / https://targeturl/
ProxyPassReverse / https://targeturl/
</VirtualHost>
SSLDisable
where the store.kdb contains the CA certificates of the targeturl, as indicated in the SO thread
However, the server continuously spits out the following error message:
SSL0227E: SSL Handshake Failed, Specified label could not be found in the key file, or the specified label is not a 'personal certificate' (no private key). Label='(null)'
As far as i understand, this means that IHS is failing to handle incoming https traffic, which should not happen. It should not happen because the <VirtualHost *:80> specifies port 80, and also because any traffic that reaches the IHS has the SSL terminated by the loadbalancer.
Am i misunderstanding the error message? If not, how can i get this working?
edit to show working solution:
LoadModule ibm_ssl_module modules/mod_ibm_ssl.so
SSLProxyEngine on
<VirtualHost *:80>
# ServerName webserverhostname # not needed so far
# SSLEnable # this would activate SSL for incoming traffic
KeyFile store.kdb # this contains the CA certificates of the target server
# SSLStashFile store.sth # would only be needed for incoming SSL
ProxyPass / https://targeturl/
ProxyPassReverse / https://targeturl/
</VirtualHost>
# SSLDisable
SSLEnable should not be present in a virtual host that doesn't actually handle inbound SSL.
SSLStashFile is also not needed. It is unfortunately named.
You should deep dive on the error_log entries you get in the config without these two. There is likely an early SSL error that does not fail startup. The only necessary config even without frontend SSL is just:
SSLProxyEngine on
ProxyPass / https://example.com/
KeyFile /path/to/key.kdb
I have a Docker container with wordpress:latest in a host which has Apache 2.4 installed.
I added the lines below to my Apache configuration file, inside the vhost group:
ProxyPass http://localhost:8010
ProxyPassReverse http://localhost:8010
When I try to access my URL I can reach wordpress homepage, however all static files point to localhost so my layout doesn't work.
What am I missing? Some setup at Apache? Wordpress itself?
Apache modules are already enabled.
Edit 1:
Forgot to mention: this piece of configuration is inside a Location directive, which is inside a vhost directive.
<VirtualHost *:80>
...
<Location /usa>
RequestHeader set X-Is-Reverse=Proxy true
RequestHeader set X-Original-Host mysite.com.br
ProxyPass http://localhost:8010
ProxyPreserveHost On
ProxyPassReverse http://localhost:8010
</Location>
...
</VirtualHost>
Check that the Site URL setting in wordpress matches the URL your clients are calling.
This is the documentation on how to change the site URL in wordpress: https://codex.wordpress.org/Changing_The_Site_URL
If you proxy pass to your backend like that, requests coming into your container will be sent with the Host header set to localhost. Apparently, the WordPress container takes care of the host that has been set in order to generate static assets links. Try setting the following proxy option:
ProxyPreserveHost On
Just after the ProxyPass configuration line.
This options forward the Host HTTP header coming from the client over to the proxy connection. This way the backend will understand which public URL it's been called from and asset links should be correct.
Edit.
If you can't use the ProxyPreserveHost Directive you could try and directly set the Host header using:
RequestHeader set Host "your.host.name"
I complete the configuration in nginx as well as i connect it via this link
http://1.2.3.4/MyProject/
where my ip address assign in nginx 1.2.3.4
and my nginx configuration
server_name 1.2.3.4;
listen 80;
but when i give domain name like
server name account.com;
listen 80;
but when i open that page from browser like:- http://account.come it will redirect at http://:1.2.3.4/myproject
so how can i hide my ip-address and see my domain name?
Thankyou so much.
remove any server_name 1.2.3.4; in all config files and also see default config file under site-availeables
to check why its redirect to ip please check yor DNS server for example bind or bind9 service or named: /etc/named and all zones under /var/lib/named
maybe new site not configured proper by you then ping sitename once in your client system like windows and once by lynx on server via putty...
2-check nginx is working with proxycache or module cache ??
3-check your project code setting for example wordpress or some projects redirect some pages to cached url on database...
to check is from this project make test.php and code about echo rand(1,999); that can test redirection and cache at once.
ifrandom code show same number it is cache problem.
if no cache but redirecting to server ip address it is configuration issue...
if not solved remove all http server configs and define again .
add with www alias for site name
server {
listen 80 ;
server_name a.com www.a.com;
I had got the solution for that, I changed my godady account configuration.
and then put like:-
server_name abc.com;
Hello I am trying to create a website in multiple languages. Every language has it own virtual subdomain. So for example here are some urls:
nl.foo.eu, fr.foo.eu, de.foo.eu
My domain that generates all the content is foo.eu, it generates the content and translates it to the right language.
This is done with wordpress and the plugin qTranslate-X.
But everytime when I go to an url like nl.foo.eu the page returns an internal server error 500.
So my question is: Do i need to configure something in my DNS to make this possible?
And could I be doing something else wrong?
I went trough the error log of the server and this is the error i am retrieving:
[Fri Apr 17 09:53:21.028095 2015] [core:error] [pid 731951] [client 12.34.56.78:50514] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.
I configured my environment this way:
select "Use Pre-Domain Mode (uses http://en.yoursite.com)" in the advanced settings of domain
add DNS records; in my hosts file, I added this:
127.0.0.1 www.example.com
127.0.0.1 en.example.com
127.0.0.1 example.com
check that your web server is properly configured. I'm using Apache and I have this configuration with wildcard in ServerAlias:
<VirtualHost *:80>
DocumentRoot /wamp/www/example
ServerName www.example.com
ServerAlias example.com *.example.com
AcceptPathInfo On
</VirtualHost>
I hope this can help you
I want to test nginx subdomains before uploading config to the server. Can i test it on localhost? I try
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://localhost:8080;
}
}
server {
listen 80;
server_name sub.localhost;
location / {
proxy_pass http://localhost:8080/sub;
}
}
And it does not work. Shoulld i change my hosts file in order to make it work? Also, after uploading site to the server should i change DNS records and add sub.mydomain.com?
Yes, add '127.0.0.1 sub.localhost' to your hosts file. That sub has to be resolved somehow. That should work.
Then once you're ready to go to the net, yes, add an a or cname record for the subdomain sub.
When I use proxy_pass I also include the proxy.conf from nginx.
http://wiki.nginx.org/HttpProxyModule
In Linux based OS just to edit as sudo /etc/hosts file and change 127.0.0.1 localhost to 127.0.0.1 *.localhost.
So at /etc/nginx/sites-enabled/<environment>/<your_project_name> edit server_name key as <subdomain>.localhost.
Reload nginx and networking service.
$ sudo service nginx reload
$ sudo service networking reload
And then try http://<subdomain>.localhost at url bar.
It works for me.
UPDATE
In my opinion, a better solution is creating a virtual server that only responds if subdomain doesn’t exist, at /etc/nginx/sites-enabled/development/default, as default server (remember that you can define only one server as default).
server {
listen 80 default_server;
root /var/www/html/errors/404;
server_name *.localhost *.<host-name>;
location / {
index subdomain.html;
}
}
Make sure that in nginx.conf (generally at /etc/nginx/nginx.conf) contain include /etc/nginx/sites-enabled/**/*; to this virtual server work. If not, put it and then run $ sudo service nginx reload.
In this case isn't necessary put *.localhost in /etc/hosts, but only localhost.
For your public webserver with its own domain name, you just need to add a Canonical name using a CNAME record in your DNS configuration:
CNAME * example.com.
Once this is done, set your nginx setting
server_name *.example.com example.com;
In your local setup you can keep the same configuration for nginx but unless you have a local DNS setup, you will have to edit your /etc/hosts file and add each subdomain manually. wildcards don't work in the /etc/hosts file.
127.0.0.1 abc.example.com def.example.com ghi.example.com
It is generally recommended to use .local as the namespace for your local domains.
With an Nginx configuration like shown by the OP, all that is needed is to configure the local DNS resolution. I run Linux containers on a VM with a local DHCP IP but test them on Windows 10 browsers.
The DNS configuration can be done by editing "C:\Windows\System32\drivers\etc\hosts" as Administrator.
192.168.100.50 sub.example.local
192.168.100.50 example.local
Of course, use 127.0.0.1 or other appropriate IP as needed.