48

What are some good ways to do this? Is it even possible to do cleanly?

Ideally I'd like to use packet headers to decide which server should handle requests. However, if there is an easier/better way let me know.

Dane O'Connor
  • 75,180
  • 37
  • 119
  • 173

9 Answers9

33

It's impossible for both servers to listen on the same port at the same IP address: since a single socket can only be opened by a single process, only the first server configured for a certain IP/port combination will successfully bind, and the second one will fail.

You will thus need a workaround to achieve what you want. Easiest is probably to run Apache on your primary IP/port combination, and have it route requests for IIS (which should be configured for a different IP and/or port) to it using mod_rewrite.

Keep in mind that the alternative IP and port IIS runs on should be reachable to the clients connecting to your server: if you only have a single IP address available, you should take care to pick an IIS port that isn't generally blocked by firewalls (8080 might be a good option, or 443, even though you're running regular HTTP and not SSL)

P.S. Also, please note that you do need to modify the IIS default configuration using httpcfg before it will allow other servers to run on port 80 on any IP address on the same server: see Micky McQuade's answer for the procedure to do that...

mdb
  • 52,000
  • 11
  • 64
  • 62
  • Can you elaborate how you'd have Apache route the request? Also, is there a reason Apache should be the primary server or is it just preference? – Dane O'Connor Sep 20 '08 at 15:10
  • The reason to make Apache the primary is the fact that is has mod_rewrite. (Similar solutions exist for IIS, but not as flexible.) To have Apache route the request, you'd need to define a folder (which can be a virtual host root) on it with rewrite rules in .htaccess or httpd.conf – mdb Sep 20 '08 at 15:39
  • 3
    For future readers, `mod_rewrite` is not a good solution to this problem because it only handles the URL, whereas a proper proxy handles everything else. – Walf Dec 09 '13 at 00:32
  • @Walf Maybe I'm short sighted, but I don't see how you would do it in a URL agnostic manner. If you have certain URLs handled by Apache, and others handled by IIS, all request coming to the same IP:port, then how do you distinguish them without handling the URL? – AaronLS May 14 '15 at 21:24
  • @AaronLS See [my answer](http://stackoverflow.com/a/8721605/315024). It's not about a URL agnostic solution, it's just not the right tool for the job. – Walf May 20 '15 at 01:54
  • @Walf I did look at your answer which works great for subdomains, it doesn't work for URLs. I think you've made a generalization about what tool is right for the job, without consideration for how much the job varies. It's pretty common to have virtual paths mapped to different web applications. You might have a service supporting web API at `example.com/api`, while Apache serves a website at `example.com/marketing`, while IIS serves `example.com/cms`. You can accomplish this with mod_proxy, but you need to leverage other features of mod_proxy outside of what you demonstrated in your answer. – AaronLS May 20 '15 at 20:43
  • @AaronLS That's not what @thedeeno's question was about, and `mod_rewrite` would likely still be inadequate for your hypothetical. It doesn't do proper passing of the request and response headers back and forth. You'd be better off have one app calling the other and knowing how to do any required translations before serving it to the user. – Walf May 22 '15 at 01:56
  • @Walf "You'd be better off have one app calling the other and knowing how to do any required translations before serving it to the user." So The CMS team's site needs to be programmed to call the marketing site? That's utter nonsense. An absolute violation of separation of concerns. If you have a good setup you should be able to stand up distinct sites and applications at unique URLs and not have a need for them to be aware of each other. – AaronLS May 26 '15 at 20:40
  • @Walf It sounds like maybe your aversion to mod_rewrite is a result of lack of understand of its capabilities. It is absolutely capable of that scenario. – AaronLS May 26 '15 at 20:43
  • @AaronLS I don't have any such aversion. This question is about separate sites, not just multiple services installed on one site. The Apache docs say this about external addresses: "If an absolute URL is specified ... an external redirect is performed for the given URL." How is that meant to forward request headers, such as `Host` and return verbatim responses, including response codes like 303 redirects? Educate us. – Walf Jun 05 '15 at 02:52
30

I found this post which suggested to have two separate IP addresses so that both could listen on port 80.

There was a caveat that you had to make a change in IIS because of socket pooling. Here are the instructions based on the link above:

  1. Extract the httpcfg.exe utility from the support tools area on the Win2003 CD.
  2. Stop all IIS services: net stop http /y
  3. Have IIS listen only on the IP address I'd designated for IIS: httpcfg set iplisten -i 192.168.1.253
  4. Make sure: httpcfg query iplisten (The IPs listed are the only IP addresses that IIS will be listening on and no other.)
  5. Restart IIS Services: net start w3svc
  6. Start the Apache service
Michael
  • 8,362
  • 6
  • 61
  • 88
Micky McQuade
  • 1,873
  • 1
  • 16
  • 21
  • This is exactly right; I had to do this a couple months ago to solve the exact same problem. If using two IP addresses is acceptable, this is a very easy and robust solution. – Cody Hatch Sep 20 '08 at 16:17
  • 1
    fyi, for Windows 2008 there is a different article explaining how to do it. http://weblogs.asp.net/steveschofield/archive/2007/07/06/iis7-post-44-iis7-and-apache-on-the-same-machine.aspx – Jim Geurts Apr 12 '11 at 13:49
  • 1
    Thanks, its helped for me, but `net stop /y` stopped also print spooler, so `net start spooler` required later. – Alexey Feb 14 '14 at 04:40
  • @MickyMcQuade would you mind taking a look at my related question please? http://serverfault.com/questions/620805/tomcat-and-iis-7-both-on-different-ips-and-different-ports – n00b Aug 15 '14 at 20:58
13

For people with only one IP address and multiple sites on one server, you can configure IIS to listen on a port other than 80, e.g 8080 by setting the TCP port in the properties of each of its sites (including the default one).

In Apache, enable mod_proxy and mod_proxy_http, then add a catch-all VirtualHost (after all others) so that requests Apache isn't explicitly handling get "forwarded" on to IIS.

<VirtualHost *:80>
    ServerName foo.bar
    ServerAlias *
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8080/
</VirtualHost>

Now you can have Apache serve some sites and IIS serve others, with no visible difference to the user.

Edit: your IIS sites must not include their port number in any URLs within their responses, including headers.

Walf
  • 8,535
  • 2
  • 44
  • 59
4

You need at least mod_proxy and mod_proxy_http which both are part of the distribution (yet not everytime built automatically). Then you can look here: http://httpd.apache.org/docs/2.2/mod/mod_proxy.html

Simplest config in a virtualhost context is:

ProxyPass         /winapp http://127.0.0.1:8080/somedir/

ProxyPassReverse  /winapp http://127.0.0.1:8080/somedir/

(Depending on your webapp, the actual config might become more sophisticated. ) That transparently redirects every request on the path winapp/ to the windows server and transfers the resulting output back to the client.

Attention: Take care of the links in the delivered pages: they aren't rewritten, so you can save yourself lotsa hassle if you generally use relative links in your app, like

<a href=../pics/mypic.jpg">

instead of the usual integration nightmare of every link being absolute:

<a href="http://myinternalhostname/somedir/crappydesign.jpg">

THE LATTER IS BAD ALMOST EVERY SINGLE TIME!

For rewriting links in pages there's mod_proxy_html (not to confuse with mod_proxy_http!) but that's another story and a cruel one as well.

3

Either two different IP addresses (like recommended) or one web server is reverse-proxying the other (which is listening on a port <>80).

For instance: Apache listens on port 80, IIS on port 8080. Every http request goes to Apache first (of course). You can then decide to forward every request to a particular (named virtual) domain or every request that contains a particular directory (e.g. http://www.example.com/winapp/) to the IIS.

Advantage of this concept is that you have only one server listening to the public instead of two, you are more flexible as with two distinct servers.

Drawbacks: some webapps are crappily designed and a real pain in the ass to integrate into a reverse-proxy infrastructure. A working IIS webapp is dependent on a working Apache, so we have some inter-dependencies.

  • From my research I was considering a reverse proxy scenario. Can you elaborate how you set this up? Did you use Apache mod_Proxy? My two apps aren't dependent on each other which is a plus - are there still some gotchas I should watch out for? – Dane O'Connor Sep 22 '08 at 17:40
0

I see this is quite an old post, but came across this looking for an answer for this problem. After reading some of the answers they seem very long winded, so after about 5 mins I managed to solve the problem very simply as follows:

httpd.conf for Apache leave the listen port as 80 and 'Server Name' as FQDN/IP :80.

Now for IIS go to Administrative Services > IIS Manager > 'Sites' in the Left hand nav drop down > in the right window select the top line (default web site) then bindings on the right.

Now select http > edit and change to 81 and enter your local IP for the server/pc and in domain enter either your FQDN (www.domain.com) or external IP close.

Restart both servers ensure your ports are open on both router and firewall, done.

This sounds long winded but literally took 5 mins of playing about. works perfectly.

System: Windows 8, IIS 8, Apache 2.2

Matthew White
  • 65
  • 1
  • 9
  • 1
    I think @thedeeno was trying to avoid the issues associated with usign a non-default port. – Walf Oct 22 '14 at 06:10
0

Installing Windows 10 I had this problem: apache(ipv4) and spooler service(ipv6) listening the same 80 port.

I resolved editing apache httpd.conf file changing the line

Listen 80

to

Listen 127.0.0.1:80

0

That's not quite true. E.g. for HTTP Windows supports URL based port sharing, allowing multiple processes to use the same IP address and Port.

-1

You will need to use different IP addresses. The server, whether Apache or IIS, grabs the traffic based on the IP and Port, which ever they are bound to listen to. Once it starts listening, then it uses the headers, such as the server name to filter and determine what site is being accessed. You can't do it will simply changing the server name in the request

stephenbayer
  • 12,373
  • 15
  • 63
  • 98