读取网络接口的配置文件

网络配置有四个核心元素:接口的IP地址、接口的网络掩码、主机的DNS服务器配置以及主机的默认网关或默认路由配置。这里存在一个问题:目前没有原生并可移植Go代码来获取以上信息。这表明在UNIX系统的主机上,没有可移植的代码来查询DNS配置和默认网关信息。

因此在本节中,将介绍如何使用Go代码读取UNIX系统的网络接口配置。为此,我将介绍两个可移植的程序,用于查询有关网络接口的配置。

第一个程序netConfig.go的源代码由三部分组成。

以下Go代码是netConfig.go的第一部分:

  1. package main
  2. import (
  3. "fmt"
  4. "net"
  5. )
  6. func main() {
  7. interfaces, err := net.Interfaces()
  8. if err != nil {
  9. fmt.Println(err)
  10. return
  11. }

函数net.Interfaces()的作用是将当前计算机的所有接口信息通过一个切片数据结构返回,切片的数据元素类型为net.Interface。此切片将用于获取接口的信息。

代码netConfig.go的第二个部分包含以下Go代码:

  1. for _, i := range interfaces {
  2. fmt.Printf("Interface: %v\n", i.Name)
  3. byName, err := net.InterfaceByName(i.Name)
  4. if err != nil {
  5. fmt.Println(err)
  6. }

在上面的代码中,使用net.Interface类型来访问切片的每个元素,获取所需的信息。

  1. > ```go
  2. > addresses, err := byName.Addrs()
  3. > for k, v := range addresses {
  4. > fmt.Printf("Interface Address #%v: %v\n", k, v.String())
  5. > }
  6. > fmt.Println()
  7. > }
  8. > }
  9. >

在操作系统为macOS High Sierra的主机上,使用版本为1.10的Go运行环境执行netConfig.go会得到以下输出:

  1. $ go run netConfig.go
  2. Interface: lo0
  3. Interface Address #0: 127.0.0.1/8
  4. Interface Address #1: ::1/128
  5. Interface Address #2: fe80::1/64
  6. Interface: gif0
  7. Interface: stf0
  8. Interface: XHC20
  9. Interface: en0
  10. Interface Address #0: fe80::18fa:901a:ea9:eb5f/64
  11. Interface Address #1: 192.168.1.200/24
  12. Interface Address #2: 2a02:587:3006:b800:1cb8:bf1b:b154:4d0c/64
  13. Interface Address #3: 2a02:587:3006:b800:d84a:f0c:c932:35d1/64
  14. Interface: en1
  15. Interface: p2p0
  16. Interface: awdl0
  17. Interface: en2
  18. Interface: en3
  19. Interface: bridge0
  20. Interface: utun0
  21. Interface Address #0: fe80::2514:c3a3:ca83:e1c6/64
  22. Interface: utun1
  23. Interface Address #0: fe80::4e0b:a9a6:9abe:81a4/64
  24. Interface: en5
  25. Interface Address #0: fe80::1cb4:a29e:97bc:6fb5/64
  26. Interface Address #1: 169.254.72.59/16

如上,因为现代计算机配置很多网络接口,同时程序支持IPv4和IPv6协议,netConfig.go返回了很多接口和IP地址信息。

在操作系统为Debian Linux的主机上,使用版本为1.7.4的Go运行环境执行netConfig.go会得到以下输出:

  1. $ go run netConfig.go
  2. Interface: lo
  3. Interface Address #0: 127.0.0.1/8
  4. Interface Address #1: ::1/128
  5. Interface: dummy0
  6. Interface: eth0
  7. Interface Address #0: 10.74.193.253/24
  8. Interface Address #1: 2a01:7e00::f03c:91ff:fe69:1381/64
  9. Interface Address #2: fe80::f03c:91ff:fe69:1381/64
  10. Interface: teql0
  11. Interface: tunl0
  12. Interface: gre0
  13. Interface: gretap0
  14. Interface: erspan0
  15. Interface: ip_vti0
  16. Interface: ip6_vti0
  17. Interface: sit0
  18. Interface: ip6tnl0
  19. Interface: ip6gre0

可以看到有的网络接口没有显示网络地址,可能的主要原因是接口是关闭的,或者该接口没有进行配置。

并非所有列出的网络接口都关联了真正的硬件网络设备。最典型的例子是lo0接口,它是环回设备。环回设备是一种特殊的虚拟网络接口,主机可以通过该接口与自身通信。

下一个Go程序netCapabilities.go的代码也分为三部分。程序netCapabilities.go的目的是打印UNIX操作系统的主机上每个网络接口的功能。

程序netCapabilities.go使用结构net.Interface的字段,定义如下:

  1. type Interface struct {
  2. Index int
  3. MTU int
  4. Name string
  5. HardwareAddr HardwareAddr
  6. Flags Flags
  7. }

Go程序netCapabilities.go的第一部分如下:

  1. package main
  2. import (
  3. "fmt"
  4. "net"
  5. )
  1. > ```go
  2. > func main() {
  3. > interfaces, err := net.Interfaces()
  4. >
  5. > if err != nil {
  6. > fmt.Print(err)
  7. > return
  8. > }
  9. >
  1. > ```go
  2. > for _, i := range interfaces {
  3. > fmt.Printf("Name: %v\n", i.Name)
  4. > fmt.Println("Interface Flags:", i.Flags.String())
  5. > fmt.Println("Interface MTU:", i.MTU)
  6. > fmt.Println("Interface Hardware Address:", i.HardwareAddr)
  7. > fmt.Println()
  8. > }
  9. > }
  10. >

在操作系统为macOS High Sierra的主机上运行netCapabilities.go生成以下输出:

  1. $ go run netCapabilities.go
  2. Name: lo0
  3. Interface Flags: up|loopback|multicast
  4. Interface MTU: 16384
  5. Interface Hardware Address:
  6. Name: gif0
  7. Interface Flags: pointtopoint|multicast
  8. Interface MTU: 1280
  9. Interface Hardware Address:
  10. Name: stf0
  11. Interface Flags: 0
  12. Interface MTU: 1280
  13. Interface Hardware Address:
  14. Name: XHC20
  15. Interface Flags: 0
  16. Interface MTU: 0
  17. Interface Hardware Address:
  18. Name: en0
  19. Interface Flags: up|broadcast|multicast
  20. Interface MTU: 1500
  21. Interface Hardware Address: 98:5a:eb:d7:84:cd
  22. Name: en1
  23. Interface Flags: up|broadcast|multicast
  24. Interface MTU: 1500
  25. Interface Hardware Address: d0:03:4b:cf:84:d3
  26. Name: p2p0
  27. Interface Flags: broadcast|multicast
  28. Interface MTU: 2304
  29. Interface Hardware Address: 02:03:4b:cf:84:d3
  30. Name: awdl0
  31. Interface Flags: broadcast|multicast
  32. Interface MTU: 1484
  33. Interface Hardware Address: 02:ac:d4:3b:d9:29
  34. Name: en2
  35. Interface Flags: up|broadcast|multicast
  36. Interface MTU: 1500
  37. Interface Hardware Address: 0a:00:00:a5:32:b0
  38. Name: en3
  39. Interface Flags: up|broadcast|multicast
  40. Interface MTU: 1500
  41. Interface Hardware Address: 0a:00:00:a5:32:b1
  42. Name: bridge0
  43. Interface Flags: up|broadcast|multicast
  44. Interface MTU: 1500
  45. Interface Hardware Address: 0a:00:00:a5:32:b0
  46. Name: utun0
  47. Interface Flags: up|pointtopoint|multicast
  48. Interface MTU: 2000
  49. Interface Hardware Address:
  50. Name: utun1
  51. Interface Flags: up|pointtopoint|multicast
  52. Interface MTU: 1380
  53. Interface Hardware Address:
  54. Name: en5
  55. Interface Flags: up|broadcast|multicast
  56. Interface MTU: 1500
  57. Interface Hardware Address: 6e:72:e7:1b:cd:5f

在Debian Linux操作系统的主机上执行netCapabilities.go将输出类似的结果。

最后,如果对查找主机的默认网关感兴趣,可以在shell运行环境中执行netstat -nr命令查看,或在Go程序中使用exec.Command()执行该命令,并通过pipeexec.CombinedOutput()以文本的形式获取其输出,并打印。然而,这种方式既不优雅也不完美。