0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Go言語】ChatGPTに聞きながらローカル環境で利用可能なIPアドレスとMacアドレスを取得して一覧表示してみる

Last updated at Posted at 2024-12-27

開発で利用しているUbuntu環境のIPアドレスとMacアドレスを取得したいと思い、Go言語は書いたことがないので、ChatGPTに聞きながら実装してみた記録です。


ということでChatGPTにこんな質問をしてみました。

Go言語でローカルのネットワークインターフェースの情報を取得したい。
取得したい情報は、外部ネットワークと通信可能なIPアドレスとMacアドレスです。
有線LANが利用可能だがLANケーブルが接続されていない場合や、無線WiFiが利用可能だが無効化されている場合には取得対象とはしない。
なお、有線LANや無線WiFiのネットワークインターフェースが複数存在する場合にも対応したい。


以下の回答が得られました。

Go言語で指定された条件に合うネットワークインターフェースの情報を取得するには、標準ライブラリの net パッケージを使用して実装できます。以下のコードは、外部ネットワークに接続可能なインターフェースのIPアドレスとMACアドレスを取得する方法を示しています。

実装例

package main

import (
	"fmt"
	"net"
)

func main() {
	interfaces, err := net.Interfaces()
	if err != nil {
		fmt.Println("Error fetching interfaces:", err)
		return
	}

	for _, iface := range interfaces {
		// インターフェースが無効か、ループバックである場合はスキップ
		if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
			continue
		}

		// IPアドレス情報を取得
		addrs, err := iface.Addrs()
		if err != nil {
			fmt.Printf("Error fetching addresses for interface %s: %v\n", iface.Name, err)
			continue
		}

		for _, addr := range addrs {
			var ip net.IP

			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}

			// IPv4のみを対象
			if ip == nil || ip.IsLoopback() || !ip.IsGlobalUnicast() || ip.To4() == nil {
				continue
			}

			fmt.Printf("Interface: %s\n", iface.Name)
			fmt.Printf("  IP Address: %s\n", ip.String())
			fmt.Printf("  MAC Address: %s\n", iface.HardwareAddr.String())
		}
	}
}

提示されたコードを実行してみると、なんかたくさん表示されました。
利用しているUbuntu環境では有線LANと無線WiFiが利用可能な状態ですが、LANケーブルを接続していない有線LANは表示されておらず、無線WiFiの情報が表示されているところまでは意図通りな動作ですが、関係なさそうなインターフェースが大量に表示されています。

$ go run main.go 
Interface: wlp44s0
  IP Address: 192.168.XXX.XXX
  MAC Address: 4c:d5:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.21.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.23.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.27.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.26.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: docker0
  IP Address: 172.17.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.29.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.22.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.28.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.20.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.24.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.18.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.19.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 192.168.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX
Interface: br-XXXXXXXXXXXX
  IP Address: 172.25.XXX.XXX
  MAC Address: 02:42:XX:XX:XX:XX

関係なさそうなインターフェースは、恐らくDockerで利用しているものでは?と予想できたので、こんな風に返信しました。

Dockerで利用しているネットワークインターフェースは除外したいです。


以下の回答が得られました。

Dockerのネットワークインターフェースを除外するためには、 net.Interface 構造体の Name フィールドを使用してインターフェース名に基づくフィルタリングを追加するのが簡単です。通常、Dockerで使用されるインターフェース名は docker0br-* (ブリッジネットワーク)などのパターンです。

以下に、Dockerのネットワークインターフェースを除外するコードを示します。

改良版コード

package main

import (
	"fmt"
	"net"
	"strings"
)

func main() {
	interfaces, err := net.Interfaces()
	if err != nil {
		fmt.Println("Error fetching interfaces:", err)
		return
	}

	for _, iface := range interfaces {
		// インターフェースが無効か、ループバック、またはDocker関連の場合はスキップ
		if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 || isDockerInterface(iface.Name) {
			continue
		}

		// IPアドレス情報を取得
		addrs, err := iface.Addrs()
		if err != nil {
			fmt.Printf("Error fetching addresses for interface %s: %v\n", iface.Name, err)
			continue
		}

		for _, addr := range addrs {
			var ip net.IP

			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}

			// IPv4のみを対象
			if ip == nil || ip.IsLoopback() || !ip.IsGlobalUnicast() || ip.To4() == nil {
				continue
			}

			fmt.Printf("Interface: %s\n", iface.Name)
			fmt.Printf("  IP Address: %s\n", ip.String())
			fmt.Printf("  MAC Address: %s\n", iface.HardwareAddr.String())
		}
	}
}

// Docker関連のインターフェース名を判定するヘルパー関数
func isDockerInterface(name string) bool {
	// Dockerで使われる典型的なインターフェース名
	dockerPrefixes := []string{"docker", "br-", "veth", "tunl", "flannel"}

	for _, prefix := range dockerPrefixes {
		if strings.HasPrefix(name, prefix) {
			return true
		}
	}
	return false
}

実行してみると、意図通り無線WiFiのネットワークインターフェースのみが表示されるようになりました。

$ go run main.go 
Interface: wlp44s0
  IP Address: 192.168.XXX.XXX
  MAC Address: 4c:d5:XX:XX:XX:XX
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?