物联网之常见网络配置
伙伴们,你们好呀!我是老寇!跟我一起学习网络配置
由于工作原因,需要熟悉网关设备的网络配置,因此整理一下,便于查阅。
我还记得上大学的时候,老师教我们计算机网络的时候,我没有听讲却用来学习Java。因此,对计算机网络不熟悉,这也间接导致在工作中遇到网络相关的问题束手无措,通过翻阅资料和同事交流才搞明白,我写的这个,对新手来说,应该有一定的借鉴意义。
“往者不可谏来者犹可追”。这句话出自《论语》,意思是 过去的事情已无法劝谏挽回。未来的事情还能够来得及追改 很多事情都是需要自己亲身经历的,也是无法逃避的,这可能就是命中注定的宿命吧!所以,与其逃避不如坦然面对,直面自己的惨淡人生,活出属于自己的精彩!
在科技高速发展的今天,几乎每个人都用上了智能手机,智能手机只要是上网,就需要用到 网络
一、常见网络配置名词
1.IP地址
IP地址就像你家在互联网上的“门牌号”,有了它,数据才能准确找到你的设备并传输信息。
常见形式
- IPv4:四组数字,如
192.168.1.1
(总量有限,类似电话号码不够用)。 - IPv6:更长,如
2001:0db8:85a3::8a2e:0370:7334
(解决数量不足问题,未来主流)。
2.网关
网关就像你家的“大门”,所有设备想连接外部互联网(如刷视频、看网页),都必须先经过它才能出入。
网关能把你家所有设备的“内部IP”(如 192.168.1.18
)统一转换成一个对外的“公网IP”,保护隐私且节省地址。
子网掩码
子网掩码像一把“尺子”,用来量出IP地址中哪部分是“小区名”(网络区域),哪部分是“门牌号”(具体设备),让路由器知道该在本地送货还是发往外省。
举例 192.168.1.18/24
IP地址:192.168.1.18
子网掩码:255.255.255.0
子网掩码长度:24
问题:子网掩码为什么是 255.255.255.0
Mac地址
MAC地址是设备网卡的“身份证号”(全球唯一且不可更改),用来在本地网络(如你家Wi-Fi)中精准识别每一台手机/电脑/打印机,实现“面对面”直连通信。
二、动手实践
我们一起使用代码的方式修改网络配置,工作中使用Go开发,操作系统为Ubuntu,所以用Go和Ubuntu来举例!
Ubuntu网络配置路径为 /etc/netplan/01-network-manager-all.yaml
,不同的Ubuntu版本可能名字有点差异,但是不影响配置使用
我们一起学习一下网络配置的参数
注意: 网关设备如果有两个LAN
口,可以配置两个【LAN1
和LAN2
】,对应网络接口名称为eth0
和eth1
注意: 以太网
可以动态获取IP
【Dhcp
】和静态配置IP
【Static
】
字段说明
字段 | 说明 |
---|---|
version | 必须为 2 (Netplan 配置版本) |
renderer | 指定使用哪个后端,常见有 networkd 或 NetworkManager |
ethernets | 配置物理网卡 |
wifis | 配置无线接口(需 NetworkManager 支持) |
Ethernet 参数配置示例
参数 | 类型 | 示例 | 说明 |
---|---|---|---|
dhcp4 | bool | true / false | 是否启用 IPv4 DHCP |
dhcp6 | bool | true / false | 是否启用 IPv6 DHCP |
addresses | 列表 | [192.168.1.100/24] | 分配静态 IP 地址和子网掩码 |
gateway4 | 字符串 | 192.168.1.1 | IPv4 默认网关 |
gateway6 | 字符串 | fe80::1 | IPv6 默认网关 |
nameservers.addresses | 列表 | [8.8.8.8, 1.1.1.1] | DNS 服务器列表 |
nameservers.search | 列表 | [example.com] | DNS 搜索域列表 |
optional | bool | true | 设置为可选(不影响系统启动) |
macaddress | 字符串 | aa:bb:cc:dd:ee:ff | 指定网卡的 MAC 地址 |
mtu | 整数 | 1500 | 设置 MTU 值 |
routes.to | 列表 | 10.0.0.0/8 | 目标网段 |
routes.via | 列表 | 192.168.1.1 | 下一跳地址(gateway),数据包将被发送到这个网关去转发 |
routes.metric | 列表 | 100 | 路由优先级,数字越小优先级越高。多个匹配路径中会优先使用 metric 较低的 |
Wifi 参数配置示例
参数 | 类型 | 示例 | 说明 |
---|---|---|---|
dhcp4 | boolean | true / false | 是否启用 IPv4 的 DHCP |
dhcp6 | boolean | true / false | 是否启用 IPv6 的 DHCP |
optional | boolean | true | 将接口标记为“非关键”,启动时不阻塞 |
addresses | list | [192.168.1.100/24] | 分配静态 IP 地址 |
gateway4 | string | 192.168.1.1 | 设置 IPv4 默认网关 |
gateway6 | string | fe80::1 | 设置 IPv6 默认网关 |
nameservers.addresses | list | [8.8.8.8, 1.1.1.1] | 设置 DNS 服务器 |
macaddress | string | aa:bb:cc:dd:ee:ff | 设置 MAC 地址(MAC Spoofing) |
routes.to | 列表 | 10.0.0.0/8 | 目标网段 |
routes.via | 列表 | 192.168.1.1 | 下一跳地址(gateway),数据包将被发送到这个网关去转发 |
routes.metric | 列表 | 100 | 路由优先级,数字越小优先级越高。多个匹配路径中会优先使用 metric 较低的 |
access-points.<SSID>.password | string | "12345678" | Wi-Fi 密码,支持 WPA/WPA2 |
access-points.<SSID>.mode | string | "infrastructure" / "adhoc" | 连接模式(基础设施或点对点) |
access-points.<SSID>.bssid | string | aa:bb:cc:dd:ee:ff | 连接特定 AP 的 MAC 地址(仅在多 AP 场景用) |
access-points.<SSID>.band | string | "2.4GHz" / "5GHz" | 频段(可选) |
access-points.<SSID>.channel | int | 6 | 频道(仅用于 Ad-Hoc) |
access-points.<SSID>.hidden | boolean | true | SSID 是否为隐藏 Wi-Fi |
net.go
package mainimport ("errors""os""os/exec""runtime""strings""gopkg.in/yaml.v3"
)const (// 默认网络配置文件路径DEFAULT_NETPLAN_CONFIG_PATH = "/etc/netplan/01-network-manager-all.yaml"// LAN1 网口1LAN1 = "eth0"// LAN2 网口2LAN2 = "eth1"
)type NetworkConfig struct {Address string `json:"address"`Gateway string `json:"gateway"`Dns string `json:"dns"`MacAddress string `json:"macAddress"`
}type NetPlanConfig struct {Network struct {// Version 必须为 2,表示 Netplan 配置的版本Version int8 `yaml:"version,omitempty"`// Renderer 指定使用哪个后端,常见有 networkd 或 NetworkManager// NetworkManager 适用于桌面环境// networkd 适用于服务器环境Renderer string `yaml:"renderer,omitempty"`// Ethernets 是一个 map,键为网卡名称,值为 Ethernet 配置// 例如:`"eth0": { ... }`// 这里的网卡名称可以是物理网卡名或虚拟网卡名// 例如:`"eth0"`、`"eth1"`、`"wlan0"` 等Ethernets map[string]*Ethernet `yaml:"ethernets,omitempty"`// 如果需要配置无线网卡,请使用 `wifis` 字段Wifis map[string]*Wifi `yaml:"wifis,omitempty"`} `yaml:"network,omitempty"`
}// Wifi 无线网络接口配置结构体【Wi-Fi】
type Wifi struct {// DHCP4 和 DHCP6 分别表示是否启用 IPv4 和 IPv6 的 DHCPDhcp4 bool `yaml:"dhcp4"`Dhcp6 bool `yaml:"dhcp6,omitempty"`// Optional 表示该接口是否为可选的,设置为 true 时启动时Optional bool `yaml:"optional,omitempty"`// Address 配置 IP 地址Addresses []string `yaml:"addresses,omitempty"`// Gateway4 和 Gateway6 分别表示 IPv4 和 IPv6 的默认网关Gateway4 string `yaml:"gateway4,omitempty"`Gateway6 string `yaml:"gateway6,omitempty"`// Nameservers 包含 DNS 服务器地址Nameservers struct {// Addresses 是 DNS 服务器地址列表Addresses []string `yaml:"addresses,omitempty"`} `yaml:"nameservers,omitempty"`// MacAddress 是网卡的 MAC 地址MacAddress string `yaml:"macaddress,omitempty"`// Routes 是一个路由列表,每个路由包含目标地址、网关和优先级Routes Route `yaml:"routes,omitempty"`// AccessPoints 是一个 map,键为 SSID,值为 AccessPoint 配置AccessPoints map[string]AccessPoint `yaml:"access-points,omitempty"`
}// Ethernet 网卡结构体【以太网】
type Ethernet struct {// DHCP4 和 DHCP6 分别表示是否启用 IPv4 和 IPv6 的 DHCPDHCP4 bool `yaml:"dhcp4"`DHCP6 bool `yaml:"dhcp6,omitempty"`// Addresses 是一个字符串数组,表示分配的静态 IP 地址和子网掩码Addresses []string `yaml:"addresses,omitempty"`// Gateway4 和 Gateway6 分别表示 IPv4 和 IPv6 的默认网关Gateway4 string `yaml:"gateway4,omitempty"`Gateway6 string `yaml:"gateway6,omitempty"`// Nameservers 包含 DNS 服务器地址和搜索域Nameservers struct {// Addresses 是 DNS 服务器地址列表Addresses []string `yaml:"addresses,omitempty"`// Search 是 DNS 搜索域列表Search []string `yaml:"search,omitempty"`} `yaml:"nameservers,omitempty"`// Routes 是一个路由列表,每个路由包含目标地址、网关和优先级Routes Route `yaml:"routes,omitempty"`// Optional 表示该接口是否为可选的,设置为 true 时启动时不会阻塞Optional bool `yaml:"optional,omitempty"`// MacAddress 是网卡的 MAC 地址MacAddress string `yaml:"macaddress,omitempty"`// Mtu 是网卡的 MTUMtu int `yaml:"mtu,omitempty"`
}// Route 路由
type Route struct {// To 是目标地址或网段To string `yaml:"to,omitempty"`// Via 是路由的网关地址Via string `yaml:"via,omitempty"`// Metric 是路由的优先级,数字越小优先级越高Metric int `yaml:"metric,omitempty"`
}// AccessPoint 无线接入点配置结构体
type AccessPoint struct {// Mode 是连接模式,可能的值有 "infrastructure"(基础设施模式)或 "adhoc"(点对点模式)Mode string `yaml:"mode,omitempty"`// Password 是 Wi-Fi 密码,支持 WPA/WPA2Password string `yaml:"password,omitempty"`// Bssid 是接入点的 MAC 地址,通常用于连接特定的 APBssid string `yaml:"bssid,omitempty"`// Band 是无线频段,可能的值有 "2.4GHz" 或 "5GHz"Band string `yaml:"band,omitempty"`// Channel 是无线频道,通常用于 Ad-Hoc 模式Channel int `yaml:"channel,omitempty"`// Hidden 是是否隐藏 SSID,通常用于 Ad-Hoc 模式Hidden bool `yaml:"hidden,omitempty"`
}func NewDefaultNetPlanConfig() *NetPlanConfig {netConfig := &NetPlanConfig{}netConfig.Network.Version = 2netConfig.Network.Renderer = "NetworkManager"// 两个网口netConfig.Network.Ethernets = make(map[string]*Ethernet, 2)netConfig.Network.Ethernets[LAN1] = &Ethernet{}netConfig.Network.Ethernets[LAN2] = &Ethernet{}return netConfig
}func SaveNetPlanConfig(buf []byte, path string) error {err := os.WriteFile(path, buf, 0644)if err != nil {return errors.New("写入网络配置文件失败,错误信息:" + err.Error())}return nil
}func ApplyNetPlanConfig() error {err := validateOS()if err != nil {return err}err = exec.Command("netplan", "apply").Run()if err != nil {return errors.New("应用网络配置失败,错误信息:" + err.Error())}return nil
}func ReadNetPlanConfig(path string) (*NetPlanConfig, error) {data, err := os.ReadFile(path)if err != nil {return nil, errors.New("读取网络配置文件失败,错误信息:" + err.Error())}netConfig := &NetPlanConfig{}err = yaml.Unmarshal(data, netConfig)if err != nil {return nil, errors.New("网络配置反序列化失败,错误信息:" + err.Error())}return netConfig, nil
}func GetMacAddress() (string, error) {err := validateOS()if err != nil {return "", err}output, err := exec.Command("sh", "-c", `ip link show eth0 | awk '/ether/ {print $2}'`).Output()if err != nil {return "", errors.New("获取MAC地址失败,错误信息:" + err.Error())}return strings.TrimSpace(string(output)), nil
}func GetIpAddress() (string, error) {err := validateOS()if err != nil {return "", err}output, err := exec.Command("sh", "-c", `ip addr show eth0 | grep "inet " | awk '{print $2}' | cut -d'/' -f1`).Output()if err != nil {return "", errors.New("获取IP地址失败,错误信息:" + err.Error())}return strings.TrimSpace(string(output)), nil
}func GetGateway() (string, error) {err := validateOS()if err != nil {return "", err}output, err := exec.Command("sh", "-c", `ip route | grep default | grep eth0 | awk '{print $3}'`).Output()if err != nil {return "", errors.New("获取网关失败,错误信息:" + err.Error())}return strings.TrimSpace(string(output)), nil
}func GetNetmask() (string, error) {err := validateOS()if err != nil {return "", err}output, err := exec.Command("sh", "-c", `ip addr show eth0 | grep "inet " | awk '{print $2}' | cut -d'/' -f2`).Output()if err != nil {return "", errors.New("获取子网掩码长度失败,错误信息:" + err.Error())}return strings.TrimSpace(string(output)), nil
}func GetNetworkConfig(path string) (*NetworkConfig, error) {config, err := getNetPlanConfig(path)if err != nil {return nil, err}ethernet := config.Network.Ethernets[LAN1]return &NetworkConfig{Address: ethernet.Addresses[0],Gateway: ethernet.Gateway4,Dns: strings.Join(ethernet.Nameservers.Addresses, ","),MacAddress: ethernet.MacAddress,}, nil
}func getNetPlanConfig(path string) (*NetPlanConfig, error) {data, err := os.ReadFile(path)if err != nil {return nil, errors.New("获取网络配置失败,错误信息:" + err.Error())}netConfig := &NetPlanConfig{}err = yaml.Unmarshal(data, netConfig)return netConfig, nil
}func validateOS() error {if runtime.GOOS != "linux" {return errors.New("网关在 " + runtime.GOOS + " 操作系统上不支持该操作")}return nil
}
net_test.go
package mainimport ("fmt""gopkg.in/yaml.v3""testing"
)func TestNetPlanConfig(t *testing.T) {netConfig := NewDefaultNetPlanConfig()netConfig.Network.Ethernets[LAN1].DHCP4 = truenetConfig.Network.Ethernets[LAN1].MacAddress = "22:03:xz:2f:a2:1a"netConfig.Network.Ethernets[LAN2].DHCP4 = falsenetConfig.Network.Ethernets[LAN2].MacAddress = "22:03:xz:2f:a2:1a"netConfig.Network.Ethernets[LAN2].Addresses = []string{"100.100.1.10/24"}netConfig.Network.Ethernets[LAN2].Gateway4 = "100.100.1.1"netConfig.Network.Ethernets[LAN2].Nameservers.Addresses = []string{"8.8.8.8", "114.114.114.114"}out, err := yaml.Marshal(netConfig)if err != nil {fmt.Println(err.Error())}fmt.Println(string(out))err = SaveNetPlanConfig(out, "ethernets.yaml")if err != nil {fmt.Println(err.Error())}err = ApplyNetPlanConfig()if err != nil {fmt.Println(err.Error())}config, err := ReadNetPlanConfig("ethernets.yaml")if err != nil {fmt.Println(err.Error())return}fmt.Println(config.Network.Ethernets[LAN1].DHCP4)config.Network.Ethernets[LAN1].DHCP4 = falseconfig.Network.Ethernets[LAN1].Addresses = []string{"192.168.1.10/24"}config.Network.Ethernets[LAN1].Gateway4 = "192.168.1.1"config.Network.Ethernets[LAN1].Nameservers.Addresses = []string{"8.8.8.8", "114.114.114.114"}out, err = yaml.Marshal(config)err = SaveNetPlanConfig(out, "ethernets.yaml")if err != nil {fmt.Println(err.Error())return}fmt.Println(GetNetmask())fmt.Println(GetMacAddress())fmt.Println(GetIpAddress())fmt.Println(GetGateway())networkConfig, err := GetNetworkConfig("ethernets.yaml")if err != nil {fmt.Println(err.Error())return}fmt.Println(networkConfig.Dns)fmt.Println(networkConfig.Gateway)fmt.Println(networkConfig.Address)fmt.Println(networkConfig.MacAddress)
}
运行结果
network:version: 2renderer: NetworkManagerethernets:eth0:dhcp4: truemacaddress: 22:03:xz:2f:a2:1aeth1:dhcp4: falseaddresses:- 100.100.1.10/24gateway4: 100.100.1.1nameservers:addresses:- 8.8.8.8- 114.114.114.114macaddress: 22:03:xz:2f:a2:1a网关在 windows 操作系统上不支持该操作
true网关在 windows 操作系统上不支持该操作网关在 windows 操作系统上不支持该操作网关在 windows 操作系统上不支持该操作网关在 windows 操作系统上不支持该操作
8.8.8.8,114.114.114.114
192.168.1.1
192.168.1.10/24
22:03:xz:2f:a2:1a
处理器架构分为amd64
和arm64
,所以,Go打包也有点差异
我们可以通过 arch
命令查看处理器架构架构
我调试过的网关设备有 armv7l
aarch64
x86_64
这几种
armv7l
set GOARCH=arm
go env -w GOARCH=arm
set GOARM=7
go env -w GOARM=7
set GOOS=linux
go env -w GOOS=linux
go build -o xxx .
aarch64
set GOARCH=arm
go env -w GOARCH=arm
set GOARM=8
go env -w GOARM=8
set GOOS=linux
go env -w GOOS=linux
go build -o xxx .
x86_64
set GOARCH=amd64
go env -w GOARCH=amd64
set GOOS=linux
go env -w GOOS=linux
go build -o xxx .
当然,我们也可以手动修改网络配置
sudo vi /etc/netplan/01-network-manager-all.yaml
network:version: 2renderer: NetworkManagerethernets:eth0:dhcp4: truemacaddress: 22:03:xz:2f:a2:1aeth1:dhcp4: falseaddresses:- 100.100.1.10/24gateway4: 100.100.1.1nameservers:addresses:- 8.8.8.8- 114.114.114.114macaddress: 22:03:xz:2f:a2:1a
# 应用配置
sudo netplan apply
# 重启网络
sudo systemctl restart NetworkManager
如果出现这种 sudo: unable to resolve host xxx: Name or service not known
问题
请重新配置hosts
vi /etc/hosts
hosts
127.0.0.1 localhost
127.0.0.1 xxx
有些设备的处理器版本比较老,我们不能通过配置文件去修改怎么办?
以armv7l
【32位
】为例,我们只能通过命令
的方式去修改,使用Go
执行命令
来修改配置
静态配置IP
# IP地址: 192.168.1.18/24
# 网关:192.168.1.1
# DNS:8.8.8.8
nmcli connection delete "eth0 static"
nmcli connection add con-name "eth0 static" ifname eth0 type ethernet
nmcli connection modify "eth0 static" ipv4.method manual ipv4.addresses 192.168.1.18/24 ipv4.gateway 192.168.1.1 ipv4.dns 8.8.8.8
nmcli connection up "eth0 static"
nmcli connection delete "eth0 dhcp"
动态获取IP
nmcli connection delete "eth0 dhcp"
nmcli connection add con-name "eth0 dhcp" ifname eth0 type ethernet
nmcli connection modify "eth0 dhcp" ipv4.method auto
nmcli connection up "eth0 dhcp"
nmcli connection delete "eth0 static"
我是老寇,我们下次再见啦!