build(deps): bump github.com/vishvananda/netlink
Bumps [github.com/vishvananda/netlink](https://github.com/vishvananda/netlink) from 1.2.1-beta.2 to 1.3.0. - [Release notes](https://github.com/vishvananda/netlink/releases) - [Commits](https://github.com/vishvananda/netlink/compare/v1.2.1-beta.2...v1.3.0) --- updated-dependencies: - dependency-name: github.com/vishvananda/netlink dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
423
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
423
vendor/github.com/vishvananda/netlink/conntrack_linux.go
generated
vendored
@@ -55,10 +55,30 @@ func ConntrackTableFlush(table ConntrackTableType) error {
|
||||
return pkgHandle.ConntrackTableFlush(table)
|
||||
}
|
||||
|
||||
// ConntrackCreate creates a new conntrack flow in the desired table
|
||||
// conntrack -I [table] Create a conntrack or expectation
|
||||
func ConntrackCreate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
return pkgHandle.ConntrackCreate(table, family, flow)
|
||||
}
|
||||
|
||||
// ConntrackUpdate updates an existing conntrack flow in the desired table using the handle
|
||||
// conntrack -U [table] Update a conntrack
|
||||
func ConntrackUpdate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
return pkgHandle.ConntrackUpdate(table, family, flow)
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
//
|
||||
// Deprecated: use [ConntrackDeleteFilter] instead.
|
||||
func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) {
|
||||
return pkgHandle.ConntrackDeleteFilter(table, family, filter)
|
||||
return pkgHandle.ConntrackDeleteFilters(table, family, filter)
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
func ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
|
||||
return pkgHandle.ConntrackDeleteFilters(table, family, filters...)
|
||||
}
|
||||
|
||||
// ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed
|
||||
@@ -87,9 +107,51 @@ func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// ConntrackCreate creates a new conntrack flow in the desired table using the handle
|
||||
// conntrack -I [table] Create a conntrack or expectation
|
||||
func (h *Handle) ConntrackCreate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_NEW, unix.NLM_F_ACK|unix.NLM_F_CREATE)
|
||||
attr, err := flow.toNlData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, a := range attr {
|
||||
req.AddData(a)
|
||||
}
|
||||
|
||||
_, err = req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// ConntrackUpdate updates an existing conntrack flow in the desired table using the handle
|
||||
// conntrack -U [table] Update a conntrack
|
||||
func (h *Handle) ConntrackUpdate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error {
|
||||
req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_NEW, unix.NLM_F_ACK|unix.NLM_F_REPLACE)
|
||||
attr, err := flow.toNlData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, a := range attr {
|
||||
req.AddData(a)
|
||||
}
|
||||
|
||||
_, err = req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
return err
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
//
|
||||
// Deprecated: use [Handle.ConntrackDeleteFilters] instead.
|
||||
func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) {
|
||||
return h.ConntrackDeleteFilters(table, family, filter)
|
||||
}
|
||||
|
||||
// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters using the netlink handle passed
|
||||
// conntrack -D [table] parameters Delete conntrack or expectation
|
||||
func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) {
|
||||
res, err := h.dumpConntrackTable(table, family)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -98,12 +160,16 @@ func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFami
|
||||
var matched uint
|
||||
for _, dataRaw := range res {
|
||||
flow := parseRawData(dataRaw)
|
||||
if match := filter.MatchConntrackFlow(flow); match {
|
||||
req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK)
|
||||
// skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already
|
||||
req2.AddRawData(dataRaw[4:])
|
||||
req2.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
matched++
|
||||
for _, filter := range filters {
|
||||
if match := filter.MatchConntrackFlow(flow); match {
|
||||
req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK)
|
||||
// skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already
|
||||
req2.AddRawData(dataRaw[4:])
|
||||
req2.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
matched++
|
||||
// flow is already deleted, no need to match on other filters and continue to the next flow.
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,10 +194,44 @@ func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily)
|
||||
return req.Execute(unix.NETLINK_NETFILTER, 0)
|
||||
}
|
||||
|
||||
// ProtoInfo wraps an L4-protocol structure - roughly corresponds to the
|
||||
// __nfct_protoinfo union found in libnetfilter_conntrack/include/internal/object.h.
|
||||
// Currently, only protocol names, and TCP state is supported.
|
||||
type ProtoInfo interface {
|
||||
Protocol() string
|
||||
}
|
||||
|
||||
// ProtoInfoTCP corresponds to the `tcp` struct of the __nfct_protoinfo union.
|
||||
// Only TCP state is currently supported.
|
||||
type ProtoInfoTCP struct {
|
||||
State uint8
|
||||
}
|
||||
// Protocol returns "tcp".
|
||||
func (*ProtoInfoTCP) Protocol() string {return "tcp"}
|
||||
func (p *ProtoInfoTCP) toNlData() ([]*nl.RtAttr, error) {
|
||||
ctProtoInfo := nl.NewRtAttr(unix.NLA_F_NESTED | nl.CTA_PROTOINFO, []byte{})
|
||||
ctProtoInfoTCP := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_PROTOINFO_TCP, []byte{})
|
||||
ctProtoInfoTCPState := nl.NewRtAttr(nl.CTA_PROTOINFO_TCP_STATE, nl.Uint8Attr(p.State))
|
||||
ctProtoInfoTCP.AddChild(ctProtoInfoTCPState)
|
||||
ctProtoInfo.AddChild(ctProtoInfoTCP)
|
||||
|
||||
return []*nl.RtAttr{ctProtoInfo}, nil
|
||||
}
|
||||
|
||||
// ProtoInfoSCTP only supports the protocol name.
|
||||
type ProtoInfoSCTP struct {}
|
||||
// Protocol returns "sctp".
|
||||
func (*ProtoInfoSCTP) Protocol() string {return "sctp"}
|
||||
|
||||
// ProtoInfoDCCP only supports the protocol name.
|
||||
type ProtoInfoDCCP struct {}
|
||||
// Protocol returns "dccp".
|
||||
func (*ProtoInfoDCCP) Protocol() string {return "dccp"}
|
||||
|
||||
// The full conntrack flow structure is very complicated and can be found in the file:
|
||||
// http://git.netfilter.org/libnetfilter_conntrack/tree/include/internal/object.h
|
||||
// For the time being, the structure below allows to parse and extract the base information of a flow
|
||||
type ipTuple struct {
|
||||
type IPTuple struct {
|
||||
Bytes uint64
|
||||
DstIP net.IP
|
||||
DstPort uint16
|
||||
@@ -141,28 +241,150 @@ type ipTuple struct {
|
||||
SrcPort uint16
|
||||
}
|
||||
|
||||
// toNlData generates the inner fields of a nested tuple netlink datastructure
|
||||
// does not generate the "nested"-flagged outer message.
|
||||
func (t *IPTuple) toNlData(family uint8) ([]*nl.RtAttr, error) {
|
||||
|
||||
var srcIPsFlag, dstIPsFlag int
|
||||
if family == nl.FAMILY_V4 {
|
||||
srcIPsFlag = nl.CTA_IP_V4_SRC
|
||||
dstIPsFlag = nl.CTA_IP_V4_DST
|
||||
} else if family == nl.FAMILY_V6 {
|
||||
srcIPsFlag = nl.CTA_IP_V6_SRC
|
||||
dstIPsFlag = nl.CTA_IP_V6_DST
|
||||
} else {
|
||||
return []*nl.RtAttr{}, fmt.Errorf("couldn't generate netlink message for tuple due to unrecognized FamilyType '%d'", family)
|
||||
}
|
||||
|
||||
ctTupleIP := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_IP, nil)
|
||||
ctTupleIPSrc := nl.NewRtAttr(srcIPsFlag, t.SrcIP)
|
||||
ctTupleIP.AddChild(ctTupleIPSrc)
|
||||
ctTupleIPDst := nl.NewRtAttr(dstIPsFlag, t.DstIP)
|
||||
ctTupleIP.AddChild(ctTupleIPDst)
|
||||
|
||||
ctTupleProto := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_PROTO, nil)
|
||||
ctTupleProtoNum := nl.NewRtAttr(nl.CTA_PROTO_NUM, []byte{t.Protocol})
|
||||
ctTupleProto.AddChild(ctTupleProtoNum)
|
||||
ctTupleProtoSrcPort := nl.NewRtAttr(nl.CTA_PROTO_SRC_PORT, nl.BEUint16Attr(t.SrcPort))
|
||||
ctTupleProto.AddChild(ctTupleProtoSrcPort)
|
||||
ctTupleProtoDstPort := nl.NewRtAttr(nl.CTA_PROTO_DST_PORT, nl.BEUint16Attr(t.DstPort))
|
||||
ctTupleProto.AddChild(ctTupleProtoDstPort, )
|
||||
|
||||
return []*nl.RtAttr{ctTupleIP, ctTupleProto}, nil
|
||||
}
|
||||
|
||||
type ConntrackFlow struct {
|
||||
FamilyType uint8
|
||||
Forward ipTuple
|
||||
Reverse ipTuple
|
||||
Forward IPTuple
|
||||
Reverse IPTuple
|
||||
Mark uint32
|
||||
Zone uint16
|
||||
TimeStart uint64
|
||||
TimeStop uint64
|
||||
TimeOut uint32
|
||||
Labels []byte
|
||||
ProtoInfo ProtoInfo
|
||||
}
|
||||
|
||||
func (s *ConntrackFlow) String() string {
|
||||
// conntrack cmd output:
|
||||
// udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0
|
||||
// udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0 labels=0x00000000050012ac4202010000000000 zone=100
|
||||
// start=2019-07-26 01:26:21.557800506 +0000 UTC stop=1970-01-01 00:00:00 +0000 UTC timeout=30(sec)
|
||||
start := time.Unix(0, int64(s.TimeStart))
|
||||
stop := time.Unix(0, int64(s.TimeStop))
|
||||
timeout := int32(s.TimeOut)
|
||||
return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=0x%x start=%v stop=%v timeout=%d(sec)",
|
||||
res := fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=0x%x ",
|
||||
nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol,
|
||||
s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort, s.Forward.Packets, s.Forward.Bytes,
|
||||
s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort, s.Reverse.Packets, s.Reverse.Bytes,
|
||||
s.Mark, start, stop, timeout)
|
||||
s.Mark)
|
||||
if len(s.Labels) > 0 {
|
||||
res += fmt.Sprintf("labels=0x%x ", s.Labels)
|
||||
}
|
||||
if s.Zone != 0 {
|
||||
res += fmt.Sprintf("zone=%d ", s.Zone)
|
||||
}
|
||||
res += fmt.Sprintf("start=%v stop=%v timeout=%d(sec)", start, stop, timeout)
|
||||
return res
|
||||
}
|
||||
|
||||
// toNlData generates netlink messages representing the flow.
|
||||
func (s *ConntrackFlow) toNlData() ([]*nl.RtAttr, error) {
|
||||
var payload []*nl.RtAttr
|
||||
// The message structure is built as follows:
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_ORIG>
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_IP>
|
||||
// <len, [CTA_IP_V4_SRC|CTA_IP_V6_SRC]>
|
||||
// <IP>
|
||||
// <len, [CTA_IP_V4_DST|CTA_IP_V6_DST]>
|
||||
// <IP>
|
||||
// <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO>
|
||||
// <len, CTA_PROTO_NUM>
|
||||
// <uint8>
|
||||
// <len, CTA_PROTO_SRC_PORT>
|
||||
// <BEuint16>
|
||||
// <len, CTA_PROTO_DST_PORT>
|
||||
// <BEuint16>
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_REPLY>
|
||||
// <len, NLA_F_NESTED|CTA_TUPLE_IP>
|
||||
// <len, [CTA_IP_V4_SRC|CTA_IP_V6_SRC]>
|
||||
// <IP>
|
||||
// <len, [CTA_IP_V4_DST|CTA_IP_V6_DST]>
|
||||
// <IP>
|
||||
// <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO>
|
||||
// <len, CTA_PROTO_NUM>
|
||||
// <uint8>
|
||||
// <len, CTA_PROTO_SRC_PORT>
|
||||
// <BEuint16>
|
||||
// <len, CTA_PROTO_DST_PORT>
|
||||
// <BEuint16>
|
||||
// <len, CTA_STATUS>
|
||||
// <uint64>
|
||||
// <len, CTA_MARK>
|
||||
// <BEuint64>
|
||||
// <len, CTA_TIMEOUT>
|
||||
// <BEuint64>
|
||||
// <len, NLA_F_NESTED|CTA_PROTOINFO>
|
||||
|
||||
// CTA_TUPLE_ORIG
|
||||
ctTupleOrig := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_ORIG, nil)
|
||||
forwardFlowAttrs, err := s.Forward.toNlData(s.FamilyType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't generate netlink data for conntrack forward flow: %w", err)
|
||||
}
|
||||
for _, a := range forwardFlowAttrs {
|
||||
ctTupleOrig.AddChild(a)
|
||||
}
|
||||
|
||||
// CTA_TUPLE_REPLY
|
||||
ctTupleReply := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_REPLY, nil)
|
||||
reverseFlowAttrs, err := s.Reverse.toNlData(s.FamilyType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't generate netlink data for conntrack reverse flow: %w", err)
|
||||
}
|
||||
for _, a := range reverseFlowAttrs {
|
||||
ctTupleReply.AddChild(a)
|
||||
}
|
||||
|
||||
ctMark := nl.NewRtAttr(nl.CTA_MARK, nl.BEUint32Attr(s.Mark))
|
||||
ctTimeout := nl.NewRtAttr(nl.CTA_TIMEOUT, nl.BEUint32Attr(s.TimeOut))
|
||||
|
||||
payload = append(payload, ctTupleOrig, ctTupleReply, ctMark, ctTimeout)
|
||||
|
||||
if s.ProtoInfo != nil {
|
||||
switch p := s.ProtoInfo.(type) {
|
||||
case *ProtoInfoTCP:
|
||||
attrs, err := p.toNlData()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't generate netlink data for conntrack flow's TCP protoinfo: %w", err)
|
||||
}
|
||||
payload = append(payload, attrs...)
|
||||
default:
|
||||
return nil, errors.New("couldn't generate netlink data for conntrack: field 'ProtoInfo' only supports TCP or nil")
|
||||
}
|
||||
}
|
||||
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
// This method parse the ip tuple structure
|
||||
@@ -172,7 +394,7 @@ func (s *ConntrackFlow) String() string {
|
||||
// <len, NLA_F_NESTED|nl.CTA_TUPLE_PROTO, 1 byte for the protocol, 3 bytes of padding>
|
||||
// <len, CTA_PROTO_SRC_PORT, 2 bytes for the source port, 2 bytes of padding>
|
||||
// <len, CTA_PROTO_DST_PORT, 2 bytes for the source port, 2 bytes of padding>
|
||||
func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
|
||||
func parseIpTuple(reader *bytes.Reader, tpl *IPTuple) uint8 {
|
||||
for i := 0; i < 2; i++ {
|
||||
_, t, _, v := parseNfAttrTLV(reader)
|
||||
switch t {
|
||||
@@ -191,7 +413,7 @@ func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 {
|
||||
tpl.Protocol = uint8(v[0])
|
||||
}
|
||||
// We only parse TCP & UDP headers. Skip the others.
|
||||
if tpl.Protocol != 6 && tpl.Protocol != 17 {
|
||||
if tpl.Protocol != unix.IPPROTO_TCP && tpl.Protocol != unix.IPPROTO_UDP {
|
||||
// skip the rest
|
||||
bytesRemaining := protoInfoTotalLen - protoInfoBytesRead
|
||||
reader.Seek(int64(bytesRemaining), seekCurrent)
|
||||
@@ -240,9 +462,13 @@ func parseNfAttrTL(r *bytes.Reader) (isNested bool, attrType, len uint16) {
|
||||
return isNested, attrType, len
|
||||
}
|
||||
|
||||
func skipNfAttrValue(r *bytes.Reader, len uint16) {
|
||||
// skipNfAttrValue seeks `r` past attr of length `len`.
|
||||
// Maintains buffer alignment.
|
||||
// Returns length of the seek performed.
|
||||
func skipNfAttrValue(r *bytes.Reader, len uint16) uint16 {
|
||||
len = (len + nl.NLA_ALIGNTO - 1) & ^(nl.NLA_ALIGNTO - 1)
|
||||
r.Seek(int64(len), seekCurrent)
|
||||
return len
|
||||
}
|
||||
|
||||
func parseBERaw16(r *bytes.Reader, v *uint16) {
|
||||
@@ -257,6 +483,10 @@ func parseBERaw64(r *bytes.Reader, v *uint64) {
|
||||
binary.Read(r, binary.BigEndian, v)
|
||||
}
|
||||
|
||||
func parseRaw32(r *bytes.Reader, v *uint32) {
|
||||
binary.Read(r, nl.NativeEndian(), v)
|
||||
}
|
||||
|
||||
func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) {
|
||||
for i := 0; i < 2; i++ {
|
||||
switch _, t, _ := parseNfAttrTL(r); t {
|
||||
@@ -296,6 +526,60 @@ func parseTimeStamp(r *bytes.Reader, readSize uint16) (tstart, tstop uint64) {
|
||||
|
||||
}
|
||||
|
||||
func parseProtoInfoTCPState(r *bytes.Reader) (s uint8) {
|
||||
binary.Read(r, binary.BigEndian, &s)
|
||||
r.Seek(nl.SizeofNfattr - 1, seekCurrent)
|
||||
return s
|
||||
}
|
||||
|
||||
// parseProtoInfoTCP reads the entire nested protoinfo structure, but only parses the state attr.
|
||||
func parseProtoInfoTCP(r *bytes.Reader, attrLen uint16) (*ProtoInfoTCP) {
|
||||
p := new(ProtoInfoTCP)
|
||||
bytesRead := 0
|
||||
for bytesRead < int(attrLen) {
|
||||
_, t, l := parseNfAttrTL(r)
|
||||
bytesRead += nl.SizeofNfattr
|
||||
|
||||
switch t {
|
||||
case nl.CTA_PROTOINFO_TCP_STATE:
|
||||
p.State = parseProtoInfoTCPState(r)
|
||||
bytesRead += nl.SizeofNfattr
|
||||
default:
|
||||
bytesRead += int(skipNfAttrValue(r, l))
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func parseProtoInfo(r *bytes.Reader, attrLen uint16) (p ProtoInfo) {
|
||||
bytesRead := 0
|
||||
for bytesRead < int(attrLen) {
|
||||
_, t, l := parseNfAttrTL(r)
|
||||
bytesRead += nl.SizeofNfattr
|
||||
|
||||
switch t {
|
||||
case nl.CTA_PROTOINFO_TCP:
|
||||
p = parseProtoInfoTCP(r, l)
|
||||
bytesRead += int(l)
|
||||
// No inner fields of DCCP / SCTP currently supported.
|
||||
case nl.CTA_PROTOINFO_DCCP:
|
||||
p = new(ProtoInfoDCCP)
|
||||
skipped := skipNfAttrValue(r, l)
|
||||
bytesRead += int(skipped)
|
||||
case nl.CTA_PROTOINFO_SCTP:
|
||||
p = new(ProtoInfoSCTP)
|
||||
skipped := skipNfAttrValue(r, l)
|
||||
bytesRead += int(skipped)
|
||||
default:
|
||||
skipped := skipNfAttrValue(r, l)
|
||||
bytesRead += int(skipped)
|
||||
}
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func parseTimeOut(r *bytes.Reader) (ttimeout uint32) {
|
||||
parseBERaw32(r, &ttimeout)
|
||||
return
|
||||
@@ -306,6 +590,18 @@ func parseConnectionMark(r *bytes.Reader) (mark uint32) {
|
||||
return
|
||||
}
|
||||
|
||||
func parseConnectionLabels(r *bytes.Reader) (label []byte) {
|
||||
label = make([]byte, 16) // netfilter defines 128 bit labels value
|
||||
binary.Read(r, nl.NativeEndian(), &label)
|
||||
return
|
||||
}
|
||||
|
||||
func parseConnectionZone(r *bytes.Reader) (zone uint16) {
|
||||
parseBERaw16(r, &zone)
|
||||
r.Seek(2, seekCurrent)
|
||||
return
|
||||
}
|
||||
|
||||
func parseRawData(data []byte) *ConntrackFlow {
|
||||
s := &ConntrackFlow{}
|
||||
// First there is the Nfgenmsg header
|
||||
@@ -343,7 +639,7 @@ func parseRawData(data []byte) *ConntrackFlow {
|
||||
case nl.CTA_TIMESTAMP:
|
||||
s.TimeStart, s.TimeStop = parseTimeStamp(reader, l)
|
||||
case nl.CTA_PROTOINFO:
|
||||
skipNfAttrValue(reader, l)
|
||||
s.ProtoInfo = parseProtoInfo(reader, l)
|
||||
default:
|
||||
skipNfAttrValue(reader, l)
|
||||
}
|
||||
@@ -351,10 +647,14 @@ func parseRawData(data []byte) *ConntrackFlow {
|
||||
switch t {
|
||||
case nl.CTA_MARK:
|
||||
s.Mark = parseConnectionMark(reader)
|
||||
case nl.CTA_LABELS:
|
||||
s.Labels = parseConnectionLabels(reader)
|
||||
case nl.CTA_TIMEOUT:
|
||||
s.TimeOut = parseTimeOut(reader)
|
||||
case nl.CTA_STATUS, nl.CTA_USE, nl.CTA_ID:
|
||||
case nl.CTA_ID, nl.CTA_STATUS, nl.CTA_USE:
|
||||
skipNfAttrValue(reader, l)
|
||||
case nl.CTA_ZONE:
|
||||
s.Zone = parseConnectionZone(reader)
|
||||
default:
|
||||
skipNfAttrValue(reader, l)
|
||||
}
|
||||
@@ -399,16 +699,18 @@ func parseRawData(data []byte) *ConntrackFlow {
|
||||
type ConntrackFilterType uint8
|
||||
|
||||
const (
|
||||
ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction
|
||||
ConntrackOrigDstIP // -orig-dst ip Destination address from original direction
|
||||
ConntrackReplySrcIP // --reply-src ip Reply Source IP
|
||||
ConntrackReplyDstIP // --reply-dst ip Reply Destination IP
|
||||
ConntrackReplyAnyIP // Match source or destination reply IP
|
||||
ConntrackOrigSrcPort // --orig-port-src port Source port in original direction
|
||||
ConntrackOrigDstPort // --orig-port-dst port Destination port in original direction
|
||||
ConntrackNatSrcIP = ConntrackReplySrcIP // deprecated use instead ConntrackReplySrcIP
|
||||
ConntrackNatDstIP = ConntrackReplyDstIP // deprecated use instead ConntrackReplyDstIP
|
||||
ConntrackNatAnyIP = ConntrackReplyAnyIP // deprecated use instead ConntrackReplyAnyIP
|
||||
ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction
|
||||
ConntrackOrigDstIP // -orig-dst ip Destination address from original direction
|
||||
ConntrackReplySrcIP // --reply-src ip Reply Source IP
|
||||
ConntrackReplyDstIP // --reply-dst ip Reply Destination IP
|
||||
ConntrackReplyAnyIP // Match source or destination reply IP
|
||||
ConntrackOrigSrcPort // --orig-port-src port Source port in original direction
|
||||
ConntrackOrigDstPort // --orig-port-dst port Destination port in original direction
|
||||
ConntrackMatchLabels // --label label1,label2 Labels used in entry
|
||||
ConntrackUnmatchLabels // --label label1,label2 Labels not used in entry
|
||||
ConntrackNatSrcIP = ConntrackReplySrcIP // deprecated use instead ConntrackReplySrcIP
|
||||
ConntrackNatDstIP = ConntrackReplyDstIP // deprecated use instead ConntrackReplyDstIP
|
||||
ConntrackNatAnyIP = ConntrackReplyAnyIP // deprecated use instead ConntrackReplyAnyIP
|
||||
)
|
||||
|
||||
type CustomConntrackFilter interface {
|
||||
@@ -421,6 +723,8 @@ type ConntrackFilter struct {
|
||||
ipNetFilter map[ConntrackFilterType]*net.IPNet
|
||||
portFilter map[ConntrackFilterType]uint16
|
||||
protoFilter uint8
|
||||
labelFilter map[ConntrackFilterType][][]byte
|
||||
zoneFilter *uint16
|
||||
}
|
||||
|
||||
// AddIPNet adds a IP subnet to the conntrack filter
|
||||
@@ -474,10 +778,43 @@ func (f *ConntrackFilter) AddProtocol(proto uint8) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddLabels adds the provided list (zero or more) of labels to the conntrack filter
|
||||
// ConntrackFilterType here can be either:
|
||||
// 1. ConntrackMatchLabels: This matches every flow that has a label value (len(flow.Labels) > 0)
|
||||
// against the list of provided labels. If `flow.Labels` contains ALL the provided labels
|
||||
// it is considered a match. This can be used when you want to match flows that contain
|
||||
// one or more labels.
|
||||
// 2. ConntrackUnmatchLabels: This matches every flow that has a label value (len(flow.Labels) > 0)
|
||||
// against the list of provided labels. If `flow.Labels` does NOT contain ALL the provided labels
|
||||
// it is considered a match. This can be used when you want to match flows that don't contain
|
||||
// one or more labels.
|
||||
func (f *ConntrackFilter) AddLabels(tp ConntrackFilterType, labels [][]byte) error {
|
||||
if len(labels) == 0 {
|
||||
return errors.New("Invalid length for provided labels")
|
||||
}
|
||||
if f.labelFilter == nil {
|
||||
f.labelFilter = make(map[ConntrackFilterType][][]byte)
|
||||
}
|
||||
if _, ok := f.labelFilter[tp]; ok {
|
||||
return errors.New("Filter attribute already present")
|
||||
}
|
||||
f.labelFilter[tp] = labels
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddZone adds a zone to the conntrack filter
|
||||
func (f *ConntrackFilter) AddZone(zone uint16) error {
|
||||
if f.zoneFilter != nil {
|
||||
return errors.New("Filter attribute already present")
|
||||
}
|
||||
f.zoneFilter = &zone
|
||||
return nil
|
||||
}
|
||||
|
||||
// MatchConntrackFlow applies the filter to the flow and returns true if the flow matches the filter
|
||||
// false otherwise
|
||||
func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
||||
if len(f.ipNetFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 {
|
||||
if len(f.ipNetFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 && len(f.labelFilter) == 0 && f.zoneFilter == nil {
|
||||
// empty filter always not match
|
||||
return false
|
||||
}
|
||||
@@ -488,6 +825,11 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Conntrack zone filter
|
||||
if f.zoneFilter != nil && *f.zoneFilter != flow.Zone {
|
||||
return false
|
||||
}
|
||||
|
||||
match := true
|
||||
|
||||
// IP conntrack filter
|
||||
@@ -531,6 +873,29 @@ func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// Label filter
|
||||
if len(f.labelFilter) > 0 {
|
||||
if len(flow.Labels) > 0 {
|
||||
// --label label1,label2 in conn entry;
|
||||
// every label passed should be contained in flow.Labels for a match to be true
|
||||
if elem, found := f.labelFilter[ConntrackMatchLabels]; match && found {
|
||||
for _, label := range elem {
|
||||
match = match && (bytes.Contains(flow.Labels, label))
|
||||
}
|
||||
}
|
||||
// --label label1,label2 in conn entry;
|
||||
// every label passed should be not contained in flow.Labels for a match to be true
|
||||
if elem, found := f.labelFilter[ConntrackUnmatchLabels]; match && found {
|
||||
for _, label := range elem {
|
||||
match = match && !(bytes.Contains(flow.Labels, label))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// flow doesn't contain labels, so it doesn't contain or notContain any provided matches
|
||||
match = false
|
||||
}
|
||||
}
|
||||
|
||||
return match
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user