何も設定しなくても Ricoh IT2 は起きた。
とりあえず Wake up On Lan Tool を使った。
LAN で起動するまで
要は NIC に特殊な UDP パケットが届けば起動する。
- マジックパケットをブロードキャストする
- NIC がマジックパケットを検知する
- UDP/7 か UDP/9 が正式らしいが、事実上 UDP であればポートは何でもいい
- データは ff ff ff ff ff ff に送り先の NIC の MAC x 16
- セキュリティは無い
- 起動する
WAN で起動するまで
別に難しくない。ルーターの NAT でブロードキャストアドレスを指定できるかだけが問題。
- ルーターに NAT エントリを追加する
- プロトコル: UDP
- 変換元ポート: 適当
- 変換後アドレス: 192.168.0.255 とかのブロードキャストアドレス
- 変換後ポート: 適当
- ホスト名の (IP なり DDNS なり) 適当に指定したポートにマジックパケットを送る
- ルーターが NAT でマジックパケットをブロードキャストする
- 後は LAN 内と同等
magicpacket.py
というわけでさくさくっと実装。バイナリ
LAN: magicpacket.py XX:XX:XX:XX:XX:XX
WAN: magicpacket.py -d example.com:port XX:XX:XX:XX:XX:XX
"""magicpacket.py""" import re, socket from optparse import OptionParser if __name__ == '__main__': parser = OptionParser(usage='Usage: %prog [options] MAC-address') parser.add_option('-d', '--dest', '--destination', metavar='hostname[:port]', help='destination address (default=%default)', dest='dest', default='255.255.255.255:7') options, args = parser.parse_args() if not args: parser.error('no MAC address given') if ':' in options.dest: addr = options.dest.split(':', 1) addr[1] = int(addr[1]) else: addr = options.dest, 7 if addr[0] == '255.255.255.255': addr_list = [] for ifaddr in socket.gethostbyname_ex(socket.gethostname())[2]: addr_list.append((ifaddr.rsplit('.', 1)[0] + '.255', addr[1])) else: addr_list = [addr, ] for arg in args: arg = re.sub('[^0-9A-Fa-f]', '', arg) mac = ''.join(chr(int(i+j, 16)) for i, j in zip(arg[::2], arg[1::2])) for addr in addr_list: sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock.sendto('\xff' * 6 + mac * 16, tuple(addr)) #sock.sendto('\xff' * 6 + mac * 20, tuple(addr))