반응형

WOL 기능에서 사용되는 매직패킷을 전송하는 프로그램

python + pyqt

 

0. 개발환경

  • 맥북 OSX
  • PyCharm (Python 3.7x) + pyqt

1. GUI

 

먼저 대략적인 앱 디자인을 구성합니다.

저는 위와같이 대충 만들었습니다.

정확한 크기는 코딩단계에서 조절해줍니다.

 

[QT 디자이너]를 사용하지 않을 예정이기 때문에 대충 목표디자인을 파워포인트로 잡았습니다.

 

 

 

 

2. Coding

udp통신이고 기존에 파이썬으로 WOL패킷전송을 수행하는 코드를 작성해둔 적이 있었기 때문에 해당코드를 그대로 이용했습니다.

 

2019/05/14 - [이론/네트워크] - [네트워크 패킷] Python으로 WOL패킷 송신하기(1/2)

2019/05/14 - [이론/네트워크] - [네트워크 패킷] Python으로 WOL패킷 송신하기(2/2)

 

 

import sys
import socket, struct, time
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap, QIcon
from PyQt5.QtCore import Qt

class LayoutWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        wg = WidgetSet()
        self.setCentralWidget(wg)
        self.statusBar().showMessage('Youngq.tistory.com')

        self.setWindowTitle('WOL Program')
        self.setWindowIcon(QIcon('web.png'))
        self.setGeometry(500, 500, 350, 180)
        self.show()

class WidgetSet(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # Line 1 : Wol 이미지 + msg 영역
        hbox0 = QHBoxLayout()
        hbox0.setAlignment(Qt.AlignVCenter)

        pixmap = QPixmap('wol_mini.png')
        pixmap = pixmap.scaledToWidth(35)
        lbl_img = QLabel()
        lbl_img.setPixmap(pixmap)
        hbox0.addWidget(lbl_img)
        hbox0.addStretch(200)

        msg = QLabel()
        msg.setFixedSize(200,25)
        msg.setText("Ready")
        msg.setAlignment(Qt.AlignRight)
        self.err = msg
        hbox0.addWidget(msg)

        # Line 2 : 대역폭입력 + 콤보박스
        hbox1 = QHBoxLayout()
        hbox1.setAlignment(Qt.AlignVCenter)

        qle1 = QLineEdit(self)
        qle1.setFixedSize(170, 25)
        qle1.setPlaceholderText("목적지 IP주소 또는 망주소 입력")
        self.ip = qle1
        hbox1.addWidget(qle1)
        hbox1.addStretch(20)

        cIP = QLabel()
        cIP.setFixedSize(110, 30)
        currentIP = self.ipaddr()
        cIP.setText("IP : "+currentIP)
        hbox1.addWidget(cIP)

        # Line 3 : 맥주소 입력 + 전송버튼
        hbox2 = QHBoxLayout()
        hbox2.setAlignment(Qt.AlignHorizontal_Mask)
        qle2 = QLineEdit(self)
        qle2.setFixedSize(170, 25)
        qle2.setPlaceholderText("MAC 주소 입력")
        self.mac = qle2
        hbox2.addWidget(qle2)
        hbox2.addStretch(20)

        btn = QPushButton(self)
        btn.setText('Send')
        btn.setFixedSize(70, 30)
        self.sendBtn = btn
        btn.clicked.connect(self.sending) # EventH

        hbox2.addWidget(btn)
        # Stacking : 레이아웃 배치
        vbox = QVBoxLayout()
        vbox.addLayout(hbox0)
        vbox.addLayout(hbox1)
        vbox.addLayout(hbox2)
        self.setLayout(vbox)

    def sending(self):
        try:
            WOL(self.mac.text(), self.ip.text())
            self.err.setText("신호 전송완료")
        except:
            self.err.setText("잘못된 입력이 존재합니다.")

    def ipaddr(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        return s.getsockname()[0]

def WOL(macAddr, network):
    sep = macAddr[2]
    macAddr = macAddr.replace(sep, '')

    data = b'FFFFFFFFFFFF' + (macAddr * 16).encode()
    send_data = b''

    for i in range(0, len(data), 2):
        send_data += struct.pack('B', int(data[i: i + 2], 16))

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    for i in range(3):
        sock.sendto(send_data, (network, 9))
        time.sleep(0.05)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = LayoutWindow()
    sys.exit(app.exec_())

 

특별한 알고리즘이 필요없는 단순 프로그램이지만, GUI 구성까지 포함해서 100줄 조금 넘어가는 코드로... 역시 파이썬입니다...

 

해당 코드는 다음 링크에서 복사 가능합니다.

 

https://github.com/yekyu94/WOL_python/blob/master/wol.py

 

yekyu94/WOL_python

python WOL GUI Coding. Contribute to yekyu94/WOL_python development by creating an account on GitHub.

github.com

 

Pyqt를 통해서 제작한 코드이기 때문에 pyqt가 설치되어있지 않는 경우 애러가 발생합니다.

 

 

 

 

3. Testing

 

 

실행화면
와이어샤크로 확인

 

위와같이 전송이 완료되면 입력한 IP주소와 MAC주소를 타겟으로한 WOL패킷이 3개 전송되는 것을 볼 수 있습니다.

 

이렇게 만든 프로그램을 pyinstaller같은 라이브러리를 이용하여 쉽게 exe파일등으로 변환이 가능합니다.

 

해당부분은 넘어가겠습니다.

반응형
반응형

와이어샤크 + WOL + python

실제 구현에 관련된 코드는 2부에 있습니다.

1부에서는 와이어샤크로 WOL패킷을 확인하고 간단한 이론을 보겠습니다.

 

WOL

WOL은 전원이 종료된 컴퓨터의 랜카드에 특별한 패킷을 송신함으로써 PC를 켜주는 기능을 의미합니다.

WOL을 수행하기 위해서는 기본적으로 PC의 랜카드가 컴퓨터 종료 후에도 WOL 패킷(매직패킷)을 수신할 수 있는 상태여야합니다.(이부분은 여기서 다루지 않겠습니다.)

 

Wireshark

와이어샤크는 네트워크 패킷을 분석하는 가장 대중적인 툴입니다.

간편하게 현재 랜카드가 송신/수신한 모든 패킷들을 확인 할 수 있으며, 해당 패킷의 정보를 쉽게 확인할 수 있도록 간편한 인터페이스를 제공합니다.

 

WOL 패킷확인

Wake On Lan 어플

 

 

 WOL 패킷 확인을 위해서 해당 패킷을 전송하는 어플 [Wake On Lan]을 사용했습니다.

 

 

 

 

왼쪽에 보이는 것처럼 [wol test]라고 [11:22:33:44:55:66]이라는 맥주소를 갖고있는 컴퓨터에 WOL 패킷을 전송하도록 해주었습니다.

 

이때 와이어샤크로 감자하는 PC와 해당 스마트폰은 동일한 네트워크망에 접속되어있어야합니다.(공유기 종류 무관)

 

 

 

 

 

 

 

 

 

 

 

 

 

와이어 샤크 패킷수신화면

WOL이 사용하는 udp 9번 포트를 필터링한 결과 3개의 패킷이 전송된 것을 볼 수 있었습니다.

(맥주소는 굳이 가려봤습니다.)

 

한번에 어플이 3개의 패킷을 송신하는 것을 볼 수 있었습니다.

 

 

패킷정보(총 144byte)

와이어샤크 수신 패킷

와이어샤크 화면 하단에 표시된 내용을 순서대로 말씀드리겠습니다.

 

 

Ethernet 계층 (MAC프레임)

Ethernet (Data Link) Layer
이미지 출처 : 정보통신기술용어해설

  • DA(Dst Mac Address) = 'ff ff ff ff ff ff'
  • SA(Src Mac Address) = '50 77 05 -- -- --' 
  • Ethertype(Ethernet Protocol Type) = '08 00' (IPv4)

참고) 이더넷 타입표

  • Data = Layer3 이상부분

 

 

 

Network 계층 (IP Header)

Network Layer
이미지 출처 : 정보통신기술용어해설

  • Verson = '4'
    • IPv4
  • Header Length = '5'
    • Header Length는 위 IP헤더에서 한 줄을 의미합니다.
    • 즉 5x4byte = 20byte로 IP헤더의 최소길이를 의미합니다.
  • Type of Service = '00'
    • 미할당 영역으로 추가기능을 위한 공간입니다.
  •  Total Length = '00 82'
    • 8x16+2 = 130byte
    • 즉, IP Packet = Header(20byte) + Data(110byte) 로 이루어집니다.
  • Identification = '29 22'
    • Packet에 부여되는 식별자(오류제어등에 사용됨)
  • Flags + Fragment offset
    • Flags는 3bit 공간에 각 자리수가 특정의미를 갖음
    • [ Reserved bit | Don't Fragment | More Fragments | 
    • 40 = 010 = Don't Fragment
    • offset은 단편화가 된 경우 패킷의 순서를 확인하는 용도로 사용됨
  • TTL(Time to Live) = '40'
    • 패킷이 통과할 수 있는 노드의 수를 의미합니다.
    • 노드를 통과할 때 마다 1씩 감소하며 0이되면 전송실패와 함께, ICMP 메시지를 전송합니다.
  • Protocol type = '11'
    • 프로토콜 맵팽은 아래와 같습니다.
    • ICMP = 1 | IGMP = 2 | TCP = 6 | EGP = 8 | UDP = 17 | OSPF = 89 등...
    • 11 = 10진수로 17(즉, UDP를 의미)
  • Header Checksum = '48 69'
    • Checksum은 오류검출용 코드입니다.
  • Src IP Addr = 'c9 a8 23 90' (192.168.35.144)
  • Dst IP Addr = 'c0 a8 23 ff' (192.168.35.255)
    • WOL 기능은 목적지 주소를 망주소로 전송합니다.

 

 

 

Transport (UDP Datagram)

Transport Layer (UDP Datagram)
이미지 출처 : 정보통신기술용어해설

  • Src Port = 'eb e5' (60389)
  • Dst Port = '00 09' (9)
    • WOL은 수신 Port로 7 또는 9를 사용합니다.
  • Length = '00 6e' (110)
    • 위어서 언급한 것처럼, IP Packet에서 Data영역이었던 UDP부분이 110Byte임을 볼 수 있습니다.
  • Checksum = 'ad 79'
    • 수신측 오류확인을 위해 사용합니다.

 

 

 

Application (WOL Data)

Application Layer (WOL Data)

WOL은 특별한 데이터를 넘겨줍니다.

UDP Data로 들어온 WOL 정보

'FF FF FF FF FF FF' Broadcast MAC 주소와 목적지의 MAC 주소의 조합으로 이루어집니다.

 

위와 같이 하나의 'Broadcast' + 16개(또는 20개)의 '목적지 MAC 주소'로 이루어집니다.

 

 

 

 

끝?

 

다음 게시물은 위의 패킷을 생성하는 파이썬 코드를 보겠습니다. 이상입니다.

반응형

+ Recent posts