godivert

package module
v0.0.0-...-c28a0cd Latest Latest
Warning

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

Go to latest
Published: Jan 14, 2022 License: LGPL-3.0 Imports: 7 Imported by: 4

README

GoDivert

Go bindings for WinDivert.

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

Note: this project was forked from https://github.com/Macronut/godivert, which itself was forked from https://github.com/williamfhe/godivert.

Installation

go get github.com/Crosse/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/Crosse/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/Crosse/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/Crosse/godivert"
    "github.com/Crosse/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 = 1
	WinDivertDirectionInbound  Direction = 0
)
View Source
const (
	// The highest priority a handle can have.
	PriorityMax = 30000
	// The default handle priority.
	//
	// Note that multiple handles should not have the same priority.
	PriorityDefault = 0
	// The lowest priority a handle can have.
	PriorityLowest = -PriorityMax
)
View Source
const (
	ChecksumAll      = 0x00
	ChecksumNoIP     = 0x01
	ChecksumNoICMP   = 0x02
	ChecksumNoICMPv6 = 0x04
	ChecksumNoTCP    = 0x08
	ChecksumNoUDP    = 0x10
)

Variables

This section is empty.

Functions

func HelperCheckFilter

func HelperCheckFilter(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 ChecksumFlag

type ChecksumFlag int64

type Direction

type Direction int

func (Direction) String

func (d Direction) String() string

type Event

type Event int
const (
	EventNetworkPacket Event = iota
	EventFlowEstablished
	EventFlowDeleted
	EventSocketBind
	EventSocketConnect
	EventSocketListen
	EventSocketAccept
	EventSocketClose
	EventReflectOpen
	EventReflectClose
)

func (Event) String

func (e Event) String() string

type Layer

type Layer int
const (
	// Network packets to/from the local machine.
	LayerNetwork Layer = iota
	// Network packets passing through the local machine.
	LayerForward
	// Network flow established/deleted events.
	LayerFlow
	// Socket operation events.
	LayerSocket
	// WinDivert handle events.
	LayerReflect
)

func (Layer) String

func (l Layer) String() string

type OpenFlag

type OpenFlag uint8
const (
	OpenFlagNone        OpenFlag = 0x00
	OpenFlagSniff       OpenFlag = 0x01
	OpenFlagDrop        OpenFlag = 0x02
	OpenFlagReceiveOnly OpenFlag = 0x04
	OpenFlagSendOnly    OpenFlag = 0x08
	OpenFlagNoInstall   OpenFlag = 0x10
	OpenFlagFragments   OpenFlag = 0x20
)

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 Priority

type Priority int16

type WinDivertAddress

type WinDivertAddress struct {
	Timestamp int64
	Flags     uint64
	Data      [64]byte
}

Represents a WinDivertAddress struct

See : https://reqrypt.org/windivert-doc.html#divert_address

func (*WinDivertAddress) Direction

func (w *WinDivertAddress) Direction() Direction

Direction returns the direction of the packet

func (*WinDivertAddress) Event

func (w *WinDivertAddress) Event() Event

func (*WinDivertAddress) IPChecksumValid

func (w *WinDivertAddress) IPChecksumValid() bool

func (*WinDivertAddress) IPv6

func (w *WinDivertAddress) IPv6() bool

func (*WinDivertAddress) Impostor

func (w *WinDivertAddress) Impostor() bool

func (*WinDivertAddress) Layer

func (w *WinDivertAddress) Layer() Layer

func (*WinDivertAddress) Loopback

func (w *WinDivertAddress) Loopback() bool

func (*WinDivertAddress) Outbound

func (w *WinDivertAddress) Outbound() bool

func (*WinDivertAddress) Sniffed

func (w *WinDivertAddress) Sniffed() bool

func (*WinDivertAddress) String

func (w *WinDivertAddress) String() string

func (*WinDivertAddress) TCPChecksumValid

func (w *WinDivertAddress) TCPChecksumValid() bool

func (*WinDivertAddress) UDPChecksumValid

func (w *WinDivertAddress) UDPChecksumValid() bool

type WinDivertHandle

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

Used to call WinDivert's functions

func OpenHandle

func OpenHandle(filter string, layer Layer, priority uint16, flags OpenFlag) (*WinDivertHandle, error)

OpenHandle opens a new WinDivert handle.

func OpenHandleWithFilter

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

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) RecalculateChecksums

func (wd *WinDivertHandle) RecalculateChecksums(packet *Packet, flags ChecksumFlag)

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