物联网之常见网络配置

伙伴们,你们好呀!我是老寇!跟我一起学习网络配置

由于工作原因,需要熟悉网关设备的网络配置,因此整理一下,便于查阅。

我还记得上大学的时候,老师教我们计算机网络 的时候,我没有听讲却用来学习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 ,所以用GoUbuntu来举例!

Ubuntu 网络配置路径为 /etc/netplan/01-network-manager-all.yaml,不同的Ubuntu版本可能名字有点差异,但是不影响配置使用

我们一起学习一下网络配置的参数

注意: 网关设备如果有两个LAN口,可以配置两个【LAN1LAN2】,对应网络接口名称为eth0eth1

注意: 以太网可以动态获取IPDhcp】和静态配置IPStatic

字段说明

字段 说明
version 必须为 2(Netplan 配置版本)
renderer 指定使用哪个后端,常见有 networkdNetworkManager
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

go 复制代码
package main

import (
    "errors"
    "os"
    "os/exec"
    "runtime"
    "strings"

    "gopkg.in/yaml.v3"
)

const (
    // 默认网络配置文件路径
    DEFAULT_NETPLAN_CONFIG_PATH = "/etc/netplan/01-network-manager-all.yaml"
    // LAN1 网口1
    LAN1 = "eth0"
    // LAN2 网口2
    LAN2 = "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 的 DHCP
    Dhcp4 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 的 DHCP
    DHCP4 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 是网卡的 MTU
    Mtu 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/WPA2
    Password string `yaml:"password,omitempty"`
    // Bssid 是接入点的 MAC 地址,通常用于连接特定的 AP
    Bssid 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 = 2
    netConfig.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

go 复制代码
package main

import (
    "fmt"
    "gopkg.in/yaml.v3"
    "testing"
)

func TestNetPlanConfig(t *testing.T) {
    netConfig := NewDefaultNetPlanConfig()
    netConfig.Network.Ethernets[LAN1].DHCP4 = true
    netConfig.Network.Ethernets[LAN1].MacAddress = "22:03:xz:2f:a2:1a"
    netConfig.Network.Ethernets[LAN2].DHCP4 = false
    netConfig.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 = false
    config.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)
}

运行结果

shell 复制代码
network:
    version: 2
    renderer: NetworkManager
    ethernets:
        eth0:
            dhcp4: true
            macaddress: 22:03:xz:2f:a2:1a
        eth1:
            dhcp4: false
            addresses:
                - 100.100.1.10/24
            gateway4: 100.100.1.1
            nameservers:
                addresses:
                    - 8.8.8.8
                    - 114.114.114.114
            macaddress: 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

处理器架构分为amd64arm64,所以,Go打包也有点差异

我们可以通过 arch命令查看处理器架构架构

我调试过的网关设备有 armv7l aarch64 x86_64这几种

armv7l

shell 复制代码
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

shell 复制代码
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

shell 复制代码
set GOARCH=amd64
go env -w GOARCH=amd64
set GOOS=linux
go env -w GOOS=linux
go build -o xxx .

当然,我们也可以手动修改网络配置

shell 复制代码
sudo vi /etc/netplan/01-network-manager-all.yaml
yaml 复制代码
network:
    version: 2
    renderer: NetworkManager
    ethernets:
        eth0:
            dhcp4: true
            macaddress: 22:03:xz:2f:a2:1a
        eth1:
            dhcp4: false
            addresses:
                - 100.100.1.10/24
            gateway4: 100.100.1.1
            nameservers:
                addresses:
                    - 8.8.8.8
                    - 114.114.114.114
            macaddress: 22:03:xz:2f:a2:1a
shell 复制代码
# 应用配置
sudo netplan apply
# 重启网络
sudo systemctl restart NetworkManager

如果出现这种 sudo: unable to resolve host xxx: Name or service not known 问题

请重新配置hosts

shell 复制代码
vi /etc/hosts

hosts

shell 复制代码
127.0.0.1 localhost
127.0.0.1 xxx

有些设备的处理器版本比较老,我们不能通过配置文件去修改怎么办?

armv7l32位】为例,我们只能通过命令的方式去修改,使用Go 执行命令来修改配置

静态配置IP

shell 复制代码
# 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

shell 复制代码
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"

我是老寇,我们下次再见啦!

相关推荐
上海云盾商务经理杨杨13 分钟前
2025年高防IP隐身术:四层架构拆解源站IP“消失之谜”
网络协议·tcp/ip·网络安全·架构
zhuyasen1 小时前
Sponge:一个重构Go开发体验的框架,让你在开发项目开"外挂"
go·gin·grpc
芯希望2 小时前
芯伯乐XBL6019 60V/5A DC-DC升压芯片的优质选择
大数据·人工智能·物联网·dc-dc·电子元器件·电源管理ic·xblw芯伯乐
电子科技圈2 小时前
芯科科技成为全球首家通过PSA 4级认证的物联网芯片厂商巩固其在物联网安全领域的领导地位
科技·物联网·安全·网络安全·边缘计算
点灯小铭4 小时前
基于STM32单片机的OneNet物联网环境检测系统
stm32·单片机·物联网·毕业设计·课程设计
郭京京7 小时前
go语言函数
go
无聊的HZ7 小时前
HTTP 请求返回状态码和具体含义?200、400、403、404、502、503、504等
网络·网络协议·http
DemonAvenger8 小时前
微服务通信:Go网络编程实战
网络协议·架构·go
程序员爱钓鱼9 小时前
Go语言实战案例:文件上传服务
后端·go·trae