网络唤醒全攻略(Wake On Lan)

网络唤醒全攻略(Wake On Lan)

🗨

由于机器需要的时候才用到,所以如果经常开机的话很费电,按需开机是最佳办法.

前提条件

  • 主板支持,现在的主板基本都支持,所以基本不用担心,很旧的主板好像是2000年左右的,还是需要插网卡(PCI2.1标准)需要3针WOL线连接主板;
  • 关机时候为主板通电(600mA以上电流),把电源切断是不行的,网卡带电才可以;
  • 非正常关机可能会唤醒失败,所以里如果断电导致关机的话可能需要手工开启机器;
  • 被唤醒的电脑必须连接网络,或者路由器,并且有一台手机或者电脑可以发送唤醒包;

实现步骤

首先现在唤醒客户端
  • PC端可以使用(Aquila Technolgy)
    https://wol.aquilatech.com/
  • 安卓端(极致工具箱-网络唤醒
    http://sj.qq.com/myapp/detail.htm?apkName=com.easyapps.txtoolbox
    https://play.google.com/store/apps/details?id=com.easyapps.txtoolbox
  • 苹果(RemoteBoot WOL)
    https://itunes.apple.com/CN/app/id310369182?mt=8
客户端参数设置

以安卓为例子,极致工具箱安装好后打开网络唤醒,按+添加参数;

  • Name:填写一个别名就可以,例如:HomePC
  • Mac Address:填写电脑网卡MAC地址(注意是主板上有线网卡),这个要填写正确,如何获得? 进入命令行运行:ipconfig /all,然后查看对应的物理地址即可,共6组2字节十六进制字符;
  • Broadcast IP/Hostname/FQDN
    • Broadcast IP/Hostname 是电脑所在的局域网的广播地址:如果你的电脑分配到192.168.1.100则填写192.168.1.255,将唤醒包广播到1网段下面所有电脑,Hostname:则是你电脑的主机名.
    • FQDN:是广域网唤醒,例如你的手机在公网(4g上网),不在局域网,则需要填写路由器的DDNS域名,如:homepc.router.net
  • Port 端口默认是9,这里默认就可以
被唤醒电脑设置
  • BIOS打开唤醒设置
    在BIOS电源相关选项寻找Resume By LAN,Enable Wake ON LAN 类似选项开启
  • 网卡设置
    知道对应的网卡,打开可唤醒选项:

  • 防火墙设置
    • 添加入站规则,允许端口9通过:
    • 作用域选“公用”
    • IP地址选所有
路由器设置
  • 静态IP(局域网唤醒)
    建议设置静态的IP地址,那内网的话你要唤醒的电脑就固定IP了,否则的话每次都不一样,以我的华硕AC68U路由器为例:
  • 外围端口映射(广域网唤醒,如果你没有广域网唤醒需求可以跳过)
    端口映射的意思是在公网的时候将数据包通过域名(路由器通过DDNS和域名绑定)发送到路由器IP,路由器会将相应的包转发到指定IP的电脑上。
  • ARP绑定(广域网唤醒,如果你没有广域网唤醒需求可以跳过)
    假如你的路由有ARP绑定功能,直接设置就可以了,
    我的路由器没有ARP绑定,是可以刷梅林固件,支持开机脚本配置,所以设置脚本就可以了:新建一个脚本arp_b85m.sh,名字自己定义,放入命令:

    arp -s 192.168.2.200 XX:XX:XX:XX:XX:XX


唤醒测试

现在要被唤醒的PC上安装Aquila Technolgy WOL
https://wol.aquilatech.com/
打开封包监控诊断:

  • 局域网唤醒
    确保同一局域网并且能互通(WiFi或者有线网络)
    然后唤醒
  • 广域网唤醒
    断开WiFi,连接数据网络
    然后唤醒
    如图能看到数据包的表示唤醒包能发到网卡
  • 最后
    正常关掉电脑,进行唤醒测试,一般情况下都能成功

总结

网络唤醒的关键之处

  • 硬件支持并打开相应的设置
  • 网卡设置可接受唤醒数据包
  • MAC地址和静态IP
  • 如果广域网的端口转发和ARP绑定很重要

 

网络唤醒原理浅析(Wake On LAN)

 

上文介绍如何设置远程唤醒电脑,着重于使用,下文主要从原理方面解析一下当中的奥妙;

原理

将唤醒魔术包发送的被唤醒机器的网卡上,魔术包指AMD公司开发的唤醒数据包,具有远程唤醒的网卡都支持这个标准,用16进制表示如下:

6对“FF”前缀+16次重复MAC地址,举个例子假如我的网卡MAC地址是:AA:BB:CC:DD:EE:FF:11
那么魔术包就是:

0xFFFFFFFFFFAABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11

但是传送的时候必须封包成二进制格式才可以传送,简单来说,我们抽2个区段分析:
FFFFFFFFFFF 转成: 11111111 11111111 11111111 11111111 11111111 11111111

AABBCCDDEEFF11 转成:‭10101010 10111011 11001100 11011101 11101110 11111111 00010001‬

那么封包后就是把每个字节连接在一起:

11111111 11111111 11111111 11111111 11111111  11111111 10101010 10111011 11001100 11011101 11101110 11111111 00010001‬
……..10101010 10111011 11001100 11011101 11101110 11111111 00010001‬(第16次)

开发实现

关键代码(Java):

    private String Wake(String name, String host, String mac, int port) {
        try {
            byte[] macBytes = getMacBytes(mac);//转成字节类型
            byte[] bytes = new byte[6 + 16 * macBytes.length];
            for (int i = 0; i < 6; i++) {
                bytes[i] = (byte) 0xff;
            }
            for (int i = 6; i < bytes.length; i += macBytes.length) {
                System.arraycopy(macBytes, 0, bytes, i, macBytes.length); //放入16个MAC地址
            }
            InetAddress address = InetAddress.getByName(host);
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
            DatagramSocket socket = new DatagramSocket();
            socket.send(packet);
            socket.close();
            return "wol_package_sent_success";
        } catch (Exception e) {
             return "wol_package_sent_fail";
        }
    }
private static byte[] getMacBytes(String mac) throws IllegalArgumentException {
        byte[] bytes = new byte[6];
        String[] hex = mac.split("(\\:|\\-)");
        if (hex.length != 6) {
            throw new IllegalArgumentException("Invalid MAC address.");
        }
        try {
            for (int i = 0; i < 6; i++) {
                bytes[i] = (byte) Integer.parseInt(hex[i], 16);
            }
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Invalid hex digit in MAC address.");
        }
        return bytes;
    }

数据包流向示意图

局域网

  1. 魔术包通过手机或者电脑发送;
  2. 数据包经过路由器广播到每台机器;
  3. 被唤醒的电脑收到魔术包并且匹配成功,执行唤醒;
  4. 经过试验发现,如果电脑是待机状态,可以通过主机名或者具体IP如:192.168.1.200唤醒,如果是关机了则没有办法,我想应该是待机时候路由器分配给这个电脑的IP地址没有消失;
公网

  1. 魔术包通过路由器的域名:mypc.router.net 发送到路由器;
  2. 路由器收到数据,通过端口转发到相应的IP地址,192.168.1.100和端口9,告诉这台机器可以唤醒,ARP绑定必须存在,这个是因为很多无法远程唤醒的关键所在;看过另一种处理就是转发地址改成192.168.1.255 子网广播地址,端口不变也是9,好像就不用ARP绑定,这种方法理论上行得通,我这边暂时就不试验,试过的同学可以告诉我;
  3. 被唤醒的电脑收到魔术包并且匹配成功,执行唤醒;
思考

可以看到局域网和公网唤醒存在差别:

  1. 局域网被唤醒的IP地址是广播地址:192.168.1.255,路由器收到后通过广播,数据包一定可以发送192.168.1.100这台机器;
  2. 公网唤醒我们无办法填写具体的内网地址,只能配置路由器的公网IP,然后通过数据转发到具体的电脑IP地址,由于不是广播地址,也由于路由器ARP映射表在电脑关机后一定时间会丢失,所以路由器没有办法知道192.168.1.100是MAC所对应那台机器,所以魔术包被丢弃,所以要么增加ARP绑定,要么添加端口转发规则到广播地址,困扰多年无法远程唤醒的问题解决。

频道:电脑
扫描本文章二维码可手机访问: