netstat查看服務端口監聽在ipv6但是通過ipv4地址可正常訪問

在Linux系統中,會發現一個有趣的現象,通過 netstat 查看監聽的服務端口時,發現有些服務 Proto(protocol協議) 項只顯示了 tcp6(代表監聽服務端口在IPv6協議), 沒有 tcp (代表監聽服務端口在IPv4協議),這時千萬不要認爲此服務就不能正常提供 IPv4 地址的服務

我們先舉個栗子來區分下現象: SSH服務:(sshd_config 配置文件中配置下列三行內容,同時監聽 IPv4 和 IPv6 協議地址)

  1. root@BJ-CentOS7 ~ # vim sshd_config
  2. AddressFamily any
  3. ListenAddress ::
  4. ListenAddress 0.0.0.0
  5. root@BJ-CentOS7 ~ # netstat -anpt | grep ssh #重啓服務發現22端口同時監聽在Ipv4和Ipv6協議
  6. tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 25105/sshd
  7. tcp6 0 0 :::22 :::* LISTEN 25105/sshd

Apache服務:(httpd 配置文件中配置以下兩行內容,同時監聽 IPv4 和 IPv6 協議地址)

  1. root@BJ-CentOS7 ~ # vim httpd.conf
  2. Listen 80
  3. Listen :::80
  4. root@BJ-CentOS7 ~ # netstat -anpt | grep httpd #重啓服務發現80端口僅監聽在Ipv6協議
  5. tcp6 0 0 :::80 :::* LISTEN 24829/httpd

分別來測試 IPv4 地址加服務端口,都是可以正常連通的:

  1. root@BJ-CentOS7 ~ # tcping 192.168.1.10 22
  2. 192.168.1.10 port 22 open.
  3. root@BJ-CentOS7 ~ # tcping 192.168.1.10 80
  4. 192.168.1.10 port 80 open.

爲什麼httpd服務看起來只是監聽了IPv6地址卻可以提供 Ipv4 地址服務呢? 從Apache官網文檔及Apache源碼中可以得到答案:(這裏主要是網上找資料瞭解到的) Apache配置監聽地址說明:http://httpd.apache.org/docs/2.4/bind.html

  1. /* If we have the unspecified IPv4 address (0.0.0.0) and
  2. * the unspecified IPv6 address (::) is next, we need to
  3. * swap the order of these in the list. We always try to
  4. * bind to IPv6 first, then IPv4, since an IPv6 socket
  5. * might be able to receive IPv4 packets if V6ONLY is not
  6. * enabled, but never the other way around.
  7. * Note: In some configurations, the unspecified IPv6 address
  8. * could be even later in the list. This logic only corrects
  9. * the situation where it is next in the list, such as when
  10. * apr_sockaddr_info_get() returns an IPv4 and an IPv6 address,
  11. * in that order.
  12. */

上述描述大概,服務監聽了 tcp6 後,tcp 也可以用的。

雖然協議顯示了 IPv6 的端口監聽,但並不代表只接受 IPv6 的連接,實際上,apache會以 mapped address (::FFFF:a.b.c.d) 映射地址方式來接受 IPv4 的連接。除了少部分平臺上,例如FreeBSD,NetBSD,OpenBSD之外, Apache 在編譯時,默認啓用了 –enable-v4-mapped 選項。所以,Apache會同時接受 IPv6 和 IPv4 的連接請求。 可以通過 httpd -V 命令來查看默認編譯參數:

  1. root@BJ-CentOS7 ~ # httpd -V
  2. AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message
  3. Server version: Apache/2.4.6 (CentOS)
  4. Server built: Apr 20 2018 18:10:38
  5. Server's Module Magic Number: 20120211:24
  6. Server loaded: APR 1.4.8, APR-UTIL 1.5.2
  7. Compiled using: APR 1.4.8, APR-UTIL 1.5.2
  8. Architecture: 64-bit
  9. Server MPM: prefork
  10. threaded: no
  11. forked: yes (variable process count)
  12. Server compiled with....
  13. -D APR_HAS_SENDFILE
  14. -D APR_HAS_MMAP
  15. -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled) #重點看這裏,啓用IPv4地址映射
  16. -D APR_USE_SYSVSEM_SERIALIZE
  17. -D APR_USE_PTHREAD_SERIALIZE
  18. -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
  19. -D APR_HAS_OTHER_CHILD
  20. -D AP_HAVE_RELIABLE_PIPED_LOGS
  21. -D DYNAMIC_MODULE_LIMIT=256
  22. -D HTTPD_ROOT="/etc/httpd"
  23. -D SUEXEC_BIN="/usr/sbin/suexec"
  24. -D DEFAULT_PIDLOG="/run/httpd/httpd.pid"
  25. -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
  26. -D DEFAULT_ERRORLOG="logs/error_log"
  27. -D AP_TYPES_CONFIG_FILE="conf/mime.types"
  28. -D SERVER_CONFIG_FILE="conf/httpd.conf"

如果我們在編譯 httpd 的時候使用 –disable-v4-mapped 參數禁止 ipv4 mapped,那麼默認情況下, httpd 會分別監聽在 ipv4 和 ipv6,而非只監聽 ipv6,如下所示:

  1. netstat -anpt | grep httpd
  2. tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 27173/httpd
  3. tcp6 0 0 :::80 :::* LISTEN 27173/httpd

總結: Linux 下 Apache 服務默認開啓了 Ipv4 地址映射,會以 (::FFFF:a.b.c.d) 映射地址方式來接受 IPv4 的連接並處理,所以通過 netstat 命令看不到端口監聽 Ipv4 地址不代表不能正常提供 Ipv4 地址服務。(發現MySQL也是同樣,在配置文件 my.cnf 中 [mysqld] 配置中加入 bind-address=0.0.0.0 即可看到正常監聽在了 Ipv4 協議地址上,但是前者也是不影響 Ipv4 地址服務使用的)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章