#!/usr/bin/python # wake up a host when people try to ssh to it. # requires a iptables forward rule like this (ferm style): # # domain (ip ip6) table filter chain $ch # daddr # proto tcp dport 22 tcp-flags (SYN ACK FIN RST) SYN # mod state state NEW # mod limit limit 1/minute limit-burst 1 # NFLOG nflog-group 1371 nflog-prefix "ssh to valiant"; # # run from cron: # @reboot screen -d -S wol -m ./wol-valiant # # Depends: wakeonlan python-dpkt python-nflog # Copyright 2013-2017 Peter Palfrader # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import dpkt, nflog, socket, subprocess, sys, time import optparse NFLOG_GROUP = 1371 def cb(payload): #print payload #print payload.__dict__ #print "payload len ", payload.get_length() data = payload.get_data() pkt = dpkt.ip.IP(data) #print "proto:", pkt.p #print "source: %s" % socket.inet_ntoa(pkt.src) #print "dest: %s" % socket.inet_ntoa(pkt.dst) #if pkt.p == dpkt.ip.IP_PROTO_TCP: # print " sport: %s" % pkt.tcp.sport # print " dport: %s" % pkt.tcp.dport #return 1 print "[%s] python callback called because of %s!"%(time.strftime("%Y-%m-%d %H:%M:%S"), socket.inet_ntoa(pkt.src)) subprocess.call(['wakeonlan', MAC]) subprocess.call(['ip', 'neigh', 'replace', IPADDR, 'lladdr', MAC, 'nud', 'stale', 'dev', INTERFACE]) sys.stdout.flush() parser = optparse.OptionParser() parser.set_usage("%prog ") (options, args) = parser.parse_args() if len(args) != 3: parser.print_help() sys.exit(1) MAC = args[0] IPADDR = args[1] INTERFACE = args[2] l = nflog.log() print "setting callback" l.set_callback(cb) print "open" l.fast_open(NFLOG_GROUP, socket.AF_INET) print "trying to run" try: l.try_run() except KeyboardInterrupt, e: print "interrupted" print "unbind" l.unbind(socket.AF_INET) print "close" l.close()