2019년 4월 14일 일요일

라즈베리파이로 WOL 해서 PC 켜기(Turn on PC using WOL in Raspberry Pi) , sending magic packet for WOL through eth0


WOL로 PC를 켜는것은 공통적인 부분입니다. 여기서 시도한것은 LAN의 cross cable(공유기를 거치지 않고  PC-PC를 LAN케이블을 연결) 을 이용한 WOL 입니다.
결론는 가능하다 입니다.

1. PC의 WOL 설정 확인하기

1.1 PC BIOS 설정 확인하기
1.2 Windows 설정 확인하기
1.2.1 LAN Card 드라이버 업데이트하기
랜카드를 드라이버를 업그레이드 하지 않으면 WOL 옵션이 나타나지 않습니다.
1.2.2 LAN 설정 변경하기
LAN 카드 고급 설정 확인 할 것
1.2.3 절전 모드 확인하기
동작안되면 절전 관련 off할 것
설정->전원 및 절전->추가 전원 설정->덮개를 닫으면 수행되는 작업 선택->전원 단추 정의 및 암호 보호 설정->현재 사용할 수 없는 설정 변경->빠른 시작 켜기 check 해제해야함
설정은 인터넷 검색시 많이 나오므로 여기에서는 생략 하였습니다.

2. 공유기에서 WOL 해보기

일반적인 공유기들은 WOL 이 지원하므로 PC설정이 제대로 동작되었는지 공유기로 확인 합니다.

3. Raspberry Pi 유선 랜에서 WOL 하기

etherwake 설치하기
sudo aptiude install etherwake

아래와 같은 형식으로  00:00:00:00:00:00 =>값은 깨우고자 하는 LAN카드의 MAC address 입니다.
sudo etherwake 00:00:00:00:00:00

4. Raspberry Pi 와 PC Cross cable에서 WOL 하기

케이블만 Cross로 연결하여 etherwake를 호출 합니다.
sudo etherwake 00:00:00:00:00:00

5. eth0 장치로 매직패킷 보내기 (sending magic packet for WOL through eth0)

깨우고자 하는 PC의 환경이 라즈베리파이와 유선LAN으로 연결되어 있고 라즈베리파이의 무선WIFI로 인터넷이 연결되어 있다면  WOL시도할때 일반적인 코드로는 깨워지지 않습니다. 사유가 대부분의 구현된 코드가 인터넷 연결된 망으로 매직 패킷을 보내기 때문입니다. 무선랜 연결시에는 무선랜으로 매직패킷이 보내지게 됩니다.
리눅스에서 eth장치가 유선랜이므로 eth로 매직 패킷을 보내야 합니다.

source code
# wol
import socket
import fcntl
import struct

BROADCAST_IP = '255.255.255.255'
DEFAULT_PORT = 9

def get_ip_address(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    return socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
    )[20:24])

def create_magic_packet(macaddress):
    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(mac,ifname):
 packets = []
 ip = BROADCAST_IP
 port = DEFAULT_PORT

 packet = create_magic_packet(mac)
 packets.append(packet)

 if ifname != None:
  myip = get_ip_address("eth0".encode())
 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
 if ifname != None:
  sock.bind((myip,port))
 sock.connect((ip, port))
 for packet in packets:
  sock.send(packet)
 sock.close()

def wol(mac):
 send_magic_packet(mac,"eth0")

6. 소스 코드 설명

get_ip_address 함수는 LAN interface 장치로 부터 ip를 구합니다. 위 소스에서는 eth0 장치를 사용하였습니다. LAN카드가 여러개인경우 eth1장치가 될 수 도 있습니다.
구해진 ip를 통해서 매직 패킷으로 보낼때 특정 ip로 소켓 바인드를 합니다. sock.bind((myip,port)) , 그러면 특정 장치로 magic packet이 나가게 됩니다.




댓글 없음:

댓글 쓰기