godivert

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2020 License: LGPL-3.0 Imports: 7 Imported by: 0

README

GoDivert

Go bindings for WinDivert.

WinDivert is a user-mode packet capture-and-divert package for Windows.

Installation

go get github.com/williamfhe/godivert

Introduction

The binding's documentation can be found Here.

If you don't have the WinDivert dll installed on your System or you want to load a specific WinDivert dll you should do :

godivert.LoadDLL("PathToThe64bitDLL", "PathToThe32bitDLL")

The path can be a relative path to the .exe current directory or an absolute path.

Note that the driver must be in the same directory as the dll. LoadDLL will then load the dll depending on your OS architecture.

To start create a new instance of WinDivertHandle by calling NewWinDivertHandle and passing the filter as a parameter.

Documentation of the filter can be found Here.

winDivert, err := godivert.NewWinDivertHandle("Your filter here")

WinDivertHandle is struct that you can use to call WinDivert's function like Recv or Send.

You can divert a packet from the network stack by using winDivert.Recv() where winDivert is an instance of WinDivertHandle.

packet, err := winDivert.Recv()

You can then choose to send the packet or modify it.

packet.SetDstPort(1234) // Sets the destination port
packet.Send(winDivert) // Sends the packet back on the network stack

You can get and set values from the packet's header by using the header package. Documentation on this package can be found Here .

As the packet has been modified the checksums have to be recalculated before sending it back on the network stack.

It is done automatically if the packet has been modified when calling packet.Send but you can do it manually by calling packet.CalcNewChecksum.

To receive packets you can also use winDivert.Packets.

packetChan, err := winDivert.Packets()

Here packetChan is a channel of *godivert.Packet coming directly from the network stack.

Note that all packets diverted are guaranteed to match the filter given in godivert.NewWinDivertHandle("You filter here")

Examples

Capturing and Printing a Packet
package main

import (
    "fmt"
    "github.com/williamfhe/godivert"
)

func main() {
    winDivert, err := godivert.NewWinDivertHandle("true")
    if err != nil {
        panic(err)
    }

    packet, err := winDivert.Recv()
    if err != nil {
        panic(err)
    }
    defer winDivert.Close()

    fmt.Println(packet)

    packet.Send(winDivert)

}

Wait for a packet and print it.

Blocking Protocol by IP

package main

import (
    "net"
    "time"
    "github.com/williamfhe/godivert"
)

var cloudflareDNS = net.ParseIP("1.1.1.1")

func checkPacket(wd *godivert.WinDivertHandle, packetChan <-chan *godivert.Packet) {
    for packet := range packetChan {
        if !packet.DstIP().Equal(cloudflareDNS) {
            packet.Send(wd)
        }
    }
}

func main() {
    winDivert, err := godivert.NewWinDivertHandle("icmp")
    if err != nil {
        panic(err)
    }
    defer winDivert.Close()

    packetChan, err := winDivert.Packets()
    if err != nil {
        panic(err)
    }

    go checkPacket(winDivert, packetChan)

    time.Sleep(1 * time.Minute)
}

Forbid all ICMP packets to reach 1.1.1.1 for 1 minute.

Try it :

ping 1.1.1.1
Packet Count
package main

import (
    "fmt"
    "time"
    "github.com/williamfhe/godivert"
    "github.com/williamfhe/godivert/header"
)

var icmpv4, icmpv6, udp, tcp, unknown, served uint

func checkPacket(wd *godivert.WinDivertHandle, packetChan  <- chan *godivert.Packet) {
    for packet := range packetChan {
        countPacket(packet)
        wd.Send(packet)
    }
}

func countPacket(packet *godivert.Packet) {
    served++
    switch packet.NextHeaderType() {
    case header.ICMPv4:
        icmpv4++
    case header.ICMPv6:
        icmpv6++
    case header.TCP:
        tcp++
    case header.UDP:
        udp++
    default:
        unknown++
    }
}


func main() {
    winDivert, err := godivert.NewWinDivertHandle("true")
    if err != nil {
        panic(err)
    }

    fmt.Println("Starting")
    defer winDivert.Close()

    packetChan, err := winDivert.Packets()
    if err != nil {
        panic(err)
    }

    n := 50
    for i := 0; i < n; i++ {
        go checkPacket(winDivert, packetChan)
    }

    time.Sleep(15 * time.Second)

    fmt.Println("Stopping...")

    fmt.Printf("Served: %d packets\n", served)

    fmt.Printf("ICMPv4=%d ICMPv6=%d UDP=%d TCP=%d Unknown=%d", icmpv4, icmpv6, udp, tcp, unknown)
}

Count all protocols passing by for 15 seconds.

Documentation

Index

Constants

View Source
const (
	PacketBufferSize   = 1500
	PacketChanCapacity = 256

	WinDivertDirectionOutbound Direction = false
	WinDivertDirectionInbound  Direction = true
)
View Source
const (
	WinDivertFlagSniff uint8 = 1 << iota
	WinDivertFlagDrop  uint8 = 1 << iota
	WinDivertFlagDebug uint8 = 1 << iota
)
View Source
const (
	WINDIVERT_LAYER_NETWORK int = iota
	WINDIVERT_LAYER_NETWORK_FORWARD
	WINDIVERT_LAYER_FLOW
	WINDIVERT_LAYER_SOCKET
	WINDIVERT_LAYER_REFLECT
)

Variables

This section is empty.

Functions

func HelperCompileFilter

func HelperCompileFilter(filter string) (bool, int)

Take the given filter and check if it contains any error https://reqrypt.org/windivert-doc.html#divert_helper_check_filter

func HelperEvalFilter

func HelperEvalFilter(packet *Packet, filter string) (bool, error)

Take a packet and compare it with the given filter Returns true if the packet matches the filter https://reqrypt.org/windivert-doc.html#divert_helper_eval_filter

func LoadDLL

func LoadDLL(path64, path32 string)

LoadDLL loads the WinDivert DLL depending the OS (x64 or x86) and the given DLL path. The path can be a relative path (from the .exe folder) or absolute path.

Types

type Direction

type Direction bool

func (Direction) String

func (d Direction) String() string

type Packet

type Packet struct {
	Raw       []byte
	Addr      *WinDivertAddress
	PacketLen uint

	IpHdr      header.IPHeader
	NextHeader header.ProtocolHeader
	// contains filtered or unexported fields
}

Represents a packet

func (*Packet) CalcNewChecksum

func (p *Packet) CalcNewChecksum(wd *WinDivertHandle)

Recalculate the packet's checksum Shortcut for WinDivertHelperCalcChecksum

func (*Packet) Direction

func (p *Packet) Direction() Direction

Returns the Direction of the packet WinDivertDirectionInbound (true) for inbound Packets WinDivertDirectionOutbound (false) for outbound packets Shortcut for Addr.Direction()

func (*Packet) DstIP

func (p *Packet) DstIP() net.IP

Returns the destination IP of the packet Shortcut for IpHdr.DstIP()

func (*Packet) DstPort

func (p *Packet) DstPort() (uint16, error)

Returns the destination port of the packet Shortcut for NextHeader.DstPort()

func (*Packet) EvalFilter

func (p *Packet) EvalFilter(filter string) (bool, error)

Check the packet with the filter Returns true if the packet matches the filter

func (*Packet) IpVersion

func (p *Packet) IpVersion() int

Returns the version of the IP protocol Shortcut for ipHdr.Version()

func (*Packet) NextHeaderProtocolName

func (p *Packet) NextHeaderProtocolName() string

Returns the name of the protocol

func (*Packet) NextHeaderType

func (p *Packet) NextHeaderType() uint8

Returns the IP Protocol number of the next Header https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers

func (*Packet) ParseHeaders

func (p *Packet) ParseHeaders()

Parse the packet's headers

func (*Packet) Send

func (p *Packet) Send(wd *WinDivertHandle) (uint, error)

Inject the packet on the Network Stack If the packet has been modified calls WinDivertHelperCalcChecksum to get a new checksum

func (*Packet) SetDstIP

func (p *Packet) SetDstIP(ip net.IP)

Sets the destination IP of the packet Shortcut for IpHdr.SetDstIP()

func (*Packet) SetDstPort

func (p *Packet) SetDstPort(port uint16) error

Sets the destination port of the packet Shortcut for NextHeader.SetDstPort()

func (*Packet) SetSrcIP

func (p *Packet) SetSrcIP(ip net.IP)

Sets the source IP of the packet Shortcut for IpHdr.SetSrcIP()

func (*Packet) SetSrcPort

func (p *Packet) SetSrcPort(port uint16) error

Sets the source port of the packet Shortcut for NextHeader.SetSrcPort()

func (*Packet) SrcIP

func (p *Packet) SrcIP() net.IP

Returns the source IP of the packet Shortcut for IpHdr.SrcIP()

func (*Packet) SrcPort

func (p *Packet) SrcPort() (uint16, error)

Returns the source port of the packet Shortcut for NextHeader.SrcPort()

func (*Packet) String

func (p *Packet) String() string

func (*Packet) VerifyParsed

func (p *Packet) VerifyParsed()

Check if the headers have already been parsed and call ParseHeaders() if not

type WinDivertAddress

type WinDivertAddress struct {
	Timestamp int64
	Flags     uint64
	IfIdx     uint32
	SubIfIdx  uint32
	// contains filtered or unexported fields
}

Represents a WinDivertAddress struct See : https://reqrypt.org/windivert-doc.html#divert_address As go doesn't not support bit fields we use a little trick to get the Direction, Loopback, Import and PseudoChecksum fields Only support network and network_forward layer for now

func (*WinDivertAddress) Direction

func (w *WinDivertAddress) Direction() Direction

Returns the direction of the packet WinDivertDirectionInbound (true) for inbounds packets WinDivertDirectionOutbounds (false) for outbounds packets

func (*WinDivertAddress) IPv6

func (w *WinDivertAddress) IPv6() bool

func (*WinDivertAddress) Impostor

func (w *WinDivertAddress) Impostor() bool

Returns true if the packet is an impostor See https://reqrypt.org/windivert-doc.html#divert_address for more information

func (*WinDivertAddress) Loopback

func (w *WinDivertAddress) Loopback() bool

Returns true if the packet is a loopback packet

func (*WinDivertAddress) SetDirection

func (w *WinDivertAddress) SetDirection(d int)

func (*WinDivertAddress) String

func (w *WinDivertAddress) String() string

func (*WinDivertAddress) ValidIPChecksum

func (w *WinDivertAddress) ValidIPChecksum() bool

Returns true if the packet uses a Valid IP checksum

func (*WinDivertAddress) ValidTCPChecksum

func (w *WinDivertAddress) ValidTCPChecksum() bool

Returns true if the packet uses a Valid TCP checksum

func (*WinDivertAddress) ValidUDPChecksum

func (w *WinDivertAddress) ValidUDPChecksum() bool

Returns true if the packet uses a Valid UDP checksum

type WinDivertHandle

type WinDivertHandle struct {
	// contains filtered or unexported fields
}

Used to call WinDivert's functions

func NewWinDivertHandle

func NewWinDivertHandle(filter string) (*WinDivertHandle, error)

Create a new WinDivertHandle by calling WinDivertOpen and returns it The string parameter is the fiter that packets have to match https://reqrypt.org/windivert-doc.html#divert_open

func NewWinDivertHandleWithFlags

func NewWinDivertHandleWithFlags(filter string, layer int, flags uint8) (*WinDivertHandle, error)

Create a new WinDivertHandle by calling WinDivertOpen and returns it The string parameter is the fiter that packets have to match and flags are the used flags used https://reqrypt.org/windivert-doc.html#divert_open

func (*WinDivertHandle) Close

func (wd *WinDivertHandle) Close() error

Close the Handle See https://reqrypt.org/windivert-doc.html#divert_close

func (*WinDivertHandle) HelperCalcChecksum

func (wd *WinDivertHandle) HelperCalcChecksum(packet *Packet)

Calls WinDivertHelperCalcChecksum to calculate the packet's chacksum https://reqrypt.org/windivert-doc.html#divert_helper_calc_checksums

func (*WinDivertHandle) Packets

func (wd *WinDivertHandle) Packets() (chan *Packet, error)

Create a new channel that will be used to pass captured packets and returns it calls recvLoop to maintain a loop

func (*WinDivertHandle) Recv

func (wd *WinDivertHandle) Recv() (*Packet, error)

Divert a packet from the Network Stack https://reqrypt.org/windivert-doc.html#divert_recv

func (*WinDivertHandle) Send

func (wd *WinDivertHandle) Send(packet *Packet) (uint, error)

Inject the packet on the Network Stack https://reqrypt.org/windivert-doc.html#divert_send

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL