通过本地 IP 使用 Tomcat 访问 Web 应用程序 URL 时出现 404 错误,但可以正常使用外部 IP
404 errors accessing web app URLs with Tomcat over local IP, but works fine with external IP
我有两台 Linux 服务器通过交叉连接电缆连接,内部 IP 地址分别为 192.168.0.1 (hostA) 和 192.168.0.2 (hostB)。
hostA 运行 CentOS 5,hostB 运行 CentOS 7。
hostB 运行 Apache 2.4.x 和 Tomcat 8.5.9。所有网络流量都被路由到 Apache 网络服务器主机 B 的端口 443(例如 HTTPS)。然后,所有 Web 应用程序流量(例如 https://www.example.com/mywebapp/somepage)通过端口 8009 上的 mod_jk 版本 1.2.42 传递到 Tomcat。此外,hostB Apache Web 服务器配置为侦听 192.168.0.2 端口8009(hostA Apache Web 服务器未按此配置)。
如果hostA试图通过浏览器或命令行访问hostB上的网页(通过hostB的外部IP地址),例如:
[root@hostA ~]# curl -I http://www.example.com/mywebapp/somepage
它 returns 状态 200(良好)。
现在,如果我修改 hostA /etc/hosts
文件,使 hostA 通过交叉连接电缆(例如 192.168.0.2 而不是外部 IP 地址)访问 hostB 网站(www.example.com) , 网页 returns 错误 404.
我可以更改什么以获得状态 200?
我的网址是 xxx.xxx.xxx.xxx
(例如 IPv4)。我知道 Tomcat 默认配置 IPv6。所以,我修改了 setenv.sh
如下:
CATALINA_OPTS="-Djava.net.preferIPv4Addresses=true"
这并没有改变结果。
作为另一个线索,我观察到 hostA 在访问 www.example.com 中不属于 /mywebapp 的任何 hostB 网页时总是报告状态 200(良好),用于内部和外部 IP 地址。
我应该提到配置 hostB(例如 192.168.0.2)以监听 hostA(例如 192.168.0.1),我只是添加了
Listen 192.168.0.2:80
Listen 192.168.0.2:443
到主机 B httpd.conf
文件。我没有创建虚拟主机(可以吗?)。我没有修改 hostA 上的 httpd.conf
。
有什么办法可以解决这个问题吗?我是 Tomcat 的新手,这是新机器上的全新安装。在此先感谢您的任何建议。
更新 1(配置文件)
/etc/httpd/conf/workers.properties(对于 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
将以下内容添加到主机 B httpd.conf 的 Pre Main Include 部分:
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"
以下内容已添加到虚拟主机中的主机 B httpd.conf 包括具有外部 IP 的 www.example.com 的端口 80 和 443 的部分(我需要类似的内部 IP 吗?这是问题所在吗?) :
# 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(主机 B)
<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>
我读了(http://httpd.apache.org/docs/2.4/vhosts/examples.html,见第 3 部分,标题为 Serving the same content on different IP addresses (such as an internal and external address)
可以轻松修改现有的虚拟主机 (VH)
<VirtualHost xxx.xxx.xxx.xxx:80>
...
</VirtualHost>
通过做占本地IP,
<VirtualHost 192.168.0.1:80 xxx.xxx.xxx.xxx:80>
...
</VirtualHost>
其中本地 IP 也可以包含通配符(例如 192.168.0.*)。
问题是我的 httpd.conf
文件是 controlled/maintained 服务器托管公司的 WHM,手动编辑将被覆盖。
因此,我唯一的选择是从 httpd.conf
复制现有的整个 VH 代码用于外部 IP 地址(在我的例子中有两个 VH 部分:端口 80 和 443 各一个),并将其粘贴到pre_virtualhost_global.confGlobal
文件使用 WHM 提供的包含编辑器,并将刚刚粘贴的代码的外部 IP 地址更改为内部 IP 地址。
请记住,您需要手动维护此部分(因为 WHM 在更新等时不会触及它)。
我有两台 Linux 服务器通过交叉连接电缆连接,内部 IP 地址分别为 192.168.0.1 (hostA) 和 192.168.0.2 (hostB)。
hostA 运行 CentOS 5,hostB 运行 CentOS 7。
hostB 运行 Apache 2.4.x 和 Tomcat 8.5.9。所有网络流量都被路由到 Apache 网络服务器主机 B 的端口 443(例如 HTTPS)。然后,所有 Web 应用程序流量(例如 https://www.example.com/mywebapp/somepage)通过端口 8009 上的 mod_jk 版本 1.2.42 传递到 Tomcat。此外,hostB Apache Web 服务器配置为侦听 192.168.0.2 端口8009(hostA Apache Web 服务器未按此配置)。
如果hostA试图通过浏览器或命令行访问hostB上的网页(通过hostB的外部IP地址),例如: [root@hostA ~]# curl -I http://www.example.com/mywebapp/somepage
它 returns 状态 200(良好)。
现在,如果我修改 hostA /etc/hosts
文件,使 hostA 通过交叉连接电缆(例如 192.168.0.2 而不是外部 IP 地址)访问 hostB 网站(www.example.com) , 网页 returns 错误 404.
我可以更改什么以获得状态 200?
我的网址是 xxx.xxx.xxx.xxx
(例如 IPv4)。我知道 Tomcat 默认配置 IPv6。所以,我修改了 setenv.sh
如下:
CATALINA_OPTS="-Djava.net.preferIPv4Addresses=true"
这并没有改变结果。
作为另一个线索,我观察到 hostA 在访问 www.example.com 中不属于 /mywebapp 的任何 hostB 网页时总是报告状态 200(良好),用于内部和外部 IP 地址。
我应该提到配置 hostB(例如 192.168.0.2)以监听 hostA(例如 192.168.0.1),我只是添加了
Listen 192.168.0.2:80
Listen 192.168.0.2:443
到主机 B httpd.conf
文件。我没有创建虚拟主机(可以吗?)。我没有修改 hostA 上的 httpd.conf
。
有什么办法可以解决这个问题吗?我是 Tomcat 的新手,这是新机器上的全新安装。在此先感谢您的任何建议。
更新 1(配置文件)
/etc/httpd/conf/workers.properties(对于 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
将以下内容添加到主机 B httpd.conf 的 Pre Main Include 部分:
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"
以下内容已添加到虚拟主机中的主机 B httpd.conf 包括具有外部 IP 的 www.example.com 的端口 80 和 443 的部分(我需要类似的内部 IP 吗?这是问题所在吗?) :
# 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(主机 B)
<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>
我读了(http://httpd.apache.org/docs/2.4/vhosts/examples.html,见第 3 部分,标题为 Serving the same content on different IP addresses (such as an internal and external address)
可以轻松修改现有的虚拟主机 (VH)
<VirtualHost xxx.xxx.xxx.xxx:80>
...
</VirtualHost>
通过做占本地IP,
<VirtualHost 192.168.0.1:80 xxx.xxx.xxx.xxx:80>
...
</VirtualHost>
其中本地 IP 也可以包含通配符(例如 192.168.0.*)。
问题是我的 httpd.conf
文件是 controlled/maintained 服务器托管公司的 WHM,手动编辑将被覆盖。
因此,我唯一的选择是从 httpd.conf
复制现有的整个 VH 代码用于外部 IP 地址(在我的例子中有两个 VH 部分:端口 80 和 443 各一个),并将其粘贴到pre_virtualhost_global.confGlobal
文件使用 WHM 提供的包含编辑器,并将刚刚粘贴的代码的外部 IP 地址更改为内部 IP 地址。
请记住,您需要手动维护此部分(因为 WHM 在更新等时不会触及它)。