404 errors accessing web app URLs with Tomcat over local IP, but works fine with external IP

1.4k views Asked by At

I have two Linux servers connected via a cross-connect cable with internal IP addresses 192.168.0.1 (hostA) and 192.168.0.2 (hostB).

hostA runs CentOS 5, and hostB CentOS 7.

hostB runs Apache 2.4.x, and Tomcat 8.5.9. All web traffic gets routed to port 443 (e.g. HTTPS) of Apache web server hostB. All web application traffic (e.g. https://www.example.com/mywebapp/somepage) is then passed to Tomcat via mod_jk version 1.2.42 on port 8009. Additionally, hostB Apache web server is configured to listen on 192.168.0.2 port 8009 (hostA Apache web server is not configured as such).

If hostA attempts to access a webpage on hostB (via hostB external IP address) from a browser or command line, such as: [root@hostA ~]# curl -I http://www.example.com/mywebapp/somepage

it returns status 200 (good).

Now, if I modify the hostA /etc/hosts file such that hostA accesses the hostB website (www.example.com) via the cross-connect cable (e.g. 192.168.0.2 rather than the external IP address), the webpage returns error 404.

What can I change to get status 200?

My web addresses are xxx.xxx.xxx.xxx (e.g. IPv4). I know Tomcat configures IPv6 by default. So, I modified the setenv.sh as follows:

CATALINA_OPTS="-Djava.net.preferIPv4Addresses=true" 

This didn't change the result.

As another clue, I observe that hostA always reports status 200 (good) when accessing any hostB webpage in www.example.com that is NOT part of /mywebapp, for both internal and external IP addresses.

I should mention that to configure hostB (e.g. 192.168.0.2) to listen to hostA (e.g. 192.168.0.1), I simply added

Listen 192.168.0.2:80 
Listen 192.168.0.2:443 

to hostB httpd.conf file. I did not create a virtual host (is that OK?). I didn't modify httpd.conf on hostA.

Any ideas what I can try to resolve this? I'm new to Tomcat and this is a fresh install on a new machine. Thanks in advance for any advice.

UPDATE 1 (config files)

/etc/httpd/conf/workers.properties (for mod_jk, hostB)

# Define one real worker using ajp13
worker.list=worker1
# Set properties for worker1 (ajp13)
# (don't open 8009 in firewall to outside world)
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009

The following is added to hostB httpd.conf in Pre Main Include section:

LoadModule jk_module /etc/httpd/modules/mod_jk.so
JkWorkersFile /etc/httpd/conf/workers.properties
# Where to put jk logs
JkLogFile /etc/httpd/logs/mod_jk.log
# Set the jk log level [debug/error/info]
JkLogLevel info
# Select the log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
# JkOptions indicate to send SSL KEY SIZE,
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# JkRequestLogFormat set the request format
JkRequestLogFormat "%w %V %T"

The following is added to hostB httpd.conf in Virtual Hosts Include sections for ports 80 and 443 of www.example.com with external IP (do I need similar for internal IP? Is that the issue?):

# Send all http://example.com/mywebapp/* requests to Tomcat 
<IfModule jk_module>
   JkMount /mywebapp/* worker1
   JkMount /mywebapp worker1
</IfModule>

$CATALINA_HOME/conf/Catalina/localhost/mywebapp.xml (hostB)

<Context>
  <Resource name="jdbc/pool1"
            auth="Container"
            type="javax.sql.DataSource"
            username="uname"
            password="pwd"
            driverClassName="oracle.jdbc.OracleDriver"
            url="jdbc:oracle:thin:@192.168.0.1:xxx:xxxx"
            maxTotal="256"
            maxIdle="8"
            initialSize="4"
            removeAbandonedTimeout="7200"
            removeAbandonedOnBorrow="true"/>

  <ResourceLink name="jdbc/pool1"
                global="jdbc/dpool1"
                type="javax.sql.DataSource"/>
</Context>

$CATALINA_HOME/webapps/mywebapp/WEB-INF/web.xml

...
<resource-ref>
        <description>Connection pool #1.</description>
        <res-ref-name>jdbc/pool1</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
</resource-ref>
...

$CATALINA_HOME/conf/server.xml (hostB)

<GlobalNamingResources>
   ...              
   <Resource name="jdbc/pool1"
        auth="Container"
        type="javax.sql.DataSource"
        username="uname"
        password="pwd"
        driverClassName="oracle.jdbc.OracleDriver"
        url="jdbc:oracle:thin:@192.168.0.1:xxx:xxxx"
        maxTotal="256"
        maxIdle="8"
        initialSize="4"
        removeAbandonedTimeout="7200"
        removeAbandonedOnBorrow="true"/>  
</GlobalNamingResources>
1

There are 1 answers

0
user46688 On BEST ANSWER

I read (http://httpd.apache.org/docs/2.4/vhosts/examples.html, see the 3rd section, titled Serving the same content on different IP addresses (such as an internal and external address) that one can easily modify an existing Virtual Host (VH)

<VirtualHost xxx.xxx.xxx.xxx:80>
...
</VirtualHost>

to account for a local IP by doing,

<VirtualHost 192.168.0.1:80 xxx.xxx.xxx.xxx:80>
...
</VirtualHost>

where the local IP can also include wildcards (e.g. 192.168.0.*).

The problem is my httpd.conf file is controlled/maintained by WHM per the server hosting company, and manual edits will be overwritten.

Thus, my only option is to copy the existing entire VH code from httpd.conf for the external IP address (two VH sections in my case: one each for port 80 and 443), and paste it in the pre_virtualhost_global.confGlobal file using the Includes Editor provided by WHM, and changing the external IP address to the internal IP address for the code just pasted in.

Just keep in mind you'll need to manually maintain this section (since WHM doesn't touch it when updating, etc.).