伙伴们,你们好呀!我是老寇!跟我一起学习网络配置
由于工作原因,需要熟悉网关设备的网络配置,因此整理一下,便于查阅。
我还记得上大学的时候,老师教我们计算机网络 的时候,我没有听讲却用来学习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
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
处理器架构分为amd64
和arm64
,所以,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
有些设备的处理器版本比较老,我们不能通过配置文件去修改怎么办?
以armv7l
【32位
】为例,我们只能通过命令
的方式去修改,使用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"
我是老寇,我们下次再见啦!