first commit
This commit is contained in:
commit
d787bce159
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
lagran
|
||||
.idea
|
||||
.DS_Store
|
||||
*.DS_Store
|
49
InitParams.go
Normal file
49
InitParams.go
Normal file
@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
)
|
||||
|
||||
var Port string
|
||||
var SaEnable bool
|
||||
var WindowSa uint16
|
||||
var AEnable bool
|
||||
var WindowA uint16
|
||||
var PaEnable bool
|
||||
var WindowPa uint16
|
||||
var FaEnable bool
|
||||
var WindowFa uint16
|
||||
var Debug bool
|
||||
var Daemon bool
|
||||
var Forever bool
|
||||
|
||||
func InitParams() (string, bool, uint16, bool, uint16, bool, uint16, bool, uint16, bool, bool, bool) {
|
||||
flag.StringVar(&Port, "p", "443", "The port of geneva, multi ports should be like \"80,443\"")
|
||||
|
||||
flag.BoolVar(&SaEnable, "sa", true, "Enable to handle the packet when TCP flag SYN and ACK are 1.")
|
||||
var wsa int
|
||||
flag.IntVar(&wsa, "wsa", 4, "The window size of packet when TCP flag SYN and ACK are 1, available only when param -sa is true")
|
||||
|
||||
flag.BoolVar(&AEnable, "a", true, "Enable to handle the packet when TCP flag ACK is 1")
|
||||
var wa int
|
||||
flag.IntVar(&wa, "wa", 4, "The window size of packet when TCP flag ACK is 1, available only when param -a is true")
|
||||
|
||||
flag.BoolVar(&PaEnable, "pa", true, "Enable to handle the packet when TCP flag PSH and ACK are 1.")
|
||||
var wpa int
|
||||
flag.IntVar(&wpa, "wpa", 4, "The window size of packet when TCP flag PSH and ACK are 1, available only when param -pa is true")
|
||||
|
||||
flag.BoolVar(&FaEnable, "fa", true, "Enable to handle the packet when TCP flag FIN and ACK are 1.")
|
||||
var wfa int
|
||||
flag.IntVar(&wfa, "wfa", 4, "The window size of packet when TCP flag FIN and ACK are 1, available only when param -fa is true")
|
||||
|
||||
flag.BoolVar(&Debug, "debug", false, "Debug mode.")
|
||||
flag.BoolVar(&Daemon, "daemon", false, "Run in daemon")
|
||||
flag.BoolVar(&Forever, "forever", false, "Run forever")
|
||||
|
||||
flag.Parse()
|
||||
WindowSa = uint16(wsa)
|
||||
WindowA = uint16(wa)
|
||||
WindowPa = uint16(wpa)
|
||||
WindowFa = uint16(wfa)
|
||||
return Port, SaEnable, WindowSa, AEnable, WindowA, PaEnable, WindowPa, FaEnable, WindowFa, Debug, Daemon, Forever
|
||||
}
|
11
README.md
Normal file
11
README.md
Normal file
@ -0,0 +1,11 @@
|
||||
- 本小程序主要用来实现Geneva的以下四条规则,还可以自定义端口、需要修改的window size的值。
|
||||
```
|
||||
"[TCP:flags:SA]-tamper{TCP:window:replace:0}-|"
|
||||
"[TCP:flags:A]-tamper{TCP:window:replace:0}-|"
|
||||
"[TCP:flags:PA]-tamper{TCP:window:replace:0}-|"
|
||||
"[TCP:flags:FA]-tamper{TCP:window:replace:0}-|"
|
||||
```
|
||||
- 默认四条规则全部开启,具体使用方法参考`./lagran -h`。
|
||||
- 例如:开启第一条规则并设置window为2,同时关闭2、3、4条规则
|
||||
```./lagran -debug -p 80 -sa=true -wsa 2 -a=false -pa=false -fa=false```
|
||||
- 注意:本小程序依赖libpcap-dev、libnetfilter-queue-dev、iptables等使用之前请先安装。
|
42
common.go
Normal file
42
common.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func getProcessOwner() string {
|
||||
stdout, err := exec.Command("ps", "-o", "user=", "-p", strconv.Itoa(os.Getpid())).Output()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
return string(stdout)
|
||||
}
|
||||
|
||||
func StripSlice(slice []string, element string) []string {
|
||||
for i := 0; i < len(slice); {
|
||||
if slice[i] == element && i != len(slice)-1 {
|
||||
slice = append(slice[:i], slice[i+1:]...)
|
||||
} else if slice[i] == element && i == len(slice)-1 {
|
||||
slice = slice[:i]
|
||||
} else {
|
||||
i++
|
||||
}
|
||||
}
|
||||
return slice
|
||||
}
|
||||
|
||||
func SubProcess(args []string) *exec.Cmd {
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "[-] Error: %s\n", err)
|
||||
}
|
||||
return cmd
|
||||
}
|
21
go.mod
Normal file
21
go.mod
Normal file
@ -0,0 +1,21 @@
|
||||
module lagran
|
||||
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/coreos/go-iptables v0.6.0
|
||||
github.com/florianl/go-nfqueue v1.3.1
|
||||
github.com/google/gopacket v1.1.19
|
||||
github.com/panjf2000/ants/v2 v2.5.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/google/go-cmp v0.5.7 // indirect
|
||||
github.com/josharian/native v1.0.0 // indirect
|
||||
github.com/mdlayher/netlink v1.6.0 // indirect
|
||||
github.com/mdlayher/socket v0.1.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 // indirect
|
||||
)
|
55
go.sum
Normal file
55
go.sum
Normal file
@ -0,0 +1,55 @@
|
||||
github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk=
|
||||
github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/florianl/go-nfqueue v1.3.1 h1:khQ9fYCrjbu5CF8dZF55G2RTIEIQRI0Aj5k3msJR6Gw=
|
||||
github.com/florianl/go-nfqueue v1.3.1/go.mod h1:aHWbgkhryJxF5XxYvJ3oRZpdD4JP74Zu/hP1zuhja+M=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||
github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk=
|
||||
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/mdlayher/netlink v1.6.0 h1:rOHX5yl7qnlpiVkFWoqccueppMtXzeziFjWAjLg6sz0=
|
||||
github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA=
|
||||
github.com/mdlayher/socket v0.1.1 h1:q3uOGirUPfAV2MUoaC7BavjQ154J7+JOkTWyiV+intI=
|
||||
github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs=
|
||||
github.com/panjf2000/ants/v2 v2.5.0 h1:1rWGWSnxCsQBga+nQbA4/iY6VMeNoOIAM0ZWh9u3q2Q=
|
||||
github.com/panjf2000/ants/v2 v2.5.0/go.mod h1:cU93usDlihJZ5CfRGNDYsiBYvoilLvBF5Qp/BT2GNRE=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 h1:XDXtA5hveEEV8JB2l7nhMTp3t3cHp9ZpwcdjqyEWLlo=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
30
iptables.go
Normal file
30
iptables.go
Normal file
@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/coreos/go-iptables/iptables"
|
||||
"os"
|
||||
)
|
||||
|
||||
func SetIptable(sport string) {
|
||||
ipt, err := iptables.New()
|
||||
if err != nil {
|
||||
fmt.Printf("Iptabels new error:%v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
_ = ipt.AppendUnique("filter", "OUTPUT", "-p", "tcp", "-m", "multiport", "--sport", sport, "--tcp-flags", "SYN,RST,ACK,FIN,PSH", "SYN,ACK", "-j", "NFQUEUE", "--queue-balance", "1000:1127")
|
||||
_ = ipt.AppendUnique("filter", "OUTPUT", "-p", "tcp", "-m", "multiport", "--sport", sport, "--tcp-flags", "SYN,RST,ACK,FIN,PSH", "ACK", "-j", "NFQUEUE", "--queue-balance", "2000:2127")
|
||||
_ = ipt.AppendUnique("filter", "OUTPUT", "-p", "tcp", "-m", "multiport", "--sport", sport, "--tcp-flags", "SYN,RST,ACK,FIN,PSH", "PSH,ACK", "-j", "NFQUEUE", "--queue-balance", "3000:3127")
|
||||
_ = ipt.AppendUnique("filter", "OUTPUT", "-p", "tcp", "-m", "multiport", "--sport", sport, "--tcp-flags", "SYN,RST,ACK,FIN,PSH", "FIN,ACK", "-j", "NFQUEUE", "--queue-balance", "4000:4127")
|
||||
}
|
||||
func UnsetIptable(sport string) {
|
||||
ipt, err := iptables.New()
|
||||
if err != nil {
|
||||
fmt.Printf("Iptabels new error:%v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
_ = ipt.Delete("filter", "OUTPUT", "-p", "tcp", "-m", "multiport", "--sport", sport, "--tcp-flags", "SYN,RST,ACK,FIN,PSH", "SYN,ACK", "-j", "NFQUEUE", "--queue-balance", "1000:1127")
|
||||
_ = ipt.Delete("filter", "OUTPUT", "-p", "tcp", "-m", "multiport", "--sport", sport, "--tcp-flags", "SYN,RST,ACK,FIN,PSH", "ACK", "-j", "NFQUEUE", "--queue-balance", "2000:2127")
|
||||
_ = ipt.Delete("filter", "OUTPUT", "-p", "tcp", "-m", "multiport", "--sport", sport, "--tcp-flags", "SYN,RST,ACK,FIN,PSH", "PSH,ACK", "-j", "NFQUEUE", "--queue-balance", "3000:3127")
|
||||
_ = ipt.Delete("filter", "OUTPUT", "-p", "tcp", "-m", "multiport", "--sport", sport, "--tcp-flags", "SYN,RST,ACK,FIN,PSH", "FIN,ACK", "-j", "NFQUEUE", "--queue-balance", "4000:4127")
|
||||
}
|
89
main.go
Normal file
89
main.go
Normal file
@ -0,0 +1,89 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/panjf2000/ants/v2"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
DAEMON = "daemon"
|
||||
FOREVER = "forever"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if getProcessOwner() != "root\n" {
|
||||
log.Fatalln("Please run this program with root.")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
InitParams()
|
||||
if !Debug {
|
||||
log.SetOutput(ioutil.Discard)
|
||||
}
|
||||
if Daemon {
|
||||
SubProcess(StripSlice(os.Args, "-"+DAEMON))
|
||||
fmt.Printf("[*] Daemon running in PID: %d PPID: %d\n", os.Getpid(), os.Getppid())
|
||||
os.Exit(0)
|
||||
} else if Forever {
|
||||
for {
|
||||
cmd := SubProcess(StripSlice(os.Args, "-"+FOREVER))
|
||||
fmt.Printf("[*] Forever running in PID: %d PPID: %d\n", os.Getpid(), os.Getppid())
|
||||
cmd.Wait()
|
||||
}
|
||||
os.Exit(0)
|
||||
} else {
|
||||
UnsetIptable(Port)
|
||||
SetIptable(Port)
|
||||
var wg sync.WaitGroup
|
||||
p1, _ := ants.NewPoolWithFunc(512, func(i interface{}) {
|
||||
packetHandle(i.(int))
|
||||
wg.Done()
|
||||
})
|
||||
defer p1.Release()
|
||||
// Submit tasks one by one.
|
||||
log.Println("Starting Task p1")
|
||||
for i := 1000; i < 1512; i++ {
|
||||
wg.Add(1)
|
||||
_ = p1.Invoke(int(i))
|
||||
}
|
||||
p2, _ := ants.NewPoolWithFunc(1512, func(i interface{}) {
|
||||
packetHandle(i.(int))
|
||||
wg.Done()
|
||||
})
|
||||
defer p2.Release()
|
||||
// Submit tasks one by one.
|
||||
log.Println("Starting Task p2")
|
||||
for i := 2000; i < 2512; i++ {
|
||||
wg.Add(1)
|
||||
_ = p2.Invoke(int(i))
|
||||
}
|
||||
p3, _ := ants.NewPoolWithFunc(512, func(i interface{}) {
|
||||
packetHandle(i.(int))
|
||||
wg.Done()
|
||||
})
|
||||
defer p3.Release()
|
||||
// Submit tasks one by one.
|
||||
log.Println("Starting Task p3")
|
||||
for i := 3000; i < 3512; i++ {
|
||||
wg.Add(1)
|
||||
_ = p3.Invoke(int(i))
|
||||
}
|
||||
p4, _ := ants.NewPoolWithFunc(512, func(i interface{}) {
|
||||
packetHandle(i.(int))
|
||||
wg.Done()
|
||||
})
|
||||
defer p4.Release()
|
||||
// Submit tasks one by one.
|
||||
log.Println("Starting Task p4")
|
||||
for i := 4000; i < 4512; i++ {
|
||||
wg.Add(1)
|
||||
_ = p4.Invoke(int(i))
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
}
|
140
packet.go
Normal file
140
packet.go
Normal file
@ -0,0 +1,140 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/florianl/go-nfqueue"
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"log"
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func packetHandle(queueNum int) {
|
||||
config := nfqueue.Config{
|
||||
NfQueue: uint16(queueNum),
|
||||
MaxPacketLen: 0xFFFF,
|
||||
MaxQueueLen: 0xFF,
|
||||
Copymode: nfqueue.NfQnlCopyPacket,
|
||||
WriteTimeout: 200 * time.Millisecond,
|
||||
}
|
||||
|
||||
nf, err := nfqueue.Open(&config)
|
||||
if err != nil {
|
||||
fmt.Println("could not open nfqueue socket:", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer nf.Close()
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
||||
fn := func(a nfqueue.Attribute) int {
|
||||
id := *a.PacketID
|
||||
var srcIP net.IP
|
||||
var dstIP net.IP
|
||||
log.Printf("PKT[%03d]\t\n", id)
|
||||
|
||||
packet := gopacket.NewPacket(*a.Payload, layers.LayerTypeIPv4, gopacket.Default)
|
||||
|
||||
// Get the IP layer from this packet
|
||||
if ipLayer := packet.Layer(layers.LayerTypeIPv4); ipLayer != nil {
|
||||
// Get actual IP data from this layer
|
||||
ip, _ := ipLayer.(*layers.IPv4)
|
||||
srcIP = ip.SrcIP
|
||||
dstIP = ip.DstIP
|
||||
log.Printf("%15s > %-15s \n", srcIP, dstIP)
|
||||
}
|
||||
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
|
||||
tcp, _ := tcpLayer.(*layers.TCP)
|
||||
ports := strings.Split(Port, ",")
|
||||
reg := regexp.MustCompile(`\d+`)
|
||||
sport := reg.FindString(tcp.SrcPort.String())
|
||||
var matchedPort bool = false
|
||||
|
||||
for _, port := range ports {
|
||||
if port == sport {
|
||||
matchedPort = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if matchedPort {
|
||||
var ok1 bool = SaEnable && tcp.SYN && tcp.ACK
|
||||
var ok2 bool = AEnable && tcp.ACK && !tcp.PSH && !tcp.FIN && !tcp.SYN && !tcp.RST
|
||||
var ok3 bool = PaEnable && tcp.PSH && tcp.ACK
|
||||
var ok4 bool = FaEnable && tcp.FIN && tcp.ACK
|
||||
var windowSize uint16
|
||||
if ok1 || ok2 || ok3 || ok4 {
|
||||
if ok1 {
|
||||
windowSize = WindowSa
|
||||
log.Println("Handle SYN=1 and ACK=1")
|
||||
}
|
||||
if ok2 {
|
||||
windowSize = WindowA
|
||||
log.Println("Handle ACK=1")
|
||||
}
|
||||
if ok3 {
|
||||
windowSize = WindowPa
|
||||
log.Println("Handle PSH=1 and ACK=1")
|
||||
}
|
||||
if ok4 {
|
||||
windowSize = WindowFa
|
||||
log.Println("Handle FIN=1 and ACK=1")
|
||||
}
|
||||
packet.TransportLayer().(*layers.TCP).Window = windowSize
|
||||
err := packet.TransportLayer().(*layers.TCP).SetNetworkLayerForChecksum(packet.NetworkLayer())
|
||||
if err != nil {
|
||||
log.Fatalf("SetNetworkLayerForChecksum error: %v", err)
|
||||
}
|
||||
buffer := gopacket.NewSerializeBuffer()
|
||||
options := gopacket.SerializeOptions{
|
||||
ComputeChecksums: true,
|
||||
FixLengths: true,
|
||||
}
|
||||
if err := gopacket.SerializePacket(buffer, options, packet); err != nil {
|
||||
log.Fatalf("SerializePacket error: %v", err)
|
||||
}
|
||||
packetBytes := buffer.Bytes()
|
||||
log.Printf("Set TCP window size to %d", windowSize)
|
||||
err = nf.SetVerdictModPacket(id, nfqueue.NfAccept, packetBytes)
|
||||
if err != nil {
|
||||
log.Fatalf("SetVerdictModified error: %v", err)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
err := nf.SetVerdict(id, nfqueue.NfAccept)
|
||||
if err != nil {
|
||||
log.Fatalf("SetVerdictModified error: %v", err)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
err := nf.SetVerdict(id, nfqueue.NfAccept)
|
||||
if err != nil {
|
||||
log.Fatalf("SetVerdictModified error: %v", err)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
err := nf.SetVerdict(id, nfqueue.NfAccept)
|
||||
if err != nil {
|
||||
log.Fatalf("SetVerdictModified error: %v", err)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Register your function to listen on nflqueue queue 100
|
||||
err = nf.RegisterWithErrorFunc(ctx, fn, func(e error) int {
|
||||
if e != nil {
|
||||
log.Fatalln("RegisterWithErrorFunc Error:", e)
|
||||
}
|
||||
return 0
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
<-ctx.Done()
|
||||
}
|
Loading…
Reference in New Issue
Block a user