Created
May 10, 2017 17:22
-
-
Save kung-foo/5fa23dcb473746798183106db1c1bd83 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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