Magic Packet白皮書介紹:html
The basic technical details of Magic Packet Technologyare simple and easy to understand. There is also a sec-ond set of details, which will be implementation spe-cific. In other words, silicon- or gate-levelimplementations of Magic Packet Technology may dif-fer from AMD's approach and be completely interoper-able, as long as the basic feature set is maintained.python
https://wenku.baidu.com/view/d5a3282e453610661ed9f487.htmllinux
AMD公司出的網絡喚醒協議,即發送遠程喚醒數據包,Magic Packet雖然只是AMD公司所開發的一項技術,可是受到了幾乎全部網卡製造商的支持,所以,大多數流行網卡都能與之很好地兼容。(2010年後生產的主板)
WOL(Wake on Lan),即局域網喚醒,從根本上來講是硬件設備提供的一項管理功能,該功能能夠當電腦處於關機或休眠狀態時,經過給網卡發送特定的數據包從而命令網卡向主板發送開機指令,進而實現上電開機.可見,網絡喚醒須要硬件(主要是主板和網卡)的支持.bash
進入BIOS,將「Power Management Setup」中的「Wake Up On LAN」或「Resume by LAN」項設置爲「Enable」或「On」,相似於這樣,由於主板不同,BIOS設置位置有可能有差別服務器
好比個人主板設置是在:Setting-Advanced-Wake up event setup - Resume By PCI-E Device 設置爲Enable.網絡
有的人說還要設置boot的第一啓動項爲network,我試過不須要滴!app
BIOS設置好了,硬件已經知足條件了,而後須要OS級別的軟件設置iphone
Windows設置:socket
設備管理器-網卡設備-屬性-高級, 在列表裏能找到「Wakeup Capabilities(喚醒功能)」設置值爲「MagicPacket」或」Both」.工具
Linux設置:
先經過 ifconfig 查看要wol的網卡.
這裏須要說下,好多網友說沒有eth0, 對! 我也沒有這個網卡的信息,由於你用的確定是Ubuntu的衍生版,在Ubuntu 16.04以後以太網卡名稱由eth0,變成了enp3s0,還有systemd替換掉了initd來引導系統,參考: Linux網卡命名enp3s0說明
用ethtool命令 打印網卡信息
sudo ethtool enp3s0
打印結果:
....
....
Supports Wake-on: pumbg Wake-on: g Current message level: 0x00000033 (51) drv probe ifdown ifup
Wake-on 參數:
d 表示禁用disable
g表示啓用great
若是wake-on參數爲d就要啓用wol, 啓用命令:
sudo ethtool -s enp3s0 wol g
必需要用sudo 管理員權限不然會提示: Cannot get current wake-on-lan settings: Operation not permitted
-s 參數是修改以太網設備設置
supports wake-on 中的參數
p Wake on phy activity |
Windows 直接在網絡設備-屬性裏面, linux使用ifconfig 命令查看
例如linux:
enp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.1.213 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80::a680:65a4:a006:5bbc prefixlen 64 scopeid 0x20<link> ether d8:cb:8a:3f:32:d2 txqueuelen 1000 (以太網) RX packets 890331 bytes 1003253740 (1.0 GB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 555010 bytes 73345907 (73.3 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
到這;已經有了BIOS的支持,有了OS wake-on的支持,又知道了MAC地址,說明被控制(喚醒)機已經Ready了.
如今咱們須要局域網的電腦或者設備去訪問,訪問不是隨隨便便訪問的,由於Magic Packet是一種協議規則,必需要用規則發送,關於規則可看下一個段落解析Magic Packet包
咱們用GUI工具去訪問,經常使用的WOL工具備
WakeOnLanGui
下載地址:https://www.depicus.com/wake-on-lan/wake-on-lan-gui
下載地址:http://wakemeonlan.findmysoft.com
參數IP地址,MAC地址,任意一個端口號,IP地址也能夠直接填寫255.255.255.255
Linux下我沒有找到GUI工具,只有wakeonlan命令了
sudo apt install wakeonlan
喚醒目標主機:
wakeonlan d8:cb:8a:3f:32:d2
輸出:
Sending magic packet to 255.255.255.255:9 with d8:cb:8a:3f:32:d2
在同一個局域網下,手機也能夠喚醒目標主機
Android APP:
下載地址:https://dl.iplaysoft.com/files/3869.html
iphone APP:
下載地址:appstore本身搜.....
準備放大招了!!!!!
雖然 WOL (Wake on Lan) 網絡喚醒本來的設計就是 LAN 局域網環境下使用的,但其實咱們也是能夠想辦法讓其在 WAN 廣域網 (即互聯網) 下使用——Wake On Wan。這樣,在公司喚醒家裏的電腦(在家喚醒公司電腦...........)
由於廣域網不知道咱們局域網內對應的主機是哪個,因此只訪問外網的IP不會把Magic Packet包發到局域網指定的電腦上.咱們須要路由器端口映射的支持
登錄路由器找到 傳輸控制-NAT設置-虛擬服務器
路由器必須爲頂級路由而非二級即二級如下
若是路由器LAN設置的是DHCP動態分配IP,有可能此次分配的局域網IP與重啓以後局域網IP不統一(若是設備少於DHCP分配區間,IP會一直續租), 因此最好作一個靜態地址分配或者IP與MAC綁定.
對於外網,若是IP是運營商固定IP能夠直接使用公網IP,若是非固定IP(自動獲取IP與PPPoE撥號)能夠經過花生殼進行DDNS動態域名解析.使用動態域名替代公網IP.
經過站長工具 http://ip.chinaz.com/ 查看對應公網IP
OK! 此時,能夠經過手機APP進行互聯網的喚醒了,關閉WiFi,打開4G.好吧,不關WiFi也行.
當咱們按BOOT時,就會經過公網IP端口映射到指定的主機,發送Magic Packet包喚醒電腦.
depicus 提供了在線遠程喚醒 (如今貌似喚不起來了!!!)
https://www.depicus.com/wake-on-lan/woli
網站這樣解釋:
Wake on Lan Magic Packets can be sent over the Internet - why not try waking up one of your machines with our free Wake On Wan Service. Want a quick way to use this page ?
Bookmark https://www.depicus.com/wake-on-lan/woli?m=001143BDA600&i=82.110.108.30&s=255.255.255.255&p=4321 will get you straight there without the need to press those pesky send buttons.
換句話說,咱們能夠不用下載APP,只要保存一個書籤,當須要的時候訪問書籤便可.
https://www.depicus.com/wake-on-lan/woli?m=d8cb8a3f32d2&i=58.37.39.82&s=255.255.255.255&p=4321
在TeamViewer-其餘-常規-網絡設置中就有自帶的Lan網絡喚醒
填寫公共地址IP或端口映射對應的NAT網址,手機端TeamViewer登錄對應的帳戶,當主機關機時咱們就能夠經過手機端TeamViewer喚醒電腦
咱們已經知道,Magic Packet是一種協議規則,必須聽從規則發送,Magic Packet的包格式很簡單,首先是六個FF,而後是重複十六次待喚醒電腦的MAC
FF FF FF FF FF FF d8 cb 8a 3f 32 d2 d8 cb 8a 3f 32 d2 .......
理論上能夠在任意網絡封包中打包Magic Packet,不過通常選擇UDP或IPX
Python代碼:
#!/usr/bin/env python # -*- encoding: utf-8 -*- """ Small module for use with the wake on lan protocol. """ from __future__ import absolute_import from __future__ import unicode_literals import argparse import socket import struct import re BROADCAST_IP = '255.255.255.255' DEFAULT_PORT = 9 def create_magic_packet(macaddress): """ Create a magic packet. A magic packet is a packet that can be used with the for wake on lan protocol to wake up a computer. The packet is constructed from the mac address given as a parameter. Args: macaddress (str): the mac address that should be parsed into a magic packet. """ if len(macaddress) == 12: pass elif len(macaddress) == 17: sep = macaddress[2] macaddress = macaddress.replace(sep, '') else: raise ValueError('Incorrect MAC address format') # Pad the synchronization stream data = b'FFFFFFFFFFFF' + (macaddress * 16).encode() send_data = b'' # Split up the hex values in pack for i in range(0, len(data), 2): send_data += struct.pack(b'B', int(data[i: i + 2], 16)) return send_data def send_magic_packet(*macs, **kwargs): """ Wake up computers having any of the given mac addresses. Wake on lan must be enabled on the host device. Args: macs (str): One or more macaddresses of machines to wake. Keyword Args: ip_address (str): the ip address of the host to send the magic packet to (default "255.255.255.255") port (int): the port of the host to send the magic packet to (default 9) """ packets = [] ip = kwargs.pop('ip_address', BROADCAST_IP) port = kwargs.pop('port', DEFAULT_PORT) for k in kwargs: raise TypeError('send_magic_packet() got an unexpected keyword ' 'argument {!r}'.format(k)) for mac in macs: packet = create_magic_packet(mac) packets.append(packet) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # 若是輸入的是域名,將域名轉換爲IP ipv4_regex = re.compile(r'(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}',re.IGNORECASE) if not ipv4_regex.match(ip): ip=socket.gethostbyname(ip) sock.connect((ip, port)) for packet in packets: sock.send(packet) sock.close() print('sent to '+ip) def main(argv=None): """ Run wake on lan as a CLI application. """ parser = argparse.ArgumentParser( description='Wake one or more computers using the wake on lan' ' protocol.') parser.add_argument( 'macs', metavar='mac address', nargs='+', help='The mac addresses or of the computers you are trying to wake.') parser.add_argument( '-i', metavar='ip', default=BROADCAST_IP, help='The ip address of the host to send the magic packet to.' ' (default {})'.format(BROADCAST_IP)) parser.add_argument( '-p', metavar='port', type=int, default=DEFAULT_PORT, help='The port of the host to send the magic packet to (default 9)') args = parser.parse_args(argv) send_magic_packet(*args.macs, ip_address=args.i, port=args.p) if __name__ == '__main__': # pragma: nocover main()
terminal執行:
python3 WakeOnWan.py -i test.tpddns.cn -p 9 d8:cb:8a:3f:32:d2
python3 WakeOnWan.py -i 192.168.1.105 -p 9 d8:cb:8a:3f:32:d2
C++ 代碼:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> void fill_magic_buf(void *magic_buf, void *mac) { int i; char *ptr; ptr = magic_buf; memset(ptr, 0xFF, 6); ptr += 6; for(i = 0; i < 16; ++i) { memcpy(ptr, mac, 6); ptr += 6; } } void usage(void) { printf("usage...\n"); } int main(int argc, char **argv) { int s; int packet_num = 10; char c; unsigned char mac[6] = {0x00, 0x1A, 0x92, 0xE5, 0x1B, 0xA7}; char dstip[256] = "192.168.9.180"; int port = 9; struct sockaddr_in address; char magic_buf[6 + 6 * 16] = {0}; daemon(0,0); /* run in background */ while((c = getopt(argc, argv, "d:m:p:")) != -1) { switch(c) { case 'd': strcpy(dstip, optarg); break; case 'm': sscanf(optarg, "%x:%x:%x:%x:%x:%x", (unsigned int*)&mac[0], (unsigned int*)&mac[1], (unsigned int*)&mac[2], (unsigned int*)&mac[3], (unsigned int*)&mac[4], (unsigned int*)&mac[5]); break; case 'p': port = atoi(optarg); break; default: usage(); return -1; } } s = socket(AF_INET, SOCK_DGRAM, 0); if (s == -1) { perror("Opening socket"); exit(EXIT_FAILURE); } memset(&address, 0, sizeof(struct sockaddr_in)); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(dstip); address.sin_port = htons(port); fill_magic_buf(magic_buf, mac); /* ten packets. TODO: use ping to check whether the destination is on or else. */ while (packet_num-- > 0) { if (sendto(s, magic_buf, sizeof(magic_buf), 0, (struct sockaddr *)&address, sizeof(address)) < 0) { printf("sendto\n"); exit(EXIT_FAILURE); } sleep(1); } exit(EXIT_SUCCESS); }
1: 若是電腦非正常關機(好比按Power鍵來強制關機)仍是沒法WOL的,只有正常關機後,網卡仍會處於活動狀態能夠接收網絡數據
2:若是是外網IP訪問,路由器作端口映射必需要是頂級接入的路由器,由於二級如下NAT只能在是內網映射
3:Linux設置wol的時候,重啓後enp3s0的設置又恢復Wake-on: d 狀態, 寫個腳本讓開機執行 (Ubuntu18.04已修復)
在~/.profile 文件中添加
.config/wol.sh
wol.sh
#!/bin/sh echo "12345678" | sudo -S ethtool -s enp3s0 wol g
-S表示bash腳本免輸密碼,參考: bash腳本,自動輸入sudo的密碼