在本文中,我将探讨如何为连接到Linux主机的设备提供网络访问。将使用一个实际的故障排查案例来详细说明这个过程,最终实现用脚本完成各项检查和配置工作。
背景:
客户有一个RK3568主板,运行Ubuntu Linux系统。该主板有两个以太网接口:假设定义eth0(内网)和eth1(外网)。客户希望通过RK3568为连接到eth0的Windows PC提供外部网络访问。
简而言之就是Windows PC通过网线连接到RK3568主板的内网口 ,就能在Windows PC访问www.baidu.com(外网)。
Windows PC设置:
PC是Windows 10,需要通过图形界面或命令行来设置默认网关:
- 打开“控制面板”。
- 选择“网络和共享中心”。
- 在左侧,点击“更改适配器设置”。
- 右键点击网络连接(可能是“以太网”或类似名称),然后选择“属性”。
- 在列表中找到并双击“Internet 协议版本 4 (TCP/IPv4)”。
- 选择“使用下面的IP地址”并输入你的IP地址、子网掩码。在“默认网关”中,输入
192.168.52.2
。 - 点击“确定”保存设置。
#执行ipconfig简单确认下 ipconfig
RK3568 Ubuntu设置:
1. 故障排查步骤:
1.配置NAT(网络地址转换)
确保在Linux主机上设置了正确的NAT规则。
root@xxx:/# iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE iptables v1.8.4 (legacy): can't initialize iptables table `nat': Table does not exist (do you need to insmod?) Perhaps iptables or your kernel needs to be upgraded.
很好这一步就出错了 查下资料 我之前调试RK3399 docker的时候加过iptables nat config , 想起来了 需要在kernel 打开config功能。
那我们先解决iptables nat命令的问题 , 先让kernel boot支持 打开kernel/arch/arm64/configs/rockchip_linux_defconfig
进行增加 , 下面有些内容可能不是 先不管了 把配置拷进去 后面再研究。
+CONFIG_TUN=y + +#------------iptables +#CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_POSIX_MQUEUE=y +CONFIG_CGROUP_PIDS=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_CGROUP=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_INET_ESP=y +CONFIG_BRIDGE_NETFILTER=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_IPVS=y +CONFIG_IP_VS=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_RR=y +CONFIG_IP_VS_NFCT=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_BRIDGE=y +CONFIG_CGROUP_NET_PRIO=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_THIN_PROVISIONING=y +CONFIG_DUMMY=y +CONFIG_MACVLAN=y +CONFIG_IPVLAN=y +CONFIG_VXLAN=y +CONFIG_VETH=y +CONFIG_BTRFS_FS=y +CONFIG_BTRFS_FS_POSIX_ACL=y
编译kernel boot.img 重新烧录到RK3568 系统中, 重启。
重新验证下功能是否可以被执行 , 执行完没有任何报错 这一步完成。
root@xxx:/# iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
2. 启用IP转发:
Linux主机必须允许IP转发。
echo 1 > /proc/sys/net/ipv4/ip_forward
并确保在 /etc/sysctl.conf
文件中有以下行:
net.ipv4.ip_forward=1
3. 检 查配置双网口环境:
如果没有一个接口在与试图添加的网关相同的子网上,可能需要配置一个接口来使用这个子网。例如,如果有一个名为 eth0
的接口,可以使用以下命令为其分配一个IP地址:
ifconfig eth0 192.168.52.2 netmask 255.255.255.0 up
下面这个 ip
命令测试发现没有添加到route 不行不要用:
ip addr add 192.168.52.2/24 dev eth0 ip link set eth0 up
在这里,192.168.52.2
是一个示例IP地址,你可以选择该子网上的任何可用地址。
root@xxx:/# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::f5d1:863c:90d8:c00e prefixlen 64 scopeid 0x20<link> ether f6:b2:f0:93:bb:ab txqueuelen 1000 (Ethernet) RX packets 121 bytes 9206 (9.2 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 47 bytes 7793 (7.7 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 38 eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.1.2 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80::1b34:5d25:1cc3:eb3d prefixlen 64 scopeid 0x20<link> ether f2:b2:f0:93:bb:ab txqueuelen 1000 (Ethernet) RX packets 1317 bytes 219566 (219.5 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 55 bytes 5851 (5.8 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 43 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 166 bytes 11692 (11.6 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 166 bytes 11692 (11.6 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 root@xxx:/# ifconfig eth0 192.168.52.2 netmask 255.255.255.0 up root@xxx:/# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.52.2 netmask 255.255.255.0 broadcast 192.168.52.255 ether f6:b2:f0:93:bb:ab txqueuelen 1000 (Ethernet) RX packets 873 bytes 299601 (299.6 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 98 bytes 15353 (15.3 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 38 eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.1.2 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80::1b34:5d25:1cc3:eb3d prefixlen 64 scopeid 0x20<link> ether f2:b2:f0:93:bb:ab txqueuelen 1000 (Ethernet) RX packets 5035 bytes 782225 (782.2 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 668 bytes 287954 (287.9 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 43 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 242 bytes 17162 (17.1 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 242 bytes 17162 (17.1 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 root@xxx:/# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default _gateway 0.0.0.0 UG 102 0 0 eth1 192.168.1.0 0.0.0.0 255.255.255.0 U 102 0 0 eth1 192.168.52.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
OK 看上面的eth0 已经被配置IP和路由了。
4. 检查网络是否通:
如果Windows 10 PC无法通过RK3568访问外部网络,需要进行一系列的故障排查步骤。
Ping测试:
- 从PC上ping RK3568的内部IP地址(192.168.52.2)。确保它是通的。(OK)
- 从RK3568 ping PC的IP地址(192.168.52.1)。确保它也是通的。(OK)
- 从RK3568 ping 外部网站,如8.8.8.8。确保外部网络是通的。(OK)
- 从PC ping 8.8.8.8。如果这不起作用,但上述所有步骤都起作用,那么问题可能与NAT或路由有关。
检查NAT设置:确保在RK3568上正确设置了NAT。再次运行以下命令:
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
检查DNS:问题可能与DNS解析有关。尝试从PC ping一个域名,如www.baidu.com
。如果这不起作用,但ping 8.8.8.8起作用,可能需要在PC上设置一个静态DNS,如Google的8.8.8.8和8.8.4.4。
RK3568验证:
root@btf:/# ping 192.168.52.1 PING 192.168.52.1 (192.168.52.1) 56(84) bytes of data. 64 bytes from 192.168.52.1: icmp_seq=1 ttl=128 time=1.17 ms 64 bytes from 192.168.52.1: icmp_seq=2 ttl=128 time=1.33 ms 64 bytes from 192.168.52.1: icmp_seq=3 ttl=128 time=1.27 ms 64 bytes from 192.168.52.1: icmp_seq=4 ttl=128 time=0.937 ms 64 bytes from 192.168.52.1: icmp_seq=5 ttl=128 time=1.66 ms 64 bytes from 192.168.52.1: icmp_seq=6 ttl=128 time=3.46 ms 64 bytes from 192.168.52.1: icmp_seq=7 ttl=128 time=1.32 ms 64 bytes from 192.168.52.1: icmp_seq=8 ttl=128 time=1.62 ms 64 bytes from 192.168.52.1: icmp_seq=9 ttl=128 time=1.75 ms 64 bytes from 192.168.52.1: icmp_seq=10 ttl=128 time=1.42 ms ^C --- 192.168.52.1 ping statistics --- 10 packets transmitted, 10 received, 0% packet loss, time 9015ms rtt min/avg/max/mdev = 0.937/1.593/3.460/0.663 ms root@btf:/# ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=110 time=184 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=110 time=186 ms ^C --- 8.8.8.8 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 183.646/184.745/185.844/1.099 ms root@btf:/#
PC Windows验证:
先验证内网通不通 (OK)
再验证外网通不通(OK)
其实到这里已经可以上网了 不信你看PC右下角图标 以及打开浏览器。
5. 防火墙设置:
确保Linux主机的防火墙允许流量通过。(这一步我是没弄的 , 如果以上步骤还是不行 可以尝试弄下防火墙)
iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
6. 小节:
如果遇到问题 请详细按照第4步骤检查 , 下面2项是重要的 不要遗漏:
1. 外部连接测试:
从Linux主机ping 8.8.8.8,确保它可以访问外部网络。
2. PC的网络设置:
确保PC的默认网关设置为Linux主机的内部IP地址。
3. 最终可上网状态:
route
或
ip route
下面是我最终OK可以上网的各项配置。
root@xxx:/# ip route default via 192.168.1.1 dev eth1 proto dhcp metric 101 192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.2 metric 101 192.168.52.0/24 dev eth0 proto kernel scope link src 192.168.52.2 root@xxx:/# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default _gateway 0.0.0.0 UG 101 0 0 eth1 192.168.1.0 0.0.0.0 255.255.255.0 U 101 0 0 eth1 192.168.52.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 root@xxx:/# ifconfig -a can0: flags=128<NOARP> mtu 16 unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 10 (UNSPEC) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 55 can1: flags=128<NOARP> mtu 16 unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 10 (UNSPEC) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 56 dummy0: flags=130<BROADCAST,NOARP> mtu 1500 ether f2:4c:f0:78:b5:b0 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.52.2 netmask 255.255.255.0 broadcast 192.168.52.255 ether f6:b2:f0:93:bb:ab txqueuelen 1000 (Ethernet) RX packets 49950 bytes 15323445 (15.3 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 43930 bytes 7288991 (7.2 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 38 eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.1.2 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80::1b34:5d25:1cc3:eb3d prefixlen 64 scopeid 0x20<link> ether f2:b2:f0:93:bb:ab txqueuelen 1000 (Ethernet) RX packets 55814 bytes 9172054 (9.1 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 49908 bytes 15222325 (15.2 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 43 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 202 bytes 16611 (16.6 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 202 bytes 16611 (16.6 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 usb0: flags=4098<BROADCAST,MULTICAST> mtu 1500 ether ae:0c:29:a3:9b:6d txqueuelen 1000 (Ethernet) RX packets 1 bytes 28 (28.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 2 bytes 433 (433.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 root@xxx:/# cat /etc/sysctl.conf | grep net.ipv4.ip_forward=1 #net.ipv4.ip_forward=1 #后面发现这个不打开其实也是可以的 root@xxx:/# cat /proc/sys/net/ipv4/ip_forward 1 #这个要打开设置为1
7. 脚本:
调试过程中一脸懵逼到逐渐清晰 , 中间也学习了很多概念 也尝试了很多遍 最终反复尝试是找到了设置成符合客户需求的规律 , 命令有些繁琐 按照我的特点 肯定是要搞个脚本自动执行啦。
#!/bin/bash # 检查参数数量 if [ "$#" -ne 3 ]; then echo "使用方法: $0 <内网接口名> <内网接口IP地址> <外网接口名>" exit 1 fi # 获取参数 INTERNAL_IF="$1" IPADDR="$2" EXTERNAL_IF="$3" # 启用IP转发 echo "启用IP转发..." echo 1 > /proc/sys/net/ipv4/ip_forward # 清理旧的NAT规则 echo "清理旧的NAT规则..." iptables -F iptables -t nat -F # 清理旧的NAT规则 echo "清理旧的NAT规则..." iptables -t nat -F # 设置NAT规则 echo "设置NAT规则..." iptables -t nat -A POSTROUTING -o $EXTERNAL_IF -j MASQUERADE # 配置内网接口 echo "配置内网接口 $INTERNAL_IF..." ip addr add $IPADDR/24 dev $INTERNAL_IF ip link set $INTERNAL_IF up # 打印网络接口信息 echo "当前网络接口信息:" ip addr # 测试外网连接 echo "测试外网连接..." ping -c 4 8.8.8.8 echo "脚本执行完毕!"
现在 可以使用以下命令来运行脚本:
./enable_nat_routing.sh eth0 192.168.52.2 eth1
脚本执行结果:
root@btf:/opt# ./enable_nat_routing.sh 使用方法: ./enable_nat_routing.sh <内网接口名> <内网接口IP地址> <外网接口名> root@btf:/opt# ./enable_nat_routing.sh eth0 192.168.52.2 eth1 启用IP转发... 清理旧的NAT规则... 设置NAT规则... 配置内网接口 eth0... 当前网络接口信息: 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000 link/ether aa:e4:19:76:54:43 brd ff:ff:ff:ff:ff:ff 3: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN group default qlen 10 link/can 4: can1: <NOARP,ECHO> mtu 16 qdisc noop state DOWN group default qlen 10 link/can 5: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether f6:b2:f0:93:bb:ab brd ff:ff:ff:ff:ff:ff inet 192.168.52.2/24 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::f5d1:863c:90d8:c00e/64 scope link noprefixroute valid_lft forever preferred_lft forever 6: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether f2:b2:f0:93:bb:ab brd ff:ff:ff:ff:ff:ff inet 192.168.1.2/24 brd 192.168.1.255 scope global dynamic noprefixroute eth1 valid_lft 86348sec preferred_lft 86348sec inet6 fe80::1b34:5d25:1cc3:eb3d/64 scope link noprefixroute valid_lft forever preferred_lft forever 7: usb0: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000 link/ether ae:0c:29:a3:9b:6d brd ff:ff:ff:ff:ff:ff 当前路由信息: default via 192.168.1.1 dev eth1 proto dhcp metric 102 192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.2 metric 102 192.168.52.0/24 dev eth0 proto kernel scope link src 192.168.52.2 测试外网连接... PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=110 time=286 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=110 time=283 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=110 time=283 ms 64 bytes from 8.8.8.8: icmp_seq=4 ttl=110 time=289 ms --- 8.8.8.8 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3003ms rtt min/avg/max/mdev = 282.528/285.120/289.283/2.689 ms 脚本执行完毕!
补充:
后面测试发现 route规则会突然消失,并且ifconfig eth0 ip也没了。
root@xxx:/opt# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default _gateway 0.0.0.0 UG 102 0 0 eth1 192.168.1.0 0.0.0.0 255.255.255.0 U 102 0 0 eth1
正常情况
root@xxx:/opt# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default _gateway 0.0.0.0 UG 102 0 0 eth1 192.168.1.0 0.0.0.0 255.255.255.0 U 102 0 0 eth1 192.168.52.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
总结:
为连接到Linux主机的设备提供网络访问可能需要多个配置步骤。通过仔细地检查每个配置和进行逐步的故障排查,我们可以成功地解决这类问题。
希望这篇博客对你有所帮助!