Skip to content

Instantly share code, notes, and snippets.

@kapsel
Created September 25, 2022 18:56
Show Gist options
  • Save kapsel/aa8cb25e6d1aa9b6df7c6671c5d2aff7 to your computer and use it in GitHub Desktop.
Save kapsel/aa8cb25e6d1aa9b6df7c6671c5d2aff7 to your computer and use it in GitHub Desktop.
Listen for WOL packets to trigger power-on via IPMI
#!/usr/bin/python3
from scapy.all import sniff
from sys import argv
from struct import unpack
from subprocess import check_output
USERNAME = 'ADMIN'
PASSWORD = 'secret'
hosts = {
'ac:1f:6b:b1:76:5a': 'server1-ipmi',
'ac:1f:6b:b1:7b:22': 'server2-ipmi',
'ac:1f:6b:b1:7b:3a': 'server3-ipmi',
'ac:1f:6b:b1:7b:62': 'server4-ipmi'
}
def on_wol_packet(pkt):
if hasattr(pkt.getlayer('UDP'), 'load'):
data = pkt.getlayer('Ether').load
broadcast = ':'.join(map('{:02x}'.format, unpack('BBBBBB', data[0*6:1*6])))
machine = ':'.join(map('{:02x}'.format, unpack('BBBBBB', data[1*6:2*6])))
if machine not in hosts:
print('Unknown MAC: {:s}'.format(machine))
return
ret = check_output([
'ipmitool', '-H', hosts[machine], '-U', USERNAME, '-P', PASSWORD, 'power', 'on'
]).decode()
print('cmd returned: {:s}'.format(ret))
if __name__ == '__main__':
assert len(argv) > 1, 'Usage: {:s} LISTEN_INTERFACE'.format(argv[0])
packets = sniff(count=0, iface=argv[1], filter='ether proto 0x0842 or udp port 9 or udp port 7 or udp port 0', prn=on_wol_packet)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment