Running Virtual Servers in Parallel - Linux Web Server Development (2015)

Linux Web Server Development (2015)

Chapter 12

Running Virtual Servers in Parallel

In this chapter, you will configure two virtual servers that run in parallel. Which virtual server handles a request is dependent on the domain name in the requested URL rather than the IP Address of the server. Recall that in the previous chapter you used two different domains for the same virtual server. This server used two different rules that were based on the port number to handle each domain. In this chapter, you can use the Match Nickname matching option to separate the two virtual servers based on their domain names. In the following examples, the first virtual server will use the webserver.dynu.com domain name and the second virtual server will use the christos.dynu.comdomain name.

Disabling the Port Forwarding Service

In this section, you will find out why disabling the Port Forwarding DDNS service is required to implement the Match Nickname Cherokee Host Match option.

The Match Nickname option of the Method drop-down menu on the Host Match tab is used to create a virtual server that will respond when the domain name in the URL of the client’s request matches the virtual server’s name. For example, when the user types a URL in the browser’s address bar:

http://webserver.dynu.com/news/file.html

The URL is included in the HTTP connection request message, as can be seen from the resultant HTTP request:

GET /news/file.html HTTP/1.1
Host: webserver.dynu.com

The Cherokee server compares the Host field of the HTTP request with the virtual server names and if a match is found (e.g., the virtual server’s name is webserver.dynu.com), the specific virtual server handles the request.

That being said, the previous sequence of events does not take place when the port forwarding DDNS service is used. When Port Forwarding is used, all client-server messages are routed to the DDNS Service Provider’s Port Forwarding server. When the DDNS service receives a DNS request for a domain name for which Port Forwarding is enabled, the DDNS service responds with the IP address of its own Port Forwarding server instead of the public IP address of the router in front of the Cherokee server. When the Port Forwarding server receives the client's HTTP request, the Port Forwarding server redirects the client to send a new HTTP connection request to the public IP address of the router in front of the Cherokee server, using instead of the default port number 80, the port number on which your server listens (e.g., port 8080). The Port Forwarding server therefore alters the domain name in the Host field of the HTTP connection request, (e.g., from webserver.dynu.com, it will become <router’s-public-IP-address:8080). Both the port as well as the domain name must have been previously registered with the DDNS service provider (which was done in chapter 6).

To illustrate the sequence of events, we’ll look at the initial HTTP request (from the client’s system) as well as the HTTP request that is received by the Web server. We’ll look at both cases: with Port Forwarding enabled and with Port Forwarding disabled. To examine the headers of the HTTP protocol, we’ll use the online network tool HTTP Viewer:

http://www.rexswain.com/httpview.html

Another site offering a similar service is http://web-sniffer.net. Let’s look first at the case with the DDNS port forwarding service disabled. In the URL field of the HTTP Viewer enter the URL of the Web server’s site:

http://webserver.dynu.com:8080

After clicking the Submit button, the following page appears:

The following is a part of the information provided by this page. It includes the rexswain.com request to webserver.dynu.com:8080 which resolvers to the public IP address of the router (87.202.110.63) and eventually through the virtual servers router configuration to the server that was assigned port 8080, which is your Web server.

GET / HTTP/1.1

Host: webserver.dynu.com:8080

User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36

Referer: http://www.rexswain.com/httpview.html

Connection: close

• Finding host IP address...

• Host IP address = 87.202.110.63

• Finding TCP protocol...

• Binding to local socket...

• Connecting to host...

• Sending request...

• Waiting for response...

Receiving Header:

The Host field at the client’s request is:

http://webserver.dynu.com:8080

The web page also includes the Web server reply to the client (rexswain.com). This is a message of type OK:

HTTP/1.1·200·OK(CR)(LF)

Connection:·close(CR)(LF)

Date:·Sun,·24·May·2015·04:38:37·GMT(CR)(LF)

Server:·Cherokee/1.2.101·(UNIX)(CR)(LF)

Content-Length:·6708(CR)(LF)

Content-Type:·text/html(CR)(LF)

Expires:·Tue,·01·Jan·1970·00:00:01·GMT(CR)(LF)

(CR)(LF)

End of Header (Length = 195)

Notice that the (CR) and (LF) correspond to the Carriage Return and Line Feed ASCII characters, used as separators at the HTTP message fields.

Next, log in to your DDNS service provider’s administration web site and enable port forwarding. Return to the HTTP Viewer (www.rexswain.com) and use the following URL:

http://webserver.dynu.com

Note that the port number (8080) is not given since port forwarding is enabled. The result is shown in the following image:

The following is the request from the client to the port forwarding server and the reply from the server as listed in the rexswain.com page:

GET / HTTP/1.1

Host: webserver.dynu.com

User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36

Referer: http://www.rexswain.com/httpview.html

Connection: close

• Finding host IP address...

• Host IP address = 173.208.132.91

• Finding TCP protocol...

• Binding to local socket...

• Connecting to host...

• Sending request...

• Waiting for response...

Receiving Header:

This time, the Host field, as sent by the client is:

http://webserver.dynu.com

Information about the IP address that corresponds to this URL is also listed. This IP address is the IP address of the DDNS service provider’s Port Forwarding server:

Host IP address = 173.208.132.91

The Port Forwarding server replies with the following message:

HTTP/1.1·302·Object·moved(CR)(LF)

Date:·Sat,·23·May·2015·20:58:19·GMT(CR)(LF)

Server:·Dynu·Web·Server(CR)(LF)

X-Powered-By:·Dynu·Dynamic·DNS·Service(CR)(LF)

Location:·http://87.202.110.63:8080/(CR)(LF)

Content-Length:·145(CR)(LF)

Content-Type:·text/html(CR)(LF)

(CR)(LF)

The previous was the connection request from rexswain.com to the Port Forwarding server of the DDNS provider. The Port Forwarding server uses a Object Moved message to redirect the client to the public IP address of the router of the Web server’s LAN at the port number 8080, which is the port number forwarded. Another step follows next, with another connection request this time from the client (rexswain.com) to the router and eventually to the Web server. The connection from rexswain.com to the Web server is performed therefore with two connection requests. The second connection request message is also included in the web page of rexswain.com:

GET / HTTP/1.1

Host: 87.202.110.63:8080

User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36

Referer: http://www.rexswain.com/httpview.html

Connection: close

• Finding TCP protocol...

• Binding to local socket...

• Connecting to host...

• Sending request...

• Waiting for response...

Receiving Header:

The reply from the Web server is the HTTP message 200 (OK):

HTTP/1.1·200·OK(CR)(LF)

Connection:·close(CR)(LF)

Date:·Sun,·24·May·2015·03:58:46·GMT(CR)(LF)

Server:·Cherokee/1.2.101·(UNIX)(CR)(LF)

Content-Length:·6708(CR)(LF)

Content-Type:·text/html(CR)(LF)

Expires:·Tue,·01·Jan·1970·00:00:01·GMT(CR)(LF)

(CR)(LF)

With port forwarding disabled, the Host field in the client’s message corresponds to the server's domain name. However, with port forwarding enabled, the first request message sent to the server has a Host field that corresponds to the server’s domain name, but this is redirected. The second connection request message that follows will have an altered Host field.

You can also inspect the client’s HTTP request when it arrives at the server’s computer, with a packet sniffer, a program that captures and analyzes packets passing over a network. If you don’t have a packet sniffer, you’ll need to install Wireshark. From a Linux terminal on your Web server, run:

$ sudo apt-get install wireshark

After the installation is complete, enter the following in a terminal window:

$ sudo wireshark

The Wireshark window opens:

In the menu Capture, select Interfaces. A dialogue window appears. Choose the interface that you use (e.g., eth0). Click Start to begin capturing packets.

Wireshark starts capturing packets sent and received by the server’s computer:

Go to tools.pingdom.com and request your web page. (Since DDNS port forwarding service is disabled, don’t forget the port number).

http://webserver.dynu.com:8080

Click the Stop the running live capture button (the red square button) to stop packet capturing. Next, try to locate the request message from the tools.pingdom.com client. This is the packet destined to the Web server (with an IP address of 192.168.1.101) from the tools.pingdom.com client with the HTTP connection request message:

GET / HTTP/1.1

Locate the packet with the data GET / HTTP/1.1 in the Info column and right-click on the specific packet at the packet list and select in the pop-up menu that appears Show Packet in New Window to view it in a separate window.

A summary of the Hypertext Transfer Protocol header for this packet is listed next:

Hypertext Transfer Protocol

GET / HTTP/1.1\r\n

[Expert Info (Chat/Sequence): GET / HTTP/1.1\r\n]

[Message: GET / HTTP/1.1\r\n]

[Severity level: Chat]

[Group: Sequence]

Request Method: GET

Request URI: /

Request Version: HTTP/1.1

Host: webserver.dynu.com:8080\r\n

Connection: keep-alive\r\n

Pragma: no-cache\r\n

Cache-Control: no-cache\r\n

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n

User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36\r\n

Accept-Encoding: gzip, deflate, sdch\r\n

Accept-Language: en-US,en;q=0.8\r\n

\r\n

[Full request URI: http://webserver.dynu.com:8080/]

[HTTP request 1/2]

[Response in frame: 83]

[Next request in frame: 90]

Save the packet’s image to examine it and go to your DDNS service provider’s administration site to enable port forwarding. (This process is described in chapter 6.)

Restart packet capturing by clicking the Start a new live capture button. This is the green button to the left of the Stop the running live capture button. From an online Web server tester tool, (e.g., tools.pingdom.com), try to connect to the server. This time, use the URL without the port number (remember that the DDNS port forwarding server will add the port number):

http://webserver.dynu.com

On the tools.pingdom.com page, note that this connection fails because the Host field in the client request does not correspond to the domain name of the server and even though the request is received by the server the Match Nickname method does not apply.

Back in Wireshark, click the Stop the running live capture button, and locate the packet with the following HTTP request, which is destined to the Web server (IP address 192.168.1.101):

GET / HTTP/1.1

Right-click on the specific packet in the packet list and select Show Packet in New Window in the pop-up menu that appears to view it in a separate window.

A summary of the Hypertext Transfer Protocol header for this packet is listed next:

Hypertext Transfer Protocol

GET / HTTP/1.1\r\n

Host: 87.202.110.63:8080\r\n

Connection: keep-alive\r\n

Pragma: no-cache\r\n

Cache-Control: no-cache\r\n

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n

User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36\r\n

Accept-Encoding: gzip, deflate, sdch\r\n

Accept-Language: en-US,en;q=0.8\r\n

\r\n

[Full request URI: http://87.202.110.63:8080/]

[HTTP request 1/2]

[Response in frame: 75]

[Next request in frame: 88]

Compare the Host field in the selected packet, with the packet you saved previously. Note that the Host value in the first packet that was previously saved (when port forwarding was disabled) is exactly the same as the packet that was sent by the rexswain.com client. This is:

Host: webserver.dynu.com:8080\r\n

where \r is the Carriage Return and \n the Line Feed ASCII characters, used as separators to the HTTP header fields.

When port forwarding is enabled, the port forwarding server alters the Host field as sent by the client and replaces it with the public IP address of the router concatenated with the port number, e.g.:

Host: 87.202.110.63:8080\r\n

In that case the Host field does not indicate the server’s domain name and you cannot use the Mach Nickname matching option to separate the two virtual servers based on the domain name.

Therefore, to use the Match Nickname option, we must disable Port Forwarding for the domains registered for the two virtual servers.

Schematic Overview of the Port Forwarding Service

The next two figures show how the connection request message is formed at the Web client.

When using the HTTP Viewer network tool (e.g., web-sniffer.net), the tool acts as a Web client and queries the DDNS server to resolve your Web server’s domain name to an IP address and then sends a request to the Web server. It’s recommended to use the tool twice – once with the port forwarding service enabled and once with the port forwarding service disabled.

With port forwarding enabled, the URL used by the online network tool is:

http://webserver.dynu.com

As described in the following image the DDNS server, contacted by the online network tool (1), resolves this URL to the IP address of the Port Forwarding server. The online network tool acts as a client and sends a connection request to the Port Forwarding Server (2), which redirects the client to the IP address of the router of the Web server’s LAN. The redirected address includes the appropriate port (e.g., port 8080) and, in this case, the new address becomes <router’s public IP address>:8080. The client then connects to the router and with the Virtual Servers router configuration, the client eventually connects to the Web Server (3).

With port-forwarding disabled, the URL used in the online network tool to make a request from the Web server is webserver.dynu.com:8080. This time, the DDNS system (1) resolves the Web server’s domain name to the public IP address of the Web server’s router and the router, with its Virtual Servers service, redirects the request to the Web Server (2). In this case, a Port Forwarding server was not interfered with and the Host field in the packet remained unchanged.

The next figure shows how the request message is received by the Web server. The test page network tool (e.g., tools.pingdom.com) acts as a client to request a page from the Web server. When the Web server receives the request, a sniffer (e.g., Wireshark) can be used to grab the packet from the LAN segment on which the Web server is attached. It’s recommended to run Wireshark twice: with port forwarding enabled and with port forwarding disabled.

When port forwarding is enabled, the Host field in the packet captured by Wireshark has already been altered by the Port Forwarding server of the DDNS system. The server’s domain name has been replaced by the public IP address of the server’s router. The Match Nickname option of the Cherokee Host Match tab cannot be used in this case to match the virtual server because the Host field of the packet does not contain the server’s domain name (e.g., webserver.dynu.com) but instead contains the <router’s public IP address>:<port forwarding number> pair.

Creating the First Virtual Server

We must create two new virtual servers, one for the domain name christos.dynu.com and one for the domain name webserver.dynu.com. For the reason discussed in the previous section, visit the DDNS service provider’s site and disable Port Forwarding for both domain names before creating the servers. Also disable any other virtual servers that could respond to (and therefore interfere with) the client’s request. Set the handler of the default server to None.

First create a new Document Root Directory.

$ sudo mkdir /var/www4

Create the file index.html, a simple HTML page with a non-white background, in the www4 directory.

In the vServers section, click the Add New Virtual Server button (the blue plus sign button) in the upper-left area of the Cherokee Administration Panel. In the Nick text field of the dialogue window, enter christos.dynu.com, which is the first domain name registered in this book. Also enter the directory we just created in the Document Root text field (/var/www4). Click the Add button to confirm the settings.

Click next on the new virtual server in the server list in the left area of the window to apply other settings to the new virtual server. In the Basics tab, enter the filename index.html in the Directory Indexes text field.

In the Host Match tab, select the option Match Nickname from the Method drop-down menu.

Next go to the Behavior tab and click on the Rule Management button. A new set of tabs (Rule, Handler, etc.) appears.

In the Rule tab, choose Incoming IP/Port in the Rule Type drop-down menu. In the Incoming IP/Port drop-down menu that appears, select 8181. Since the virtual servers are selected based on the domain name and not the port number (as we did in the previous chapter), you can assign more port numbers for this virtual server. In the drop-down menu in the Assign new IP/Port area, choose port 8080.

In the Handler tab, select List & Send in the Handler drop-down menu and delete any entry in the Document root textbox. This is an alternative document root path.

You can also disable any predefined rules created by Cherokee by clicking on the green circle button next to the Rule list at the left area of the window. You can also set the handler of the Default rule to None to avoid dispatching content out of the rules you set.

Next click the SAVE button to confirm the settings. Click the Graceful restart button in the dialogue window that appears.

Creating the Second Virtual Server

We next create the virtual server that will match the domain name webserver.dynu.com. Click on the Add New Virtual Server button and enter the domain name webserver.dynu.com in the Nick text field. Create directory /var/www5and the file index.html in this directory. In the file index.html, enter HTML code for a simple colored page. Enter /var/www5 in the Document Root field. Click the Add button and select the name of the new virtual server (webserver.dynu.com) in the server list, placed on the left area of the window.

In the Basics tab, enter index.html in the Directory indexes field. In the Host Match tab, select the Match Nickname method and then click on the Rule Management button in the Behavior tab. In the new set of tabs, click the Rule tab, select Incoming IP/Port in the Rule Type drop-down menu and in the new Incoming IP/Port drop-down menu, select 8080, one of the two ports we use in this chapter. Also set the handler of the Default rule to None. As with the previous virtual server, you can also assign the port number used by the other server, port 8181.

In the Handler tab, select List & Send in the Handler drop-down menu and delete any entry in the Document root textbox. Finally click on the SAVE button in the upper-right area of the window to confirm the settings. Click the Graceful restart button in the dialogue window that appears.

Testing the Virtual Servers

At this point, the two virtual servers are running simultaneously and each virtual server is providing different content. In this example, christos.dynu.com should serve an HTML page with a green background andwebserver.dynu.com should serve an HTML page with a red background.

We’ll use www.webpagetest.org to view the HTML pages from both virtual servers. Recall that we are not using the Port Forwarding server; therefore, we must include the port numbers in the URLs:

http://webserver.dynu.com:8080

or

http://webserver.dynu.com:8181

or

http://christos.dynu.com:8181

or

http://christos.dynu.com:8080

The first two URLs should serve the red-colored page:

/var/www5/index.html

The last two URLs should serve the green-colored page:

/var/www4/index.html