mirror of
https://github.com/safing/portmaster
synced 2025-09-02 02:29:12 +00:00
Improve packet parsing
This commit is contained in:
parent
3abaca1d90
commit
5d61b7b682
6 changed files with 62 additions and 21 deletions
|
@ -179,11 +179,13 @@ func (q *Queue) packetHandler(ctx context.Context) func(nfqueue.Attribute) int {
|
||||||
verdictPending: abool.New(),
|
verdictPending: abool.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if attrs.Payload != nil {
|
if attrs.Payload == nil {
|
||||||
pkt.Payload = *attrs.Payload
|
// There is not payload.
|
||||||
|
log.Warningf("nfqueue: packet #%s has no payload", pkt.pktID)
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := pmpacket.Parse(pkt.Payload, pkt.Info()); err != nil {
|
if err := pmpacket.Parse(*attrs.Payload, &pkt.Base); err != nil {
|
||||||
log.Warningf("nfqueue: failed to parse payload: %s", err)
|
log.Warningf("nfqueue: failed to parse payload: %s", err)
|
||||||
_ = pkt.Drop()
|
_ = pkt.Drop()
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -65,6 +65,11 @@ func (pkt *packet) ID() string {
|
||||||
return fmt.Sprintf("pkt:%d qid:%d", pkt.pktID, pkt.queue.id)
|
return fmt.Sprintf("pkt:%d qid:%d", pkt.pktID, pkt.queue.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadPacketData does nothing on Linux, as data is always fully parsed.
|
||||||
|
func (pkt *packet) LoadPacketData() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(ppacher): revisit the following behavior:
|
// TODO(ppacher): revisit the following behavior:
|
||||||
// The legacy implementation of nfqueue (and the interception) module
|
// The legacy implementation of nfqueue (and the interception) module
|
||||||
// always accept a packet but may mark it so that a subsequent rule in
|
// always accept a packet but may mark it so that a subsequent rule in
|
||||||
|
|
|
@ -230,6 +230,7 @@ func GetPayload(packetID uint32, packetSize uint32) ([]byte, error) {
|
||||||
if packetSize < uint32(len(buf)) {
|
if packetSize < uint32(len(buf)) {
|
||||||
return buf[:packetSize], nil
|
return buf[:packetSize], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ type Packet struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPayload returns the full raw packet.
|
// GetPayload returns the full raw packet.
|
||||||
func (pkt *Packet) GetPayload() ([]byte, error) {
|
func (pkt *Packet) LoadPacketData() error {
|
||||||
pkt.lock.Lock()
|
pkt.lock.Lock()
|
||||||
defer pkt.lock.Unlock()
|
defer pkt.lock.Unlock()
|
||||||
|
|
||||||
|
@ -33,17 +33,21 @@ func (pkt *Packet) GetPayload() ([]byte, error) {
|
||||||
|
|
||||||
payload, err := GetPayload(pkt.verdictRequest.id, pkt.verdictRequest.packetSize)
|
payload, err := GetPayload(pkt.verdictRequest.id, pkt.verdictRequest.packetSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Tracer(pkt.Ctx()).Warningf("windowskext: failed to load payload %s", err)
|
log.Tracer(pkt.Ctx()).Warningf("windowskext: failed to load payload: %s", err)
|
||||||
log.Errorf("windowskext: failed to load payload %s", err)
|
return packet.ErrFailedToLoadPayload
|
||||||
return nil, packet.ErrFailedToLoadPayload
|
}
|
||||||
|
|
||||||
|
err = packet.Parse(payload, &pkt.Base)
|
||||||
|
if err != nil {
|
||||||
|
log.Tracer(pkt.Ctx()).Warningf("windowskext: failed to parse payload: %s", err)
|
||||||
|
return packet.ErrFailedToLoadPayload
|
||||||
}
|
}
|
||||||
pkt.Payload = payload
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pkt.Payload) == 0 {
|
if len(pkt.Raw()) == 0 {
|
||||||
return nil, packet.ErrFailedToLoadPayload
|
return packet.ErrFailedToLoadPayload
|
||||||
}
|
}
|
||||||
return pkt.Payload, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept accepts the packet.
|
// Accept accepts the packet.
|
||||||
|
|
|
@ -4,14 +4,18 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/google/gopacket"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Base is a base structure for satisfying the Packet interface.
|
// Base is a base structure for satisfying the Packet interface.
|
||||||
type Base struct {
|
type Base struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
info Info
|
info Info
|
||||||
connID string
|
connID string
|
||||||
Payload []byte
|
layers gopacket.Packet
|
||||||
|
layer3Data []byte
|
||||||
|
layer5Data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCtx sets the packet context.
|
// SetCtx sets the packet context.
|
||||||
|
@ -65,9 +69,24 @@ func (pkt *Base) HasPorts() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPayload returns the packet payload. In some cases, this will fetch the payload from the os integration system.
|
// LoadPacketData loads packet data from the integration, if not yet done.
|
||||||
func (pkt *Base) GetPayload() ([]byte, error) {
|
func (pkt *Base) LoadPacketData() error {
|
||||||
return pkt.Payload, ErrFailedToLoadPayload
|
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.
|
// GetConnectionID returns the link ID for this packet.
|
||||||
|
@ -214,9 +233,14 @@ type Packet interface {
|
||||||
SetInbound()
|
SetInbound()
|
||||||
SetOutbound()
|
SetOutbound()
|
||||||
HasPorts() bool
|
HasPorts() bool
|
||||||
GetPayload() ([]byte, error)
|
|
||||||
GetConnectionID() string
|
GetConnectionID() string
|
||||||
|
|
||||||
|
// PAYLOAD
|
||||||
|
LoadPacketData() error
|
||||||
|
Layers() gopacket.Packet
|
||||||
|
Raw() []byte
|
||||||
|
Payload() []byte
|
||||||
|
|
||||||
// MATCHING
|
// MATCHING
|
||||||
MatchesAddress(bool, IPProtocol, *net.IPNet, uint16) bool
|
MatchesAddress(bool, IPProtocol, *net.IPNet, uint16) bool
|
||||||
MatchesIP(bool, *net.IPNet) bool
|
MatchesIP(bool, *net.IPNet) bool
|
||||||
|
|
|
@ -102,10 +102,11 @@ func checkError(packet gopacket.Packet, _ *Info) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse parses an IP packet and saves the information in the given packet object.
|
// Parse parses an IP packet and saves the information in the given packet object.
|
||||||
func Parse(packetData []byte, pktInfo *Info) error {
|
func Parse(packetData []byte, pktBase *Base) (err error) {
|
||||||
if len(packetData) == 0 {
|
if len(packetData) == 0 {
|
||||||
return errors.New("empty packet")
|
return errors.New("empty packet")
|
||||||
}
|
}
|
||||||
|
pktBase.layer3Data = packetData
|
||||||
|
|
||||||
ipVersion := packetData[0] >> 4
|
ipVersion := packetData[0] >> 4
|
||||||
var networkLayerType gopacket.LayerType
|
var networkLayerType gopacket.LayerType
|
||||||
|
@ -137,11 +138,15 @@ func Parse(packetData []byte, pktInfo *Info) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, dec := range availableDecoders {
|
for _, dec := range availableDecoders {
|
||||||
if err := dec(packet, pktInfo); err != nil {
|
if err := dec(packet, pktBase.Info()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pktBase.layers = packet
|
||||||
|
if packet.TransportLayer() != nil {
|
||||||
|
pktBase.layer5Data = packet.TransportLayer().LayerPayload()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue