Using go to develop an intranet active host sniffer

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Article keywords

    • Go/golang
    • Gopacket
    • Grab Bag
    • Pcap/libpcap
    • Arp
    • Nbns
    • MDNs
    • Manuf

Program


Description

This article for the go language itself is not too much to explain, want to spend more time on a few network protocol explanation, I hope this article on the plan or are using go for TCP/IP programming and grasping the package of friends to bring help.
GitHub Address: Https://github.com/timest/goscan

Program Ideas

    • Intranet IP range is calculated by intranet IP and subnet mask
    • Broadcast ARP Request to intranet
    • Listen and crawl ARP response packet, record IP and MAC address
    • Sends active IP to send MDNs and NBNS packets, and listens and parses hostname
    • Calculate the factory information according to the MAC address

Intranet IP range is calculated by intranet IP and subnet mask

If just know an IP address, is not aware of the network IP segment, can not simply change the last byte of the native IP to 1-255. Need to use subnet mask to calculate the network segment of the intranet, this piece is relatively simple, here do not repeat, there is doubt on-line search subnet mask to obtain more information. It is worth mentioning that the last field of the IP address is not 0 and 255, the former is RFC, the latter is generally the broadcast address.

// 单网卡模式addrs, err := net.InterfaceAddrs()if err != nil {   log.Fatal("无法获取本地网络信息:", err)}for i, a := range addrs {   if ip, ok := a.(*net.IPNet); ok && !ip.IP.IsLoopback() {       if ip.IP.To4() != nil {           fmt.Println("IP:", ip.IP)           fmt.Println("子网掩码:", ip.Mask)           it, _ := net.InterfaceByIndex(i)           fmt.Println("Mac地址:", it.HardwareAddr)           break       }   }}

According to the Ipnet obtained above, the intranet IP range can be calculated:

type IP uint32// 根据IP和mask换算内网IP范围func Table(ipNet *net.IPNet) []IP {    ip := ipNet.IP.To4()    log.Info("本机ip:", ip)    var min, max IP    var data []IP    for i := 0; i < 4; i++ {        b := IP(ip[i] & ipNet.Mask[i])        min += b << ((3 - uint(i)) * 8)    }    one, _ := ipNet.Mask.Size()    max = min | IP(math.Pow(2, float64(32 - one)) - 1)    log.Infof("内网IP范围:%s --- %s", min, max)    // max 是广播地址,忽略    // i & 0x000000ff  == 0 是尾段为0的IP,根据RFC的规定,忽略    for i := min; i < max; i++ {        if i & 0x000000ff == 0 {            continue        }        data = append(data, i)    }    return data}

Broadcast ARP Request to intranet

ARP (Address Resolution Protocol), which is a TCP/IP protocol that obtains a physical address based on an IP address, is a protocol for addressing resolution. When the host sends the message, the ARP request containing the destination IP address is broadcast to all hosts on the network, and the return message is received to determine the destination's physical address------Baidu Encyclopedia

When we want to send the IP data to another host in the Ethernet, we will query the corresponding Ethernet address in the ARP cache based on the IP address of the destination host, and the ARP cache is a mapping table for the host to maintain an IP address to the corresponding Ethernet address. If the query fails, ARP broadcasts a message asking for the destination host hardware address (OP field 1), waiting for the target host to respond.
Because the ARP cache is sensitive, it is best to send an ICMP packet to verify that the target is online after it has been read to the destination host's hardware address. Of course, you can choose not to read the data from the cache, but directly send ARP packets, waiting for the online host to respond to the ARP message.


Arp

The Gopacket has encapsulated ARP messages:

type ARP struct {    BaseLayer    AddrType          LinkType     // 硬件类型    Protocol          EthernetType // 协议类型    HwAddressSize     uint8        // 硬件地址长度    ProtAddressSize   uint8        // 协议地址长度    Operation         uint16       // 操作符(1代表request 2代表reply)    SourceHwAddress   []byte       // 发送者硬件地址    SourceProtAddress []byte       // 发送者IP地址    DstHwAddress      []byte       // 目标硬件地址(可以填写00:00:00:00:00:00)    DstProtAddress    []byte       // 目标IP地址}

Give the specific code in the project:

Send ARP packet//IP Destination IP address func sendarppackage (IP IP) {srcip: = net. Parseip (IpNet.IP.String ()). To4 () Dstip: = Net. Parseip (IP. String ()). To4 () if Srcip = = Nil | | Dstip = = Nil {log. Fatal ("IP parsing Problem")}//Ethernet header//Ethernettype 0x0806 ARP ether: = &layers. ethernet{srcmac:localhaddr, Dstmac:net. Hardwareaddr{0xff, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, Ethernettype:layers. Ethernettypearp,} A: = &layers. arp{addrtype:layers. Linktypeethernet, Protocol:layers.  ETHERNETTYPEIPV4, Hwaddresssize:uint8 (6), Protaddresssize:uint8 (4), operation:uint16 (1),//0x0001  ARP Request 0x0002 ARP response sourcehwaddress:localhaddr, SOURCEPROTADDRESS:SRCIP, dsthwaddress: Net. hardwareaddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, Dstprotaddress:dstip,} buffer: = Gopacket. Newserializebuffer () var opt gopacket. Serializeoptions Gopacket. Serializelayers (buffer, opt, ether, a)   Outgoingpacket: = buffer. Bytes () handle, err: = Pcap. Openlive (Iface, 2048, false, time. Second) If err! = Nil {log. Fatal ("Pcap Open failed:", err)} defer handle. Close () Err = handle. Writepacketdata (outgoingpacket) if err! = Nil {log.    Fatal ("Sending ARP packet failed:") }}

We only need to take the first step to get the Intranet IP table, open a goruntime traversal send ARP message can be.

Listen and crawl ARP response packet, record IP and MAC address

In the previous step has been sent ARP request, only need to open an ARP listening goruntime, all have to return ARP response packet, is the intranet online host.

func listenARP(ctx context.Context) {    handle, err := pcap.OpenLive(iface, 1024, false, 10 * time.Second)    if err != nil {        log.Fatal("pcap打开失败:", err)    }    defer handle.Close()    handle.SetBPFFilter("arp")    ps := gopacket.NewPacketSource(handle, handle.LinkType())    for {        select {        case <-ctx.Done():            return        case p := <-ps.Packets():            arp := p.Layer(layers.LayerTypeARP).(*layers.ARP)            if arp.Operation == 2 {                mac := net.HardwareAddr(arp.SourceHwAddress)                pushData(ParseIP(arp.SourceProtAddress).String(), mac, "", manuf.Search(mac.String()))                go sendMdns(ParseIP(arp.SourceProtAddress), mac)                go sendNbns(ParseIP(arp.SourceProtAddress), mac)            }        }    }}

Sends active IP to send MDNs and NBNS packets, and listens and parses hostname

In the previous step, after we received an ARP response, we were able to initiate MDNs and NBNS packets waiting for the return of the hostname.

go sendMdns(ParseIP(arp.SourceProtAddress), mac)go sendNbns(ParseIP(arp.SourceProtAddress), mac)

MDNS: Send UDP MDNS (multicast DNS) packets to each other's 5353 port and 01:00:5E:00:00:FB MAC address, if the target system supports, return to host Name Detailed protocol introduction and message format can be seen in Wikipedia's introduction.
NBNS: A common kind of protocol to view the target machine hostname, like mdns, the transport layer is also UDP, the port is at 137.
The length is too long, please see NBNS.GO and mdns.go on GitHub for a specific code.

Calculate the factory information according to the MAC address

We can obtain the manufacturer information of the device through the hardware address of the target host. In this case, even if you encounter a better defense system, we can not get to the hostname, but also from the factory information to obtain a certain amount, such as factory information is OnePlus or Smartisan, you can judge is a mobile phone
Manuf file, file fragment:

00:03:8F    Weinsche    Weinschel Corporation00:03:90    DigitalV    Digital Video Communications, Inc.00:03:91    Advanced    Advanced Digital Broadcast, Ltd.00:03:92    HyundaiT    Hyundai Teletek Co., Ltd.00:03:93    Apple   Apple, Inc.00:03:94    ConnectO    Connect One00:03:95    Californ    California Amplifier00:03:96    EzCast  EZ Cast Co., Ltd.00:03:97    Watchfro    Watchfront Limited

Code is not affixed, directly see the code, 100 lines of code, or is quite simple: manuf.go. The MAC address of test result 99% can be mapped to the corresponding vendor information.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.