物联网之常见网络配置

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

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

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

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

相关推荐
jingfeng5143 分钟前
网络编程 socket——TCP
网络·tcp/ip·php
九州ip动态9 分钟前
手机网络IP归属地更改方法总结
网络·tcp/ip·智能手机
蒜鸟~蒜鸟15 分钟前
手把手教你搭建 UDP 多人聊天室(附完整源码)
网络·网络协议·udp
静谧之心17 分钟前
从“叠加”到“重叠”:Overlay 与 Overlap 双引擎驱动技术性能优化
linux·网络·设计模式·性能优化·golang·overlay·overlap
科技D人生1 小时前
物联网开发学习总结(1)—— IOT 设备 OTA 升级方案
物联网·iot 开发·ota 升级·物联网设备ota升级
源代码•宸1 小时前
网络流量分析——使用Wireshark进行分析
网络·经验分享·测试工具·wireshark
mit6.8241 小时前
[re_2] rpc|http|nginx|protobuf|
网络·c++
now_cn2 小时前
构建线上门户的核心三要素:域名、DNS与IP 全面解析
网络·网络协议·tcp/ip
无敌的牛2 小时前
网络通信IP细节
服务器·网络·tcp/ip
徐子元竟然被占了!!4 小时前
针对 “TCP 会话维持与身份验证” 的攻击
网络·网络协议·tcp/ip