Skip to content

Instantly share code, notes, and snippets.

@kung-foo
Created May 10, 2017 17:22
Show Gist options
  • Save kung-foo/5fa23dcb473746798183106db1c1bd83 to your computer and use it in GitHub Desktop.
Save kung-foo/5fa23dcb473746798183106db1c1bd83 to your computer and use it in GitHub Desktop.
diff --git a/conntable.go b/conntable.go
index b2c8736..7e21f59 100644
--- a/conntable.go
+++ b/conntable.go
@@ -1,9 +1,13 @@
package freki
import (
+ "bytes"
+ "errors"
+ "fmt"
"net"
"strconv"
"sync"
+ "sync/atomic"
"time"
"github.com/google/gopacket"
@@ -12,6 +16,17 @@ import (
type ckey [2]uint64
+var (
+ // TODO: should this match net.nf_conntrack_max?
+ initialTableSize = 262144
+ connTimeout = time.Second * 600
+)
+
+var (
+ ErrUntrackedConnection = errors.New("untracked connection")
+)
+
+// TODO: look at using FlowFromEndpoints(...)
func NewConnKeyByEndpoints(clientAddr gopacket.Endpoint, clientPort gopacket.Endpoint) ckey {
if clientAddr.EndpointType() != layers.EndpointIPv4 {
panic("clientAddr endpoint must be of type layers.EndpointIPv4")
@@ -38,10 +53,9 @@ func NewConnKeyFromNetConn(conn net.Conn) ckey {
type Metadata struct {
Added time.Time
- LastUpdated time.Time
+ LastUpdated int64
Rule *Rule
TargetPort layers.TCPPort
- //TargetIP net.IP
}
type connTable struct {
@@ -51,8 +65,11 @@ type connTable struct {
}
func newConnTable(softLimit int) *connTable {
+ if softLimit < initialTableSize {
+ softLimit = initialTableSize
+ }
ct := &connTable{
- table: make(map[ckey]*Metadata, softLimit),
+ table: make(map[ckey]*Metadata, initialTableSize),
softLimit: softLimit,
}
@@ -72,31 +89,29 @@ func (t *connTable) Register(ck ckey, matchedRule *Rule, srcIP, srcPort string,
now := time.Now()
t.table[ck] = &Metadata{
Added: now,
- LastUpdated: now,
+ LastUpdated: now.UnixNano(),
Rule: matchedRule,
TargetPort: targetPort,
- //TargetIP: targetIP,
}
-
}
}
-func (t *connTable) FlushOlderOnes() {
+func (t *connTable) FlushOlderOnes() int {
t.mtx.Lock()
defer t.mtx.Unlock()
now := time.Now()
-
minutes := 30
+ flushed := 0
for minutes >= 0 {
-
duration := time.Duration(minutes) * time.Minute
- threshold := now.Add(-1 * duration)
+ threshold := now.Add(-1 * duration).UnixNano()
for ck, md := range t.table {
- if md.LastUpdated.Before(threshold) {
+ if md.LastUpdated < threshold {
delete(t.table, ck)
+ flushed++
}
}
@@ -106,19 +121,19 @@ func (t *connTable) FlushOlderOnes() {
minutes -= 10
}
}
+ return flushed
}
-func (t *connTable) updatePacketTime(ck ckey) {
+func (t *connTable) updatePacketTime(ck ckey) error {
t.mtx.RLock()
defer t.mtx.RUnlock()
if _, ok := t.table[ck]; ok {
- t.table[ck].LastUpdated = time.Now()
- } else {
- // TODO
- // What?
+ atomic.StoreInt64(&t.table[ck].LastUpdated, time.Now().UnixNano())
+ return nil
}
+ return ErrUntrackedConnection
}
// TODO: what happens when I return a *Metadata and then FlushOlderThan()
@@ -128,3 +143,16 @@ func (t *connTable) GetByFlow(ck ckey) *Metadata {
defer t.mtx.RUnlock()
return t.table[ck]
}
+
+func (t *connTable) dump() {
+ t.mtx.RLock()
+ defer t.mtx.RUnlock()
+
+ var buffer bytes.Buffer
+
+ for ck, md := range t.table {
+ buffer.WriteString(fmt.Sprintf("%v %+v\n", ck, md))
+ }
+
+ logger.Infof("\n%s", buffer.String())
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment