最近将 OS 升级到 Red Hat Enterprise Linux 6.x,结果有一个功能就莫名的坏掉了,该功能很普通,就只是将 A 机器上的图片用 Curl (PUT) 的方式,丢到 B 机器上,但是它一执行就会收到 Error 500,於是我查看了 A 机器上的 Error log ,发现一个错误讯息: Failed to connect to 800:c:f1:806:2001:a Network is unreachable
我尝试在 A 机器上手动执行 curl "http://B/xxx/xxx" -X PUT ...
,直接用 curl 方式来上传图片,而这个方式是可以正常运做的,图片有被传到 B 机器上,但是这个结果反而让我很困扰,Curl 指令可以运作,但是 PHP 的 curl 却没办法动。
第一时间,我就先用指令 host B
来查机器 B 的 IP,看看他的 IP 是否正常,而我得到下面这个结果,该 domain 同时存在 IPv4 与 IPv6,看来这就是问题的所在,但是为什么程式会使用 IPv6 ,而不使用 IPv4 呢 ?
- host B
- B has address x4.2x3.x89.106
- B IPv6 address 800:c:f1:806:2001:a
虽然我在 A 机器中可以取得 B 机器的 IPv6 ,但是当 A 要 connect 至 B 的时候, A 会先将 Request 丢给 Router ,而那台 Router 没办法正确的处理 IPv6 格式,造成连线中断,所以我们必须强迫程式使用 IPv4 ,而不要用 IPv6 。
我们可以使用 network 这个指令,来分辨出 Router 是否可以正确的解析出 IPv6 格式,看下面这个范例 , IP 变成很奇怪的格式,代表它不支援 IPv6。
- $ nslookup 800:c:f1:806:2001:a
- Server: 192.168.0.20
- Address: 192.168.0.20#53
- Non-authoritative answer:
- 8.6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.z.0.1.0.0.4.0.0.8.6.4.0.1.2.ip6.arpa name = tx-xn-x6a.2e101.net.
Solve IPv6 Problem
PHP Curl 内建就有提供一个 option ,可以强迫系统的 Domain Name resolution 使用 IPv4,方法很简单,只要多一行语法就搞定了,加了下面这句程式后, PHP Curl 就可以正确的将 domain 转到 IPv4 ,功能也就正常了。
- curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
ifconfig 移除 IPv6
跟同事讨论后,同事也提出另一个方法,就是将 B 机器的 IPv6 下掉,因为我们的系统还不需要使用 IPv6 ,自然也不用支援 IPv6 这种 IP。
我们先检查 B 机器上的网路设定,下指令 ifconfig 后会看到 inet6 相关设定,有这个设定就是指这台机器的 IP 支援 IPv6 。
- enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
- inet 192.168.0.4 netmask 255.255.255.0 broadcast 192.168.56.255
- inet6 fe10::a20:27ff:fec:22ae prefixlen 64 scopeid 0x20<link>
- ether 01:00:17:0c:a2:0e txqueuelen 1000 (Ethernet)
- RX packets 7483810 bytes 849228602 (809.8 MiB)
- RX errors 0 dropped 0 overruns 0 frame 0
- TX packets 21513200 bytes 50057076506 (46.6 GiB)
- TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
接著用以下方式来移除 inet6 IPv6 :
- 编辑 /etc/sysconfig/network 加入以下两个设定
- NETWORKING_IPV6=no
- IPV6_AUTOCONF=no
- 编辑 /etc/sysctl.conf 加入以下设定
- net.ipv6.conf.eth0.disable_ipv6 = 1
- sudo reboot 重开机
重开机后,再用 ifconfig
检查 inet6 是否已经被移除。
- enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
- inet 192.168.0.4 netmask 255.255.255.0 broadcast 192.168.56.255
- ether 01:00:17:0c:a2:0e txqueuelen 1000 (Ethernet)
- RX packets 7483810 bytes 849228602 (809.8 MiB)
- RX errors 0 dropped 0 overruns 0 frame 0
- TX packets 21513200 bytes 50057076506 (46.6 GiB)
- TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0