diff options
Diffstat (limited to 'vendor/github.com/google/gopacket/examples/synscan/main.go')
-rw-r--r-- | vendor/github.com/google/gopacket/examples/synscan/main.go | 259 |
1 files changed, 0 insertions, 259 deletions
diff --git a/vendor/github.com/google/gopacket/examples/synscan/main.go b/vendor/github.com/google/gopacket/examples/synscan/main.go deleted file mode 100644 index 7a2345f..0000000 --- a/vendor/github.com/google/gopacket/examples/synscan/main.go +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2012 Google, Inc. All rights reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the LICENSE file in the root of the source -// tree. - -// synscan implements a TCP syn scanner on top of pcap. -// It's more complicated than arpscan, since it has to handle sending packets -// outside the local network, requiring some routing and ARP work. -// -// Since this is just an example program, it aims for simplicity over -// performance. It doesn't handle sending packets very quickly, it scans IPs -// serially instead of in parallel, and uses gopacket.Packet instead of -// gopacket.DecodingLayerParser for packet processing. We also make use of very -// simple timeout logic with time.Since. -// -// Making it blazingly fast is left as an exercise to the reader. -package main - -import ( - "errors" - "flag" - "log" - "net" - "time" - - "github.com/google/gopacket" - "github.com/google/gopacket/examples/util" - "github.com/google/gopacket/layers" - "github.com/google/gopacket/pcap" - "github.com/google/gopacket/routing" -) - -// scanner handles scanning a single IP address. -type scanner struct { - // iface is the interface to send packets on. - iface *net.Interface - // destination, gateway (if applicable), and source IP addresses to use. - dst, gw, src net.IP - - handle *pcap.Handle - - // opts and buf allow us to easily serialize packets in the send() - // method. - opts gopacket.SerializeOptions - buf gopacket.SerializeBuffer -} - -// newScanner creates a new scanner for a given destination IP address, using -// router to determine how to route packets to that IP. -func newScanner(ip net.IP, router routing.Router) (*scanner, error) { - s := &scanner{ - dst: ip, - opts: gopacket.SerializeOptions{ - FixLengths: true, - ComputeChecksums: true, - }, - buf: gopacket.NewSerializeBuffer(), - } - // Figure out the route to the IP. - iface, gw, src, err := router.Route(ip) - if err != nil { - return nil, err - } - log.Printf("scanning ip %v with interface %v, gateway %v, src %v", ip, iface.Name, gw, src) - s.gw, s.src, s.iface = gw, src, iface - - // Open the handle for reading/writing. - // Note we could very easily add some BPF filtering here to greatly - // decrease the number of packets we have to look at when getting back - // scan results. - handle, err := pcap.OpenLive(iface.Name, 65536, true, pcap.BlockForever) - if err != nil { - return nil, err - } - s.handle = handle - return s, nil -} - -// close cleans up the handle. -func (s *scanner) close() { - s.handle.Close() -} - -// getHwAddr is a hacky but effective way to get the destination hardware -// address for our packets. It does an ARP request for our gateway (if there is -// one) or destination IP (if no gateway is necessary), then waits for an ARP -// reply. This is pretty slow right now, since it blocks on the ARP -// request/reply. -func (s *scanner) getHwAddr() (net.HardwareAddr, error) { - start := time.Now() - arpDst := s.dst - if s.gw != nil { - arpDst = s.gw - } - // Prepare the layers to send for an ARP request. - eth := layers.Ethernet{ - SrcMAC: s.iface.HardwareAddr, - DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - EthernetType: layers.EthernetTypeARP, - } - arp := layers.ARP{ - AddrType: layers.LinkTypeEthernet, - Protocol: layers.EthernetTypeIPv4, - HwAddressSize: 6, - ProtAddressSize: 4, - Operation: layers.ARPRequest, - SourceHwAddress: []byte(s.iface.HardwareAddr), - SourceProtAddress: []byte(s.src), - DstHwAddress: []byte{0, 0, 0, 0, 0, 0}, - DstProtAddress: []byte(arpDst), - } - // Send a single ARP request packet (we never retry a send, since this - // is just an example ;) - if err := s.send(ð, &arp); err != nil { - return nil, err - } - // Wait 3 seconds for an ARP reply. - for { - if time.Since(start) > time.Second*3 { - return nil, errors.New("timeout getting ARP reply") - } - data, _, err := s.handle.ReadPacketData() - if err == pcap.NextErrorTimeoutExpired { - continue - } else if err != nil { - return nil, err - } - packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy) - if arpLayer := packet.Layer(layers.LayerTypeARP); arpLayer != nil { - arp := arpLayer.(*layers.ARP) - if net.IP(arp.SourceProtAddress).Equal(net.IP(arpDst)) { - return net.HardwareAddr(arp.SourceHwAddress), nil - } - } - } -} - -// scan scans the dst IP address of this scanner. -func (s *scanner) scan() error { - // First off, get the MAC address we should be sending packets to. - hwaddr, err := s.getHwAddr() - if err != nil { - return err - } - // Construct all the network layers we need. - eth := layers.Ethernet{ - SrcMAC: s.iface.HardwareAddr, - DstMAC: hwaddr, - EthernetType: layers.EthernetTypeIPv4, - } - ip4 := layers.IPv4{ - SrcIP: s.src, - DstIP: s.dst, - Version: 4, - TTL: 64, - Protocol: layers.IPProtocolTCP, - } - tcp := layers.TCP{ - SrcPort: 54321, - DstPort: 0, // will be incremented during the scan - SYN: true, - } - tcp.SetNetworkLayerForChecksum(&ip4) - - // Create the flow we expect returning packets to have, so we can check - // against it and discard useless packets. - ipFlow := gopacket.NewFlow(layers.EndpointIPv4, s.dst, s.src) - start := time.Now() - for { - // Send one packet per loop iteration until we've sent packets - // to all of ports [1, 65535]. - if tcp.DstPort < 65535 { - start = time.Now() - tcp.DstPort++ - if err := s.send(ð, &ip4, &tcp); err != nil { - log.Printf("error sending to port %v: %v", tcp.DstPort, err) - } - } - // Time out 5 seconds after the last packet we sent. - if time.Since(start) > time.Second*5 { - log.Printf("timed out for %v, assuming we've seen all we can", s.dst) - return nil - } - - // Read in the next packet. - data, _, err := s.handle.ReadPacketData() - if err == pcap.NextErrorTimeoutExpired { - continue - } else if err != nil { - log.Printf("error reading packet: %v", err) - continue - } - - // Parse the packet. We'd use DecodingLayerParser here if we - // wanted to be really fast. - packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy) - - // Find the packets we care about, and print out logging - // information about them. All others are ignored. - if net := packet.NetworkLayer(); net == nil { - // log.Printf("packet has no network layer") - } else if net.NetworkFlow() != ipFlow { - // log.Printf("packet does not match our ip src/dst") - } else if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer == nil { - // log.Printf("packet has not tcp layer") - } else if tcp, ok := tcpLayer.(*layers.TCP); !ok { - // We panic here because this is guaranteed to never - // happen. - panic("tcp layer is not tcp layer :-/") - } else if tcp.DstPort != 54321 { - // log.Printf("dst port %v does not match", tcp.DstPort) - } else if tcp.RST { - log.Printf(" port %v closed", tcp.SrcPort) - } else if tcp.SYN && tcp.ACK { - log.Printf(" port %v open", tcp.SrcPort) - } else { - // log.Printf("ignoring useless packet") - } - } -} - -// send sends the given layers as a single packet on the network. -func (s *scanner) send(l ...gopacket.SerializableLayer) error { - if err := gopacket.SerializeLayers(s.buf, s.opts, l...); err != nil { - return err - } - return s.handle.WritePacketData(s.buf.Bytes()) -} - -func main() { - defer util.Run()() - router, err := routing.New() - if err != nil { - log.Fatal("routing error:", err) - } - for _, arg := range flag.Args() { - var ip net.IP - if ip = net.ParseIP(arg); ip == nil { - log.Printf("non-ip target: %q", arg) - continue - } else if ip = ip.To4(); ip == nil { - log.Printf("non-ipv4 target: %q", arg) - continue - } - // Note: newScanner creates and closes a pcap Handle once for - // every scan target. We could do much better, were this not an - // example ;) - s, err := newScanner(ip, router) - if err != nil { - log.Printf("unable to create scanner for %v: %v", ip, err) - continue - } - if err := s.scan(); err != nil { - log.Printf("unable to scan %v: %v", ip, err) - } - s.close() - } -} |