func (conn *TCPConn) captureFlow(handle *net.IPConn, port int) {
	buf := make([]byte, 2048)
	opt := gopacket.DecodeOptions{NoCopy: true, Lazy: true}
	for {
		n, addr, err := handle.ReadFromIP(buf)
		if err != nil {
			return
		}
		packet := gopacket.NewPacket(buf[:n], layers.LayerTypeTCP, opt)
		transport := packet.TransportLayer()
		tcp, ok := transport.(*layers.TCP)
		if !ok {
			continue
		}
		if int(tcp.DstPort) != port {
			continue
		}
		var src net.TCPAddr
		src.IP = addr.IP
		src.Port = int(tcp.SrcPort)
		var orphan bool
		conn.lockflow(&src, func(e *tcpFlow) {
			if e.conn == nil {  
				orphan = true  
			}
			e.ts = time.Now()
			if tcp.ACK {
				e.seq = tcp.Ack
			}
			if tcp.SYN {
				e.ack = tcp.Seq + 1
			}
			if tcp.PSH {
				if e.ack == tcp.Seq {
					e.ack = tcp.Seq + uint32(len(tcp.Payload))
				}
			}
			e.handle = handle
		})
		if !orphan && tcp.PSH {
			payload := make([]byte, len(tcp.Payload))
			copy(payload, tcp.Payload)
			select {
			case conn.chMessage <- message{payload, &src}:
			case <-conn.die:
				return
			}
		}
	}
}
captureFlow capture every inbound packets based on rules of BPF
package tcpraw
import (
	"crypto/rand"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"sync"
	"sync/atomic"
	"syscall"
	"time"
	"github.com/coreos/go-iptables/iptables"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
)
var (
	errOpNotImplemented = errors.New("operation not implemented")
	errTimeout          = errors.New("timeout")
	expire              = time.Minute
)
type message struct {
	bts  []byte
	addr net.Addr
}
type tcpFlow struct {
	conn         *net.TCPConn                
	handle       *net.IPConn                 
	seq          uint32                      
	ack          uint32                      
	networkLayer gopacket.SerializableLayer  
	ts           time.Time                   
	buf          gopacket.SerializeBuffer    
	tcpHeader    layers.TCP
}
type TCPConn struct {
	die     chan struct{}
	dieOnce sync.Once
	tcpconn  *net.TCPConn      
	listener *net.TCPListener  
	handles []*net.IPConn
	chMessage chan message
	flowTable map[string]*tcpFlow
	flowsLock sync.Mutex
	iptables *iptables.IPTables
	iprule   []string
	ip6tables *iptables.IPTables
	ip6rule   []string
	readDeadline  atomic.Value
	writeDeadline atomic.Value
	opts gopacket.SerializeOptions
}
func (conn *TCPConn) lockflow(addr net.Addr, f func(e *tcpFlow)) {
	key := addr.String()
	conn.flowsLock.Lock()
	e := conn.flowTable[key]
	if e == nil {  
		e = new(tcpFlow)
		e.ts = time.Now()
		e.buf = gopacket.NewSerializeBuffer()
	}
	f(e)
	conn.flowTable[key] = e
	conn.flowsLock.Unlock()
}
func (conn *TCPConn) cleaner() {
	ticker := time.NewTicker(time.Minute)
	select {
	case <-conn.die:
		return
	case <-ticker.C:
		conn.flowsLock.Lock()
		for k, v := range conn.flowTable {
			if time.Now().Sub(v.ts) > expire {
				if v.conn != nil {
					setTTL(v.conn, 64)
					v.conn.Close()
				}
				delete(conn.flowTable, k)
			}
		}
		conn.flowsLock.Unlock()
	}
}