wip: migrate to mono-repo. SPN has already been moved to spn/
This commit is contained in:
266
service/network/packet/packet.go
Normal file
266
service/network/packet/packet.go
Normal file
@@ -0,0 +1,266 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
)
|
||||
|
||||
// Base is a base structure for satisfying the Packet interface.
|
||||
type Base struct {
|
||||
ctx context.Context
|
||||
info Info
|
||||
connID string
|
||||
layers gopacket.Packet
|
||||
layer3Data []byte
|
||||
layer5Data []byte
|
||||
}
|
||||
|
||||
// FastTrackedByIntegration returns whether the packet has been fast-track
|
||||
// accepted by the OS integration.
|
||||
func (pkt *Base) FastTrackedByIntegration() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// InfoOnly returns whether the packet is informational only and does not
|
||||
// represent an actual packet.
|
||||
func (pkt *Base) InfoOnly() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ExpectInfo returns whether the next packet is expected to be informational only.
|
||||
func (pkt *Base) ExpectInfo() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// SetCtx sets the packet context.
|
||||
func (pkt *Base) SetCtx(ctx context.Context) {
|
||||
pkt.ctx = ctx
|
||||
}
|
||||
|
||||
// Ctx returns the packet context.
|
||||
func (pkt *Base) Ctx() context.Context {
|
||||
return pkt.ctx
|
||||
}
|
||||
|
||||
// Info returns the packet Info.
|
||||
func (pkt *Base) Info() *Info {
|
||||
return &pkt.info
|
||||
}
|
||||
|
||||
// SetPacketInfo sets a new packet Info. This must only used when initializing the packet structure.
|
||||
func (pkt *Base) SetPacketInfo(packetInfo Info) {
|
||||
pkt.info = packetInfo
|
||||
}
|
||||
|
||||
// SetInbound sets a the packet direction to inbound. This must only used when initializing the packet structure.
|
||||
func (pkt *Base) SetInbound() {
|
||||
pkt.info.Inbound = true
|
||||
}
|
||||
|
||||
// SetOutbound sets a the packet direction to outbound. This must only used when initializing the packet structure.
|
||||
func (pkt *Base) SetOutbound() {
|
||||
pkt.info.Inbound = false
|
||||
}
|
||||
|
||||
// IsInbound checks if the packet is inbound.
|
||||
func (pkt *Base) IsInbound() bool {
|
||||
return pkt.info.Inbound
|
||||
}
|
||||
|
||||
// IsOutbound checks if the packet is outbound.
|
||||
func (pkt *Base) IsOutbound() bool {
|
||||
return !pkt.info.Inbound
|
||||
}
|
||||
|
||||
// HasPorts checks if the packet has a protocol that uses ports.
|
||||
func (pkt *Base) HasPorts() bool {
|
||||
switch pkt.info.Protocol {
|
||||
case TCP:
|
||||
return true
|
||||
case UDP, UDPLite:
|
||||
return true
|
||||
case ICMP, ICMPv6, IGMP, RAW, AnyHostInternalProtocol61:
|
||||
fallthrough
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// LoadPacketData loads packet data from the integration, if not yet done.
|
||||
func (pkt *Base) LoadPacketData() error {
|
||||
return ErrFailedToLoadPayload
|
||||
}
|
||||
|
||||
// Layers returns the parsed layer data.
|
||||
func (pkt *Base) Layers() gopacket.Packet {
|
||||
return pkt.layers
|
||||
}
|
||||
|
||||
// Raw returns the raw Layer 3 Network Data.
|
||||
func (pkt *Base) Raw() []byte {
|
||||
return pkt.layer3Data
|
||||
}
|
||||
|
||||
// Payload returns the raw Layer 5 Network Data.
|
||||
func (pkt *Base) Payload() []byte {
|
||||
return pkt.layer5Data
|
||||
}
|
||||
|
||||
// GetConnectionID returns the link ID for this packet.
|
||||
func (pkt *Base) GetConnectionID() string {
|
||||
if pkt.connID == "" {
|
||||
pkt.connID = pkt.info.CreateConnectionID()
|
||||
}
|
||||
return pkt.connID
|
||||
}
|
||||
|
||||
// MatchesAddress checks if a the packet matches a given endpoint (remote or local) in protocol, network and port.
|
||||
//
|
||||
// Comparison matrix:
|
||||
//
|
||||
// ====== IN OUT
|
||||
//
|
||||
// Local Dst Src
|
||||
// Remote Src Dst
|
||||
// .
|
||||
func (pkt *Base) MatchesAddress(remote bool, protocol IPProtocol, network *net.IPNet, port uint16) bool {
|
||||
if pkt.info.Protocol != protocol {
|
||||
return false
|
||||
}
|
||||
if pkt.info.Inbound != remote {
|
||||
if !network.Contains(pkt.info.Src) {
|
||||
return false
|
||||
}
|
||||
if pkt.info.SrcPort != port {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if !network.Contains(pkt.info.Dst) {
|
||||
return false
|
||||
}
|
||||
if pkt.info.DstPort != port {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// MatchesIP checks if a the packet matches a given endpoint (remote or local) IP.
|
||||
//
|
||||
// Comparison matrix:
|
||||
//
|
||||
// ====== IN OUT
|
||||
//
|
||||
// Local Dst Src
|
||||
// Remote Src Dst
|
||||
// .
|
||||
func (pkt *Base) MatchesIP(endpoint bool, network *net.IPNet) bool {
|
||||
if pkt.info.Inbound != endpoint {
|
||||
if network.Contains(pkt.info.Src) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if network.Contains(pkt.info.Dst) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// FORMATTING
|
||||
|
||||
func (pkt *Base) String() string {
|
||||
return pkt.FmtPacket()
|
||||
}
|
||||
|
||||
// FmtPacket returns the most important information about the packet as a string.
|
||||
func (pkt *Base) FmtPacket() string {
|
||||
if pkt.info.Protocol == TCP || pkt.info.Protocol == UDP {
|
||||
if pkt.info.Inbound {
|
||||
return fmt.Sprintf("IN %s %s:%d <-> %s:%d", pkt.info.Protocol, pkt.info.Dst, pkt.info.DstPort, pkt.info.Src, pkt.info.SrcPort)
|
||||
}
|
||||
return fmt.Sprintf("OUT %s %s:%d <-> %s:%d", pkt.info.Protocol, pkt.info.Src, pkt.info.SrcPort, pkt.info.Dst, pkt.info.DstPort)
|
||||
}
|
||||
if pkt.info.Inbound {
|
||||
return fmt.Sprintf("IN %s %s <-> %s", pkt.info.Protocol, pkt.info.Dst, pkt.info.Src)
|
||||
}
|
||||
return fmt.Sprintf("OUT %s %s <-> %s", pkt.info.Protocol, pkt.info.Src, pkt.info.Dst)
|
||||
}
|
||||
|
||||
// FmtProtocol returns the protocol as a string.
|
||||
func (pkt *Base) FmtProtocol() string {
|
||||
return pkt.info.Protocol.String()
|
||||
}
|
||||
|
||||
// FmtRemoteIP returns the remote IP address as a string.
|
||||
func (pkt *Base) FmtRemoteIP() string {
|
||||
if pkt.info.Inbound {
|
||||
return pkt.info.Src.String()
|
||||
}
|
||||
return pkt.info.Dst.String()
|
||||
}
|
||||
|
||||
// FmtRemotePort returns the remote port as a string.
|
||||
func (pkt *Base) FmtRemotePort() string {
|
||||
if pkt.info.SrcPort != 0 {
|
||||
if pkt.info.Inbound {
|
||||
return fmt.Sprintf("%d", pkt.info.SrcPort)
|
||||
}
|
||||
return fmt.Sprintf("%d", pkt.info.DstPort)
|
||||
}
|
||||
return "-"
|
||||
}
|
||||
|
||||
// FmtRemoteAddress returns the full remote address (protocol, IP, port) as a string.
|
||||
func (pkt *Base) FmtRemoteAddress() string {
|
||||
return fmt.Sprintf("%s:%s:%s", pkt.info.Protocol.String(), pkt.FmtRemoteIP(), pkt.FmtRemotePort())
|
||||
}
|
||||
|
||||
// Packet is an interface to a network packet to provide object behavior the same across all systems.
|
||||
type Packet interface {
|
||||
// Verdicts.
|
||||
Accept() error
|
||||
Block() error
|
||||
Drop() error
|
||||
PermanentAccept() error
|
||||
PermanentBlock() error
|
||||
PermanentDrop() error
|
||||
RerouteToNameserver() error
|
||||
RerouteToTunnel() error
|
||||
FastTrackedByIntegration() bool
|
||||
InfoOnly() bool
|
||||
ExpectInfo() bool
|
||||
|
||||
// Info.
|
||||
SetCtx(context.Context)
|
||||
Ctx() context.Context
|
||||
Info() *Info
|
||||
SetPacketInfo(Info)
|
||||
IsInbound() bool
|
||||
IsOutbound() bool
|
||||
SetInbound()
|
||||
SetOutbound()
|
||||
HasPorts() bool
|
||||
GetConnectionID() string
|
||||
|
||||
// Payload.
|
||||
LoadPacketData() error
|
||||
Layers() gopacket.Packet
|
||||
Raw() []byte
|
||||
Payload() []byte
|
||||
|
||||
// Matching.
|
||||
MatchesAddress(bool, IPProtocol, *net.IPNet, uint16) bool
|
||||
MatchesIP(bool, *net.IPNet) bool
|
||||
|
||||
// Formatting.
|
||||
String() string
|
||||
FmtPacket() string
|
||||
FmtProtocol() string
|
||||
FmtRemoteIP() string
|
||||
FmtRemotePort() string
|
||||
FmtRemoteAddress() string
|
||||
}
|
||||
Reference in New Issue
Block a user