./configure --prefix=/Users/weli/projs/httpd-bin --enable-ssl
In this article I'd like to show you how to use mod_jk as HTTP connector of JBoss AS, and I'll also show you how to configure SSL to work with connector.
Go to http://www.jboss.org/jbossas/downloads/ and download EAP 6.1.0.Final:
Unzip jboss-eap-6.1.0.zip and try to start server in standalone mode:
If everything goes fine you can see server is started:
Try to access web port and you should see:
Now we stop server by pressing 'CTRL-C':
Go to http://httpd.apache.org/download.cgi and download httpd 2.2.25:
Unzip httpd-2.2.25.tar.bz2 and run configure:
Please note the command we've used:
./configure --prefix=/Users/weli/projs/httpd-bin --enable-ssl
We define 'httpd-bin' will be the place that we install our compiled httpd. And we've enabled 'ssl' option so we'll have 'mod_ssl' in our httpd binaries.
If everything goes fine the 'configure' should be finished without any problems:
Now we run 'make' to compile the code:
make
After it finished we run 'make install':
make install
You can see everything is installed to 'prefix' folder we've defined:
Then we need to verify 'mod_ssl' is installed correctly:
Now let's start the httpd and test its connection:
After verify it works we could shutdown http server for now:
dhcp-17-85:bin weli$ sudo ./httpd -f /Users/weli/projs/httpd-bin/conf/httpd.conf -k stop
Goto http://tomcat.apache.org/download-connectors.cgi and download JK 1.2.37 Source Release:
Extract downloaded zip and run 'configure':
Please note we have defined the position of our httpd binary:
./configure --with-apxs=/Users/weli/projs/httpd-bin/bin/apxs
After configure finished let's compile & install it:
make
make install
If everything goes fine you can see mod_jk is installed to httpd:
And we can verify 'mod_jk.so' is correctly installed:
dhcp-17-85:native weli$ ls /Users/weli/projs/httpd-bin/modules/mod_jk.so /Users/weli/projs/httpd-bin/modules/mod_jk.so
But now if you dump modules that is used by httpd you'll see mod_jk is not there yet:
dhcp-17-85:bin weli$ pwd /Users/weli/projs/httpd-bin/bin dhcp-17-85:bin weli$ ./httpd -f /Users/weli/projs/httpd-bin/conf/httpd.conf -D DUMP_MODULES | grep mod_jk Syntax OK dhcp-17-85:bin weli$
Because we haven't configure httpd to load 'mod_jk.so', in next section let's work on it.
First is to open 'httpd.conf' in 'conf' folder:
dhcp-17-85:conf weli$ pwd /Users/weli/projs/httpd-bin/conf dhcp-17-85:conf weli$ ls httpd.conf httpd.conf
Go to the 'Dynamic Shared Object (DSO) Support' section:
# # Dynamic Shared Object (DSO) Support # # To be able to use the functionality of a module which was built as a DSO you # have to place corresponding `LoadModule' lines at this location so the # directives contained in it are actually available _before_ they are used. # Statically compiled modules (those listed by `httpd -l') do not need # to be loaded here. # # Example: # LoadModule foo_module modules/mod_foo.so #
And add mod_jk configurations under this section:
# Load mod_jk.so LoadModule jk_module /Users/weli/projs/httpd-bin/modules/mod_jk.so # Config file of mod_jk JkWorkersFile /Users/weli/projs/httpd-bin/conf/workers.properties # Redirect all requests to 'worker1' node, which will be the JBoss AS server we've installed. JkMount /* worker1 # Set mod_jk log level to 'debug', we'll check these debug info later JkLogLevel debug
After finish the above modifications to 'httpd.conf', let's save the file and exit to test 'mod_jk.so' is loaded by httpd correctly:
dhcp-17-85:bin weli$ ./httpd -f /Users/weli/projs/httpd-bin/conf/httpd.conf -D DUMP_MODULES | grep jk Syntax error on line 59 of /Users/weli/projs/httpd-bin/conf/httpd.conf: JkWorkersFile: Can't find the workers file specified
Oops, seems we've forgetten to add '/Users/weli/projs/httpd-bin/conf/workers.properties' defined in config, now let's create this file:
dhcp-17-85:conf weli$ pwd /Users/weli/projs/httpd-bin/conf dhcp-17-85:conf weli$ touch workers.properties
Now we open this file and put in the config:
worker.list=worker1 worker.worker1.type=ajp13 worker.worker1.host=127.0.0.1 worker.worker1.port=8009
Let's read the above config line by line:
worker.list=worker1
mod_jk supports cluster by using multple workers(workers could be JBossAS or Tomcat, or the application servers that support ajp13 protocol) in behind. Because for this article we just have one 'worker', which is jboss-eap-6.1.0 we've installed, so we just config one worker here, and named it 'worker1'.
worker.worker1.type=ajp13
We'll use AJP13 protocol for mod_jk to communicate with JBoss AS. You can see in JBoss AS the 'AJP 1.3' procotol stack is enabled in 'standalone-ha.xml':
dhcp-17-85:configuration weli$ pwd /Users/weli/projs/jboss-eap-6.1/standalone/configuration
dhcp-17-85:configuration weli$ grep 'AJP' standalone-ha.xml <connector name="ajp" protocol="AJP/1.3" scheme="http" socket-binding="ajp"/>
Now let's go back to 'workers.properties':
worker.worker1.host=127.0.0.1 worker.worker1.port=8009
This is the worker's working address and port. This is set according to the config in JBoss AS:
dhcp-17-85:configuration weli$ grep '8009' standalone-ha.xml <socket-binding name="ajp" port="8009"/>
dhcp-17-85:configuration weli$ grep 'inet-address.*127.0.0.1' standalone-ha.xml <inet-address value="${jboss.bind.address.management:127.0.0.1}"/> <inet-address value="${jboss.bind.address:127.0.0.1}"/> <inet-address value="${jboss.bind.address.unsecure:127.0.0.1}"/>
After editing the 'worker.properties' and its meanings, now let's save the file and test httpd config again:
dhcp-17-85:bin weli$ pwd /Users/weli/projs/httpd-bin/bin
dhcp-17-85:bin weli$ ./httpd -f /Users/weli/projs/httpd-bin/conf/httpd.conf -D DUMP_MODULES | grep jk Syntax OK jk_module (shared)
Seems mod_jk is loaded correctly now, so it's time to get all components online and do the testing
Goto 'bin' folder of JBoss AS and run the startup script:
dhcp-17-85:bin weli$ pwd /Users/weli/projs/jboss-eap-6.1/bin
dhcp-17-85:bin weli$ ./standalone.sh -c standalone-ha.xml
Server should start with 'standalone-ha' profile:
After server started, please try to access AJP port:
As we have verified that JBoss AS is configured properly, now let's move to httpd side.
Before using httpd, we need to bind httpd to public IP address. This is similar to the situations in productisation environment: We ask connector to listen to public address and redirect these requests to backend AS servers sits in LAN.
First we need to find our machine's public IP address:
dhcp-17-85:~ weli$ ifconfig en1 en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether 88:53:95:2d:fb:cd inet6 fe80::8a53:95ff:fe2d:fbcd%en1 prefixlen 64 scopeid 0x4 inet 10.0.1.13 netmask 0xffffff00 broadcast 10.0.1.255 media: autoselect status: active
So my machine's public address is
10.0.1.13
dhcp-17-85:conf weli$ pwd /Users/weli/projs/httpd-bin/conf dhcp-17-85:conf weli$ ls httpd.conf httpd.conf
We goto 'Listen' section:
# # Listen: Allows you to bind Apache to specific IP addresses and/or # ports, instead of the default. See also the <VirtualHost> # directive. # # Change this to Listen on specific IP addresses as shown below to # prevent Apache from glomming onto all bound IP addresses. # #Listen 12.34.56.78:80 Listen 80
Change
Listen 80
Listen 10.0.1.13:80
Next step we need to setup server name of httpd:
Go to 'ServerName' section of httpd:
# # ServerName gives the name and port that the server uses to identify itself. # This can often be determined automatically, but we recommend you specify # it explicitly to prevent problems during startup. # # If your host doesn't have a registered DNS name, enter its IP address here. # #ServerName www.example.com:80
Add a ServerName below this section:
ServerName mini
We've set my ServerName as 'mini'. Now let's save 'httpd.conf' and exit editor. Next step is to map this hostname with the public IP address of this machine in
/etc/hosts
dhcp-17-85:~ weli$ ping mini PING mini (10.0.1.13): 56 data bytes 64 bytes from 10.0.1.13: icmp_seq=0 ttl=64 time=0.076 ms 64 bytes from 10.0.1.13: icmp_seq=1 ttl=64 time=0.065 ms 64 bytes from 10.0.1.13: icmp_seq=2 ttl=64 time=0.053 ms 64 bytes from 10.0.1.13: icmp_seq=3 ttl=64 time=0.058 ms ^C --- mini ping statistics --- 4 packets transmitted, 4 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 0.053/0.063/0.076/0.009 ms
From the ping output we could see our public IP address is correctly mapped to hostname 'mini'.
Everything seems ready now:
JBoss AS is started with 'standalone-ha.xml' profile, and listening to AJP port 8009 binding with IP address '127.0.0.1'
httpd is listening on port 80 binding with public IP address '10.0.1.13', and ready to redirect all the requests to 'worker1', which is actually the AS 7 server sitting behind.
Time to make some fun!
Now let's start httpd:
dhcp-17-85:bin weli$ pwd /Users/weli/projs/httpd-bin/bin
dhcp-17-85:bin weli$ sudo ./httpd -f /Users/weli/projs/httpd-bin/conf/httpd.conf -k start
And let's check the debug log of 'mod_jk.so' to verify it is started correctly:
dhcp-17-85:logs weli$ pwd /Users/weli/projs/httpd-bin/logs
dhcp-17-85:logs weli$ tail -n 1 mod_jk.log [Wed Aug 07 00:38:13.566 2013] [30877:140735242764672] [debug] jk_child_init::mod_jk.c (3248): Initialized mod_jk/1.2.37
Now let's access our httpd serving address:
http://mini
With the help of mod_jk, the requests from public address port 80 has been redirected to the backend(through AJP protocol) JBoss AS server which is listening on localhost port 8009.
Now let's kill the JBoss AS server by using 'CTRL-C':
00:47:46,537 INFO [org.jboss.as] JBAS015950: JBoss EAP 6.0.0.GA (AS 7.1.2.Final-redhat-1) stopped in 19ms
And now let's connect to 'http://mini' again:
Because the backend service is down, so httpd could no longer redirect requests to worker. Checking the 'mod_jk.log' and you can see it's reporting the errors:
[Wed Aug 07 00:47:49.375 2013] [30873:140735242764672] [info] ajp_connect_to_endpoint::jk_ajp_common.c (995): Failed opening socket to (127.0.0.1:8009) (errno=61) [Wed Aug 07 00:47:49.375 2013] [30873:140735242764672] [error] ajp_send_request::jk_ajp_common.c (1630): (worker1) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=61)
Now we start JBoss AS again:
dhcp-17-85:bin weli$ pwd /Users/weli/projs/jboss-eap-6.1/bin
dhcp-17-85:bin weli$ ./standalone.sh -c standalone-ha.xml
After server started, we try to connect to 'http://mini' again:
The whole service back to work now.
Using SSL in our system is not as difficult as you think. Because we are using AJP 1.3 protocol in between httpd and JBoss AS, and httpd is listening to public address, so we just need to configure SSL in httpd and that's all:
Now let's see how to enable SSL in httpd:
First we create a 'cert' directory in 'httpd-bin' to store certificates:
dhcp-17-85:httpd-bin weli$ pwd /Users/weli/projs/httpd-bin
dhcp-17-85:httpd-bin weli$ mkdir certs
dhcp-17-85:httpd-bin weli$ ls bin certs conf htdocs include man modules build cgi-bin error icons logs manual
Now we enter this directory and create a key:
dhcp-17-85:httpd-bin weli$ cd certs/ dhcp-17-85:certs weli$
dhcp-17-85:certs weli$ openssl genrsa -des3 -out mini.key 1024 Generating RSA private key, 1024 bit long modulus ..........++++++ .........................................++++++ e is 65537 (0x10001) Enter pass phrase for mini.key: secret Verifying - Enter pass phrase for mini.key: secret dhcp-17-85:certs weli$
As show above, we've set the pass phrase as 'secret' and created the key file 'mini.key'. After generating our key, we need to sign it, so next step is to generate a CSR(Certificate Signing Request) file:
dhcp-17-85:certs weli$ openssl req -new -key mini.key -out mini.csr Enter pass phrase for mini.key: secret You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:CN State or Province Name (full name) [Some-State]:Beijing Locality Name (eg, city) []:Beijing Organization Name (eg, company): Personal Organizational Unit Name (eg, section) []:Personal Common Name (e.g. server FQDN or YOUR name) []:mini Email Address []:l.weinan@gmail.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
In above section, the 'Common Name' section is very important:
Common Name (e.g. server FQDN or YOUR name) []:mini
This must match your 'ServerName' in your 'httpd.conf' and your hostname in '/etc/hosts'.
Last step is to sign this CSR file, we'll use our own key file to sign it:
dhcp-17-85:certs weli$ openssl x509 -req -days 30 -in mini.csr -signkey mini.key -out mini.crt Signature ok subject=/C=CN/ST=Beijing/L=Beijing/O=Personal/OU=Personal/CN=mini/emailAddress=l.weinan@gmail.com Getting Private key Enter pass phrase for mini.key: secret
Now we have prepared the cert file 'mini.crt':
dhcp-17-85:certs weli$ ls mini.crt mini.csr mini.key
Next step is to configure httpd to use the cert to enable SSL:
Open httpd.conf, and in 'Listen' section, add:
Listen 10.0.1.13:443
for httpd to listen to 443 port (which is default port used by https).
Goto the bottom of 'httpd.conf', add:
NameVirtualHost *:443 <VirtualHost *:443> SSLEngine on SSLCertificateFile /Users/weli/projs/httpd-bin/certs/mini.crt SSLCertificateKeyFile /Users/weli/projs/httpd-bin/certs/mini.key JkMount /* worker1 JkLogLevel debug </VirtualHost>
Now we start httpd:
sudo ./httpd -f /Users/weli/projs/httpd-bin/conf/httpd.conf -k start Apache/2.2.25 mod_ssl/2.2.25 (Pass Phrase Dialog) Some of your private key files are encrypted for security reasons. In order to read them you have to provide the pass phrases. Server mini:443 (RSA) Enter pass phrase: secret OK: Pass Phrase Dialog successful.
And don't forget to start JBoss AS:
./standalone.sh -c 'standalone-ha.xml'
Now it's time to play with our SSL connection:
Try to access:
https://mini
And browser will complain the cert provided by web server is not valid because it's not signed by a CA:
We know this cert is signed by ourself so just ignore the warning and continue to access the URL:
Now we can see the https connection is working and the request is successfully send to JBoss AS.