V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
wangsongyan
V2EX  ›  Go 编程语言

Go 能否使用无 ipv4 的网卡发送 UDP 数据包?

  •  
  •   wangsongyan · 2023-03-08 23:16:24 +08:00 · 2106 次点击
    这是一个创建于 655 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我使用网线将 N1 和台式机直连,N1 未设置静态 IP ,有 eth0 、wlan0 两个网卡。

    eth0 网卡信息如下:

    eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet6 fe80::xxxx:xxxx:xxxx:xxxx  prefixlen 64  scopeid 0x20<link>
            ether de:93:xx:xx:xx:xx  txqueuelen 1000  (Ethernet)
            RX packets 3179  bytes 737340 (720.0 KiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 23709  bytes 4419840 (4.2 MiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
            device interrupt 20  
    

    我想使用 eth0 网卡发送 Wake-on-LAN 魔术包,做了以下尝试均无法唤醒主机,我猜测是因为 eth0 网卡没有 ipv4 ip 导致,我想问下能否使用上面 eth0 网卡发送 UDP 数据包?

    尝试一:
    inf, err := net.InterfaceByName("eth0")
    addrs, err := inf.Addrs()//此处 addrs 为空切片
    var localAddr = &net.UDPAddr{
    	IP: addrs[0].(*net.IPNet).IP,
    }
    conn, err := net.DialUDP("udp", localAddr, udpAddr)
    
    尝试二:(让系统自己选择本地地址)
    conn, err := net.DialUDP("udp", nil, udpAddr)
    

    (ps:同样环境下使用 etherwake 可以唤醒主机,所以很郁闷)

    13 条回复    2023-03-15 10:58:28 +08:00
    chuckzhou
        1
    chuckzhou  
       2023-03-09 00:19:07 +08:00   ❤️ 1
    你没有 IPv4 的 localAddr ,所以不能直接用 udp 。
    你必须构造一个以太网包,源 ip 填 0 试试。
    cdlnls
        2
    cdlnls  
       2023-03-09 00:47:58 +08:00   ❤️ 2
    试试用 gopacket 这个包,构建一个 UDP 包直接发送。
    jim9606
        3
    jim9606  
       2023-03-09 03:15:27 +08:00   ❤️ 1
    如果我没记错的话,发这种 WoL 包是要用 SOCK_RAW socket 直接构造 UDP 包的,不能走系统的 UDP 协议栈,所以基于 SOCK_DGRAM 的 UDP 封装应该不能用。
    hingle
        4
    hingle  
       2023-03-09 08:41:26 +08:00   ❤️ 1
    没用过 Wake-on-LAN 不清楚,但是没有 IP 的话应该只能走数据链路层了吧。
    cq65617875
        5
    cq65617875  
       2023-03-09 08:44:12 +08:00   ❤️ 1
    wol 不是直接用 mac 发的包么
    lxz6597863
        6
    lxz6597863  
       2023-03-09 09:22:51 +08:00   ❤️ 1
    gopacket+1
    911061873
        7
    911061873  
       2023-03-09 14:44:39 +08:00   ❤️ 1
    下面是我用 python+fastapi+socket 实现的外网开机
    主要是构建一个 UDP 的数据包,发给路由器,路由器做了端口转发,会 NAT 转成电脑网卡的 MAC 地址,然后就开机了。
    ```python
    @app.get('/电脑开机')
    def wakeonlan():
    import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    data = 'ff' * 6 + 'd85ed3454fe1' * 16
    s.sendto(bytes.fromhex(data), ('xxxx.xxddns.cn', 7))
    s.close()
    return PlainTextResponse('成功')
    ```
    911061873
        8
    911061873  
       2023-03-09 14:47:49 +08:00
    WOL 是涉及不到三层( IP 层面)的,只到二层(数据链路层)因为电脑关机的时候网卡
    wangsongyan
        10
    wangsongyan  
    OP
       2023-03-14 00:06:15 +08:00
    @chuckzhou #1 试了源 ip 填 0 ,无法唤醒

    @cdlnls #2
    @lxz6597863 #6 我去看看 gopacket 怎么使用

    @jim9606 #3 我在 Github 上搜到三个 go 写的 wol 相关的项目,都是发送的 UDP 数据包。我试了本机运行网卡灯是会闪一下的,我现在的情况确实不适合使用 UDP 来发

    @hingle #4 是这样的,思路没打开

    @cq65617875 #5 是直接发含 mac 地址的包,但是之前往哪儿发、怎么发不太清楚

    @911061873 #7 正在安装 python 环境,准备跑一波,你的代码也太简洁了!卧槽奉上

    @zhangsanfeng2012 #9 这正是我想要的代码,亲测可用

    感谢各位大佬的热心帮助!
    911061873
        11
    911061873  
       2023-03-14 02:02:28 +08:00
    数据包是一样的,ff*6+macaddr*16
    gitxuzan
        12
    gitxuzan  
       2023-03-15 10:01:46 +08:00
    我想问下这个是干嘛用的?局域网唤醒主机?
    wangsongyan
        13
    wangsongyan  
    OP
       2023-03-15 10:58:28 +08:00
    @gitxuzan #12 是的,配合公网 IP 或者内网穿透就可以实现远程开机
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5698 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 03:35 · PVG 11:35 · LAX 19:35 · JFK 22:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.