magic packet 릴레이.python
관련링크
본문
외부에서 공유기 너머 pc 를 wol 으로 깨우려 할 때 pc 가 꺼진 시간이 길어지면
공유기에서 arp 정보 유실로 제대로 깨워지지 않는 문제가 있다고 합니다.
공유기에서 arp 바인딩 기능을 지원하면 그렇게 하면 되고
그렇지 않다면 간단히 라즈베리파이 같은 상시 켜둘 수 있는 저전력 기기로 패킷을 릴레이 시킬 수 있는 서비스를 띄워두라고 해서 작성해 봤습니다.
import socket, fcntl, struct
LISTEN_PORT = 10009
INTERFACES = ["eth0", "wlan0"]
def get_broadcast_address(interface):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8919,
struct.pack('256s', interface[:15].encode('utf-8'))
)[20:24])
except Exception as e:
print(f'Error getting broadcast address for {interface}: {e}')
return None
def broadcast_magic_packet(mac_address):
"""주어진 MAC 주소로 매직 패킷 생성 및 브로드캐스트"""
mac_address = mac_address.replace(":", "").replace("-", "")
if len(mac_address) != 12:
print(f"Invalid MAC address: {mac_address}")
return
# 매직 패킷 생성
magic_packet = bytes.fromhex("FF" * 6 + mac_address * 16)
for interface in INTERFACES:
broadcast_addr = get_broadcast_address(interface)
if broadcast_addr is None:
print(f"Skipping interface {interface} due to missing broadcast address")
continue
try:
# 브로드캐스트 전송
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.setsockopt(socket.SOL_SOCKET, 25, interface.encode('utf-8') + b'\0')
s.sendto(magic_packet, (broadcast_addr, 9))
print(f"Broadcasted magic packet for MAC: {mac_address} on {interface}")
except Exception as e:
print(f"Error broadcasting on {interface}: {e}")
def listen_for_magic_packets():
"""UDP 포트에서 매직 패킷 수신 대기"""
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.bind(("0.0.0.0", LISTEN_PORT)) # 모든 IP로부터 수신 대기
print(f"Listening for magic packets on UDP port {LISTEN_PORT}...")
while True:
data, addr = s.recvfrom(1024) # 패킷 데이터와 발신 주소
print(f"Received packet from {addr}")
# MAC 주소 추출 (데이터 형식에 따라 조정 필요)
mac_address = extract_mac_address(data)
if mac_address:
print(f"Extracted MAC address: {mac_address}")
broadcast_magic_packet(mac_address)
def extract_mac_address(data):
"""패킷 데이터에서 MAC 주소 추출"""
# 매직 패킷의 형식 검증 (6바이트 FF + 16번 MAC)
if len(data) >= 102 and data[:6] == b'\xff' * 6:
mac = data[6:12]
return ':'.join(f"{byte:02x}" for byte in mac)
print("Invalid magic packet format")
return None
if __name__ == "__main__":
listen_for_magic_packets()
공유기 포워딩 설정을 통해서 10009 로 포워딩 받은 후 물려 있는 nic 마다 브로드캐스팅 뿌려주는 파이썬 코드입니다.