From 097e53a63dec093f34d223c57a81b9ac1aee802c Mon Sep 17 00:00:00 2001 From: yuhui06 Date: Sun, 7 Nov 2021 18:07:44 +0800 Subject: [PATCH 01/33] add mod_tcp_keepalive Signed-off-by: yuhui06 --- bfe_modules/bfe_modules.go | 4 + bfe_modules/mod_tcp_keepalive/conf_load.go | 59 ++++ .../mod_tcp_keepalive/conf_load_test.go | 47 +++ bfe_modules/mod_tcp_keepalive/data_load.go | 208 +++++++++++++ .../mod_tcp_keepalive/data_load_test.go | 83 ++++++ .../mod_tcp_keepalive/keepalive_drawin.go | 24 ++ .../mod_tcp_keepalive/keepalive_linux.go | 18 ++ .../mod_tcp_keepalive/keepalive_table.go | 44 +++ .../mod_tcp_keepalive/keepalive_table_test.go | 37 +++ .../mod_tcp_keepalive/mod_tcp_keepalive.go | 279 ++++++++++++++++++ .../mod_tcp_keepalive_test.go | 91 ++++++ .../testdata/mod_tcp_keepalive.conf | 5 + .../mod_tcp_keepalive/mod_tcp_keepalive.conf | 5 + .../mod_tcp_keepalive/tcp_keepalive.data | 14 + .../testdata/mod_tcp_keepalive_2.conf | 1 + .../testdata/tcp_keepalive.data | 30 ++ .../testdata/tcp_keepalive_2.data | 6 + .../testdata/tcp_keepalive_3.data | 14 + conf/mod_tcp_keepalive/mod_tcp_keepalive.conf | 5 + 19 files changed, 974 insertions(+) create mode 100644 bfe_modules/mod_tcp_keepalive/conf_load.go create mode 100644 bfe_modules/mod_tcp_keepalive/conf_load_test.go create mode 100644 bfe_modules/mod_tcp_keepalive/data_load.go create mode 100644 bfe_modules/mod_tcp_keepalive/data_load_test.go create mode 100644 bfe_modules/mod_tcp_keepalive/keepalive_drawin.go create mode 100644 bfe_modules/mod_tcp_keepalive/keepalive_linux.go create mode 100644 bfe_modules/mod_tcp_keepalive/keepalive_table.go create mode 100644 bfe_modules/mod_tcp_keepalive/keepalive_table_test.go create mode 100644 bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive.go create mode 100644 bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive_test.go create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive.conf create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/mod_tcp_keepalive.conf create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/tcp_keepalive.data create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive_2.conf create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive.data create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_2.data create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_3.data create mode 100644 conf/mod_tcp_keepalive/mod_tcp_keepalive.conf diff --git a/bfe_modules/bfe_modules.go b/bfe_modules/bfe_modules.go index 6135fc7a6..326a9830a 100644 --- a/bfe_modules/bfe_modules.go +++ b/bfe_modules/bfe_modules.go @@ -39,6 +39,7 @@ import ( "github.com/bfenetworks/bfe/bfe_modules/mod_secure_link" "github.com/bfenetworks/bfe/bfe_modules/mod_static" "github.com/bfenetworks/bfe/bfe_modules/mod_tag" + "github.com/bfenetworks/bfe/bfe_modules/mod_tcp_keepalive" "github.com/bfenetworks/bfe/bfe_modules/mod_trace" "github.com/bfenetworks/bfe/bfe_modules/mod_trust_clientip" "github.com/bfenetworks/bfe/bfe_modules/mod_userid" @@ -54,6 +55,9 @@ var moduleList = []bfe_module.BfeModule{ // Requirement: After mod_trust_clientip mod_logid.NewModuleLogId(), + // mod_tcp_keepalive + mod_tcp_keepalive.NewModuleTcpKeepAlive(), + // mode_userid mod_userid.NewModuleUserID(), diff --git a/bfe_modules/mod_tcp_keepalive/conf_load.go b/bfe_modules/mod_tcp_keepalive/conf_load.go new file mode 100644 index 000000000..1f66f968b --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/conf_load.go @@ -0,0 +1,59 @@ +/* conf_mod_tcp_keepalive.go - config for mod_tcp_keepalive */ +/* +modification history +-------------------- +2021/9/8, by Yu Hui, create +*/ +/* +DESCRIPTION +*/ + +package mod_tcp_keepalive + +import ( + "github.com/baidu/go-lib/log" + "github.com/bfenetworks/bfe/bfe_util" + gcfg "gopkg.in/gcfg.v1" +) + +type ConfModTcpKeepAlive struct { + Basic struct { + DataPath string // path of product keepalive rule data + } + + Log struct { + OpenDebug bool // whether open debug + } +} + +func ConfLoad(filePath string, confRoot string) (*ConfModTcpKeepAlive, error) { + var cfg ConfModTcpKeepAlive + var err error + + err = gcfg.ReadFileInto(&cfg, filePath) + if err != nil { + return &cfg, err + } + + // check conf of mod_tcp_keepalive + err = cfg.Check(confRoot) + if err != nil { + return &cfg, err + } + + return &cfg, nil +} + +func (cfg *ConfModTcpKeepAlive) Check(confRoot string) error { + return ConfModTcpKeepAliveCheck(cfg, confRoot) +} + +func ConfModTcpKeepAliveCheck(cfg *ConfModTcpKeepAlive, confRoot string) error { + if cfg.Basic.DataPath == "" { + log.Logger.Warn("ModTcpKeepAlive.DataPath not set, use default value") + cfg.Basic.DataPath = "mod_tcp_keepalive/tcp_keepalive.data" + } + cfg.Basic.DataPath = bfe_util.ConfPathProc(cfg.Basic.DataPath, confRoot) + + return nil +} diff --git a/bfe_modules/mod_tcp_keepalive/conf_load_test.go b/bfe_modules/mod_tcp_keepalive/conf_load_test.go new file mode 100644 index 000000000..3768f8b49 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/conf_load_test.go @@ -0,0 +1,47 @@ +/* conf_mod_tcp_keepalive_test.go - test for conf_mod_tcp_keepalive.go */ +/* +modification history +-------------------- +2021/9/8, by Yu Hui, create +*/ +/* +DESCRIPTION +*/ + +package mod_tcp_keepalive + +import ( + "testing" +) + +func TestConfModTcpKeepAlive_1(t *testing.T) { + config, err := ConfLoad("./testdata/mod_tcp_keepalive.conf", "") + if err != nil { + t.Errorf("TcpKeepAlive ConfLoad() error: %s", err.Error()) + return + } + + if config.Basic.DataPath != "../data/mod_tcp_keepalive/tcp_keepalive.data" { + t.Error("DataPath should be ../data/mod_tcp_keepalive/tcp_keepalive.data") + return + } + + if config.Log.OpenDebug != true { + t.Error("Log.OpenDebug shoule be true") + return + } +} + +func TestConfModTcpKeepAlive_2(t *testing.T) { + // invalid value + config, err := ConfLoad("./testdata/mod_tcp_keepalive_2.conf", "") + if err != nil { + t.Errorf("CondLoad() error: %s", err.Error()) + } + + // use default value + if config.Basic.DataPath != "mod_tcp_keepalive/tcp_keepalive.data" { + t.Error("DataPath shoule be mod_tcp_keepalive/tcp_keepalive.data") + return + } +} diff --git a/bfe_modules/mod_tcp_keepalive/data_load.go b/bfe_modules/mod_tcp_keepalive/data_load.go new file mode 100644 index 000000000..b386ceb22 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/data_load.go @@ -0,0 +1,208 @@ +/* data_load.go - load tcp keepalive config from json file */ +/* +modification history +-------------------- +2021/9/7, by Yu Hui, create +*/ +/* +DESCRIPTION +*/ + +package mod_tcp_keepalive + +import ( + "encoding/json" + "errors" + "fmt" + "net" + "os" +) + +/* +{ + "Version": "x", + "Config": { + "Product1": [{ + "VipConf": ["1.1.1.1", "1.1.1.2"], + "KeepAliveParam": { + "Disable": false, + "KeepIdle" : 70, + "KeepIntvl" : 15, + "KeepCnt": 9 + } + }] + } +} +*/ +// ProductRuleConf match the original tcp_keepalive.data +type ProductRuleConf struct { + Version string + Config map[string]ProductRulesFile +} + +type ProductRulesFile []ProductRuleFile +type ProductRuleFile struct { + VipConf []string + KeepAliveParam KeepAliveParam +} + +/* +{ + "Version": "x", + "Config": { + "Product1": { + "1.1.1.1": { + "Disable": false, + "KeepIdle" : 70, + "KeepIntvl" : 15, + "KeepCnt": 9 + }, + "1.1.1.2": { + "Disable": false, + "KeepIdle" : 70, + "KeepIntvl" : 15, + "KeepCnt": 9 + } + } + } +} +*/ +// ProductRuleData contains data convert from ProductRuleConf +type ProductRuleData struct { + Version string + Config ProductRules +} + +type KeepAliveParam struct { + Disable bool + KeepIdle int + KeepIntvl int + KeepCnt int +} +type KeepAliveRules map[string]KeepAliveParam +type ProductRules map[string]KeepAliveRules + +func ConvertConf(c ProductRuleConf) (ProductRuleData, error) { + data := ProductRuleData{} + data.Version = c.Version + data.Config = ProductRules{} + + for product, rules := range c.Config { + data.Config[product] = KeepAliveRules{} + for _, rule := range rules { + for _, val := range rule.VipConf { + ip, err := formatIP(val) + if err != nil { + return data, err + } + if _, ok := data.Config[product][ip]; ok { + return data, fmt.Errorf("duplicated ip[%s] in product[%s]", val, product) + } + data.Config[product][ip] = rule.KeepAliveParam + } + } + } + + return data, nil +} + +func RulesCheck(conf KeepAliveRules) error { + for ip, val := range conf { + if net.ParseIP(ip) == nil { + return fmt.Errorf("invalid ip: %s", ip) + } + + if val.KeepIdle < 0 || val.KeepIntvl < 0 || val.KeepCnt < 0 { + return fmt.Errorf("invalid keepalive param: %+v", val) + } + } + + return nil +} + +func ProductRulesCheck(conf ProductRules) error { + for product, rules := range conf { + if product == "" { + return fmt.Errorf("no product name") + } + if rules == nil { + return fmt.Errorf("no rules for product: %s", product) + } + + err := RulesCheck(rules) + if err != nil { + return fmt.Errorf("ProductRules:%s, %s", product, err.Error()) + } + } + + return nil +} + +func ProductRuleDataCheck(conf ProductRuleData) error { + var err error + + // check Version + if conf.Version == "" { + return errors.New("no Version") + } + + // check Config + if conf.Config == nil { + return errors.New("no Config") + } + + err = ProductRulesCheck(conf.Config) + if err != nil { + return fmt.Errorf("Config: %s", err.Error()) + } + + return nil +} + +func formatIP(s string) (string, error) { + ip := net.ParseIP(s) + if ip == nil { + return "", fmt.Errorf("formatIP: net.ParseIP() error, ip: %s", s) + } + + ret := ip.String() + if ret == "" { + return "", fmt.Errorf("formatIP: ip.String() error, ip: %s", s) + } + + return ret, nil +} + +func KeepAliveDataLoad(filename string) (ProductRuleData, error) { + var err error + var conf ProductRuleConf + var data ProductRuleData + + // open the file + file, err := os.Open(filename) + defer file.Close() + if err != nil { + return data, err + } + + // decode the file + decoder := json.NewDecoder(file) + err = decoder.Decode(&conf) + if err != nil { + return data, err + } + + // convert to ProductRuleData + data, err = ConvertConf(conf) + if err != nil { + return data, err + } + + // check data + err = ProductRuleDataCheck(data) + if err != nil { + return data, err + } + + return data, nil +} diff --git a/bfe_modules/mod_tcp_keepalive/data_load_test.go b/bfe_modules/mod_tcp_keepalive/data_load_test.go new file mode 100644 index 000000000..b49603393 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/data_load_test.go @@ -0,0 +1,83 @@ +/* data_load_test.go - test for data_load.go */ +/* +modification history +-------------------- +2021/9/8, by Yu Hui, create +*/ +/* +DESCRIPTION +*/ + +package mod_tcp_keepalive + +import ( + "testing" +) + +func TestKeepAliveDataLoad_1(t *testing.T) { + data, err := KeepAliveDataLoad("./testdata/tcp_keepalive.data") + if err != nil { + t.Errorf("get err from ProductRuleConfLoad(): %s", err.Error()) + return + } + + if len(data.Config) != 2 { + t.Errorf("len(config.Config) should be 2, but is %d", len(data.Config)) + return + } + + if len(data.Config["product1"]) != 3 { + t.Errorf("len(data.Config[product1]) shoule be 3, but is %d", len(data.Config["product1"])) + return + } +} + +// invalid format of data +func TestKeepAliveDataLoad_2(t *testing.T) { + _, err := KeepAliveDataLoad("./testdata/tcp_keepalive_2.data") + if err == nil { + t.Error("err should not be nil") + return + } +} + +// invalid format of ip +func TestKeepAliveDataLoad_3(t *testing.T) { + _, err := KeepAliveDataLoad("./testdata/tcp_keepalive_3.data") + if err == nil { + t.Errorf("err should not be nil: %v", err) + return + } +} + +func TestFormatIP(t *testing.T) { + ret1, _ := formatIP("2001:0db8:02de:0000:0000:0000:0000:0e13") + ret2, _ := formatIP("2001:db8:2de:000:000:000:000:e13") + ret3, _ := formatIP("2001:db8:2de:0:0:0:0:e13") + expect1 := "2001:db8:2de::e13" + + if ret1 != expect1 || ret2 != expect1 || ret3 != expect1 { + t.Errorf("ret should equal to %s", expect1) + return + } + + ret5, _ := formatIP("2001:db8:2de:0:0:0:0:e13") + ret6, _ := formatIP("2001:db8:2de::e13") + expect2 := "2001:db8:2de::e13" + if ret5 != expect2 || ret6 != expect2 { + t.Errorf("ret should equal to %s", expect2) + return + } + + _, err := formatIP("2001::25de::cade") + if err == nil { + t.Error("err should not be nil, 2001::25de::cade is invalid ip") + return + } + + _, err = formatIP("127.1") + if err == nil { + t.Error("err should not be nil, 127.1 is invalid ip") + return + } +} diff --git a/bfe_modules/mod_tcp_keepalive/keepalive_drawin.go b/bfe_modules/mod_tcp_keepalive/keepalive_drawin.go new file mode 100644 index 000000000..80f66b469 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/keepalive_drawin.go @@ -0,0 +1,24 @@ +package mod_tcp_keepalive + +import ( + "os" + "syscall" +) + +// from netinet/tcp.h (OS X 10.9.4) +const ( + _TCP_KEEPINTVL = 0x101 /* interval between keepalives */ + _TCP_KEEPCNT = 0x102 /* number of keepalives before close */ +) + +func setIdle(fd int, secs int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs)) +} + +func setCount(fd int, n int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, _TCP_KEEPCNT, n)) +} + +func setInterval(fd int, secs int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, _TCP_KEEPINTVL, secs)) +} diff --git a/bfe_modules/mod_tcp_keepalive/keepalive_linux.go b/bfe_modules/mod_tcp_keepalive/keepalive_linux.go new file mode 100644 index 000000000..0e9fe7c24 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/keepalive_linux.go @@ -0,0 +1,18 @@ +package mod_tcp_keepalive + +import ( + "os" + "syscall" +) + +func setIdle(fd int, secs int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs)) +} + +func setCount(fd int, n int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPCNT, n)) +} + +func setInterval(fd int, secs int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs)) +} diff --git a/bfe_modules/mod_tcp_keepalive/keepalive_table.go b/bfe_modules/mod_tcp_keepalive/keepalive_table.go new file mode 100644 index 000000000..3cf76b7a9 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/keepalive_table.go @@ -0,0 +1,44 @@ +/* product_rule_table.go - table for storing product tcp keepalive rules */ +/* +modification history +-------------------- +2021/9/7, by Yu Hui, create +*/ +/* +DESCRIPTION +*/ + +package mod_tcp_keepalive + +import ( + "sync" +) + +type KeepAliveTable struct { + lock sync.RWMutex + version string + productRules ProductRules +} + +func NewKeepAliveTable() *KeepAliveTable { + t := new(KeepAliveTable) + t.productRules = make(ProductRules) + + return t +} + +func (t *KeepAliveTable) Update(data ProductRuleData) { + t.lock.Lock() + t.version = data.Version + t.productRules = data.Config + t.lock.Unlock() +} + +func (t *KeepAliveTable) Search(product string) (KeepAliveRules, bool) { + t.lock.RLock() + productRules := t.productRules + t.lock.RUnlock() + + rules, ok := productRules[product] + return rules, ok +} diff --git a/bfe_modules/mod_tcp_keepalive/keepalive_table_test.go b/bfe_modules/mod_tcp_keepalive/keepalive_table_test.go new file mode 100644 index 000000000..e6721daaf --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/keepalive_table_test.go @@ -0,0 +1,37 @@ +/* keepalive_table_test.go - test for keepalive_table.go */ +/* +modification history +-------------------- +2021/9/7, by Yu Hui, create +*/ +/* +DESCRIPTION +*/ + +package mod_tcp_keepalive + +import ( + "testing" +) + +func TestKeepAliveTable(t *testing.T) { + table := NewKeepAliveTable() + path := "./testdata/tcp_keepalive.data" + data, err := KeepAliveDataLoad(path) + if err != nil { + t.Errorf("KeepAliveDataLoad(%s) error: %v", path, err) + return + } + + table.Update(data) + if len(table.productRules) != 2 { + t.Errorf("table.Update error: rules length should be 2 but %d", len(table.productRules)) + return + } + + _, ok := table.Search("product1") + if !ok { + t.Errorf("table.Search error: product1 should exist") + return + } +} diff --git a/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive.go b/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive.go new file mode 100644 index 000000000..c4c2b7e24 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive.go @@ -0,0 +1,279 @@ +/* mod_tcp_keepalive.go - module for setting tcp keepalive period */ +/* +modification history +-------------------- +2021/9/7, by Yu Hui, create +*/ +/* +DESCRIPTION +*/ + +package mod_tcp_keepalive + +import ( + "fmt" + "net" + "net/url" + "os" + "reflect" + "syscall" + + "github.com/baidu/go-lib/log" + "github.com/baidu/go-lib/web-monitor/metrics" + "github.com/baidu/go-lib/web-monitor/web_monitor" + "github.com/bfenetworks/bfe/bfe_basic" + "github.com/bfenetworks/bfe/bfe_module" + "github.com/bfenetworks/bfe/bfe_util" +) + +const ( + ModTcpKeepAlive = "mod_tcp_keepalive" +) + +var ( + openDebug = false +) + +type ModuleTcpKeepAliveState struct { + ConnToSet *metrics.Counter // connection hit rule, to set or disable keeplaive + ConnSetKeepIdle *metrics.Counter // connection set keepalive idle + ConnSetKeepIdleError *metrics.Counter // connection set keepalive idle error + ConnSetKeepIntvl *metrics.Counter // connection set keepalive interval + ConnSetKeepIntvlError *metrics.Counter // connection set keepalive interval error + ConnSetKeepCnt *metrics.Counter // connection set keepalive retry count + ConnSetKeepCntError *metrics.Counter // connection set keepalive retry count error + ConnDisableKeepAlive *metrics.Counter // connection disable keepalive message + ConnDisableKeepAliveError *metrics.Counter // connection disable keepalive error + ConnConvertToTcpConnError *metrics.Counter // connection convert to TCPConn error +} + +type ModuleTcpKeepAlive struct { + name string // name of module + + state ModuleTcpKeepAliveState // module state + metrics metrics.Metrics // module metrics + + dataPath string // path of module data file + ruleTable *KeepAliveTable // table of keepalive rules +} + +func NewModuleTcpKeepAlive() *ModuleTcpKeepAlive { + m := new(ModuleTcpKeepAlive) + m.name = ModTcpKeepAlive + m.metrics.Init(&m.state, ModTcpKeepAlive, 0) + m.ruleTable = NewKeepAliveTable() + + return m +} + +func (m *ModuleTcpKeepAlive) Name() string { + return m.name +} + +func (m *ModuleTcpKeepAlive) Init(cbs *bfe_module.BfeCallbacks, whs *web_monitor.WebHandlers, cr string) error { + var conf *ConfModTcpKeepAlive + var err error + + // load module config + confPath := bfe_module.ModConfPath(cr, m.name) + if conf, err = ConfLoad(confPath, cr); err != nil { + return fmt.Errorf("%s: conf load err %s", m.name, err.Error()) + } + + m.dataPath = conf.Basic.DataPath + openDebug = conf.Log.OpenDebug + + // load conf data + if err = m.loadConfData(nil); err != nil { + return fmt.Errorf("%s: loadConfData() err %s", m.name, err.Error()) + } + + // register handler + err = cbs.AddFilter(bfe_module.HandleAccept, m.HandleAccept) + if err != nil { + return fmt.Errorf("%s.Init(): AddFilter(m.HandleAccept): %s", m.name, err.Error()) + } + + // register web handler for monitor + err = web_monitor.RegisterHandlers(whs, web_monitor.WebHandleMonitor, m.monitorHandlers()) + if err != nil { + return fmt.Errorf("%s.Init(): RegisterHandlers(m.monitorHandlers): %s", m.name, err.Error()) + } + + // register web handler for reload + err = web_monitor.RegisterHandlers(whs, web_monitor.WebHandleReload, m.reloadHandlers()) + if err != nil { + return fmt.Errorf("%s.Init(): RegisterHandlers(m.reloadHandlers): %s", m.name, err.Error()) + } + + return nil +} + +func (m *ModuleTcpKeepAlive) loadConfData(query url.Values) error { + path := query.Get("path") + if path == "" { + // use default + path = m.dataPath + } + + // load file + data, err := KeepAliveDataLoad(path) + if err != nil { + return fmt.Errorf("err in KeepAliveDataLoad(%s): %s", path, err.Error()) + } + + m.ruleTable.Update(data) + + return nil +} + +func (m *ModuleTcpKeepAlive) disableKeepAlive(tcpConn *net.TCPConn) error { + err := tcpConn.SetKeepAlive(false) + if err != nil { + m.state.ConnDisableKeepAliveError.Inc(1) + return fmt.Errorf("SetKeepAlive(false) failed: %v", err) + } + + m.state.ConnDisableKeepAlive.Inc(1) + return nil +} + +func setNonblock(fd int) error { + return os.NewSyscallError("setsockopt", syscall.SetNonblock(fd, true)) +} + +func (m *ModuleTcpKeepAlive) setKeepAliveParam(conn *net.TCPConn, p KeepAliveParam) error { + var err error + var f *os.File + + if f, err = conn.File(); err != nil { + return fmt.Errorf("get conn.File() error: %v", err) + } + defer f.Close() + fd := int(f.Fd()) + + if p.KeepIdle > 0 { + err = setIdle(fd, p.KeepIdle) + if err != nil { + m.state.ConnSetKeepIdleError.Inc(1) + return fmt.Errorf("set tcp keepIdle error: %v", err) + } + m.state.ConnSetKeepIdle.Inc(1) + } + + if p.KeepIntvl > 0 { + err = setInterval(fd, p.KeepIntvl) + if err != nil { + m.state.ConnSetKeepIntvlError.Inc(1) + return fmt.Errorf("set tcp keepIntvl error: %v", err) + } + m.state.ConnSetKeepIntvl.Inc(1) + } + + if p.KeepCnt > 0 { + err = setCount(fd, p.KeepCnt) + if err != nil { + m.state.ConnSetKeepCntError.Inc(1) + return fmt.Errorf("set tcp KeepCnt error: %v", err) + } + m.state.ConnSetKeepCnt.Inc(1) + } + + err = setNonblock(fd) + if err != nil { + return fmt.Errorf("setNonblock error: %v", err) + } + + return err +} + +func (m *ModuleTcpKeepAlive) handleTcpKeepAlive(conn *net.TCPConn, p KeepAliveParam) error { + if p.Disable { + return m.disableKeepAlive(conn) + } + + return m.setKeepAliveParam(conn, p) +} + +func (m *ModuleTcpKeepAlive) getTcpConn(conn net.Conn) (*net.TCPConn, error) { + if c, ok := conn.(bfe_util.ConnFetcher); ok { + conn = c.GetNetConn() + return m.getTcpConn(conn) + } + + tcpConn, ok := conn.(*net.TCPConn) + if !ok { + m.state.ConnConvertToTcpConnError.Inc(1) + if openDebug { + log.Logger.Debug("conn type[%s] connvert to TCPConn failed", reflect.TypeOf(conn)) + } + + return nil, fmt.Errorf("conn connvert to TCPConn failed") + } + + return tcpConn, nil +} + +func (m *ModuleTcpKeepAlive) HandleAccept(session *bfe_basic.Session) int { + vip := session.Vip.String() + if openDebug { + log.Logger.Debug("mod[%s] get connection, remote: %v, vip: %s", m.name, session.RemoteAddr, vip) + } + + rules, ok := m.ruleTable.Search(session.Product) + if !ok { + if openDebug { + log.Logger.Debug("mod[%s] product[%s] not found, just pass", m.name, session.Product) + } + return bfe_module.BfeHandlerGoOn + } + + if param, ok := rules[vip]; ok { + m.state.ConnToSet.Inc(1) + conn, err := m.getTcpConn(session.Connection) + if err != nil { + log.Logger.Error("mod[%s] vip[%s] getTcpConn error: %v", err) + return bfe_module.BfeHandlerGoOn + } + + err = m.handleTcpKeepAlive(conn, param) + if err != nil { + log.Logger.Error("mod[%s] vip[%s] remote[%v] handleTcpKeepAlive error: %v", m.name, vip, session.RemoteAddr, err) + } + + if openDebug { + log.Logger.Debug("mod[%s] vip[%s] product[%s] found, set keepalive success, param[%+v]", m.name, vip, session.Product, param) + } + + return bfe_module.BfeHandlerGoOn + } + + return bfe_module.BfeHandlerGoOn +} + +func (m *ModuleTcpKeepAlive) getState(params map[string][]string) ([]byte, error) { + s := m.metrics.GetAll() + return s.Format(params) +} + +func (m *ModuleTcpKeepAlive) getStateDiff(params map[string][]string) ([]byte, error) { + s := m.metrics.GetDiff() + return s.Format(params) +} + +func (m *ModuleTcpKeepAlive) monitorHandlers() map[string]interface{} { + handlers := map[string]interface{}{ + m.name: m.getState, + m.name + ".diff": m.getStateDiff, + } + + return handlers +} + +func (m *ModuleTcpKeepAlive) reloadHandlers() map[string]interface{} { + handlers := map[string]interface{}{ + m.name: m.loadConfData, + } + + return handlers +} diff --git a/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive_test.go b/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive_test.go new file mode 100644 index 000000000..d4d9d4af2 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive_test.go @@ -0,0 +1,91 @@ +/* mod_tcp_keepalive_test.go - test for mod_tcp_keepalive.go */ +/* +modification history +-------------------- +2021/9/16, by Yu Hui, create +*/ +/* +DESCRIPTION +*/ + +package mod_tcp_keepalive + +import ( + "net" + "testing" +) + +import ( + "github.com/baidu/go-lib/web-monitor/web_monitor" +) + +import ( + "github.com/bfenetworks/bfe/bfe_basic" + "github.com/bfenetworks/bfe/bfe_http" + "github.com/bfenetworks/bfe/bfe_module" +) + +func prepareModule() (*ModuleTcpKeepAlive, error) { + m := NewModuleTcpKeepAlive() + err := m.Init(bfe_module.NewBfeCallbacks(), web_monitor.NewWebHandlers(), "./testdata") + return m, err +} + +func prepareRequest() *bfe_basic.Request { + request := new(bfe_basic.Request) + request.HttpRequest = new(bfe_http.Request) + request.Session = new(bfe_basic.Session) + request.Context = make(map[interface{}]interface{}) + return request +} + +func TestSetKeepAlive(t *testing.T) { + m, err := prepareModule() + if err != nil { + t.Errorf("prepareModule() error: %v", err) + return + } + s := new(bfe_basic.Session) + ip := "180.97.93.196" + address := "180.97.93.196:80" + + s.Product = "product1" + s.Vip = net.ParseIP(ip) + if s.Vip == nil { + t.Errorf("net.ParseIP(%s) == nil", ip) + } + + conn, err := net.Dial("tcp", address) + if err != nil { + t.Errorf("net.Dial(tcp, %s) error: %v", address, err) + return + } + s.Connection = conn + + m.HandleAccept(s) + metrics := m.metrics.GetAll() + if metrics.CounterData["CONN_TO_SET"] != 1 || + metrics.CounterData["CONN_SET_KEEP_IDLE"] != 1 || + metrics.CounterData["CONN_SET_KEEP_INTVL"] != 1 { + + t.Errorf("CONN_TO_SET and CONN_SET_KEEP_IDLE and CONN_SET_KEEP_INTVL should be 1") + return + } +} + +func TestModuleMisc(t *testing.T) { + m, err := prepareModule() + if err != nil { + t.Errorf("prepareModule() error: %v", err) + return + } + if s, _ := m.getState(nil); s == nil { + t.Errorf("Should return valid state") + } + if m.monitorHandlers() == nil { + t.Errorf("Should return valid monitor handlers") + } + if m.reloadHandlers() == nil { + t.Errorf("Should return valid reload handlers") + } +} diff --git a/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive.conf b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive.conf new file mode 100644 index 000000000..6799399ff --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive.conf @@ -0,0 +1,5 @@ +[basic] +DataPath = ../data/mod_tcp_keepalive/tcp_keepalive.data + +[log] +OpenDebug = true \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/mod_tcp_keepalive.conf b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/mod_tcp_keepalive.conf new file mode 100644 index 000000000..961996d40 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/mod_tcp_keepalive.conf @@ -0,0 +1,5 @@ +[basic] +DataPath = ./mod_tcp_keepalive/tcp_keepalive.data + +[log] +OpenDebug = true \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/tcp_keepalive.data b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/tcp_keepalive.data new file mode 100644 index 000000000..d56982a32 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/tcp_keepalive.data @@ -0,0 +1,14 @@ +{ + "Config": { + "product1": [ + { + "VipConf": ["180.97.93.196"], + "KeepAliveParam": { + "KeepIdle": 270, + "KeepIntvl": 9 + } + } + ] + }, + "Version": "2021-06-25 14:31:05" +} \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive_2.conf b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive_2.conf new file mode 100644 index 000000000..18639b4dc --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive_2.conf @@ -0,0 +1 @@ +[basic] \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive.data b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive.data new file mode 100644 index 000000000..0844357c2 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive.data @@ -0,0 +1,30 @@ +{ + "Config": { + "product1": [ + { + "VipConf": ["10.1.1.1", "10.1.1.2"], + "KeepAliveParam": { + "KeepIdle": 70, + "KeepIntvl": 15, + "KeepCnt": 9 + } + }, + { + "VipConf": ["10.1.1.3"], + "KeepAliveParam": { + "Disable": true + } + } + ], + "product2": [ + { + "VipConf": ["10.2.1.1"], + "KeepAliveParam": { + "KeepIdle": 20, + "KeepIntvl": 15 + } + } + ] + }, + "Version": "2021-06-25 14:31:05" +} \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_2.data b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_2.data new file mode 100644 index 000000000..75d1da671 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_2.data @@ -0,0 +1,6 @@ +{ + "Config": { + "product1": {} + }, + "Version": "2021-06-25 14:31:05", +} \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_3.data b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_3.data new file mode 100644 index 000000000..b35b3669e --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_3.data @@ -0,0 +1,14 @@ +{ + "Config": { + "product1": [ + { + "VipConf": ["10.1"], + "KeepAliveParam": { + "KeepIdle": 20, + "KeepIntvl": 15 + } + } + ] + }, + "Version": "2021-06-25 14:31:05" +} \ No newline at end of file diff --git a/conf/mod_tcp_keepalive/mod_tcp_keepalive.conf b/conf/mod_tcp_keepalive/mod_tcp_keepalive.conf new file mode 100644 index 000000000..a68c030f6 --- /dev/null +++ b/conf/mod_tcp_keepalive/mod_tcp_keepalive.conf @@ -0,0 +1,5 @@ +[basic] +DataPath = ../data/mod_tcp_keepalive/tcp_keepalive.data + +[log] +OpenDebug = false From 4c51beee68173807c66e20f9cff6f9cb4a11a93e Mon Sep 17 00:00:00 2001 From: yuhui06 Date: Sun, 7 Nov 2021 18:40:09 +0800 Subject: [PATCH 02/33] add mod_tcp_keepalive. Signed-off-by: yuhui06 --- bfe_modules/bfe_modules.go | 4 + bfe_modules/mod_tcp_keepalive/conf_load.go | 63 ++++ .../mod_tcp_keepalive/conf_load_test.go | 51 ++++ bfe_modules/mod_tcp_keepalive/data_load.go | 212 +++++++++++++ .../mod_tcp_keepalive/data_load_test.go | 87 ++++++ .../mod_tcp_keepalive/keepalive_drawin.go | 38 +++ .../mod_tcp_keepalive/keepalive_linux.go | 32 ++ .../mod_tcp_keepalive/keepalive_table.go | 48 +++ .../mod_tcp_keepalive/keepalive_table_test.go | 41 +++ .../mod_tcp_keepalive/mod_tcp_keepalive.go | 283 ++++++++++++++++++ .../mod_tcp_keepalive_test.go | 90 ++++++ .../testdata/mod_tcp_keepalive.conf | 5 + .../mod_tcp_keepalive/mod_tcp_keepalive.conf | 5 + .../mod_tcp_keepalive/tcp_keepalive.data | 14 + .../testdata/mod_tcp_keepalive_2.conf | 1 + .../testdata/tcp_keepalive.data | 30 ++ .../testdata/tcp_keepalive_2.data | 6 + .../testdata/tcp_keepalive_3.data | 14 + conf/mod_tcp_keepalive/mod_tcp_keepalive.conf | 5 + 19 files changed, 1029 insertions(+) create mode 100644 bfe_modules/mod_tcp_keepalive/conf_load.go create mode 100644 bfe_modules/mod_tcp_keepalive/conf_load_test.go create mode 100644 bfe_modules/mod_tcp_keepalive/data_load.go create mode 100644 bfe_modules/mod_tcp_keepalive/data_load_test.go create mode 100644 bfe_modules/mod_tcp_keepalive/keepalive_drawin.go create mode 100644 bfe_modules/mod_tcp_keepalive/keepalive_linux.go create mode 100644 bfe_modules/mod_tcp_keepalive/keepalive_table.go create mode 100644 bfe_modules/mod_tcp_keepalive/keepalive_table_test.go create mode 100644 bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive.go create mode 100644 bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive_test.go create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive.conf create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/mod_tcp_keepalive.conf create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/tcp_keepalive.data create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive_2.conf create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive.data create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_2.data create mode 100644 bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_3.data create mode 100644 conf/mod_tcp_keepalive/mod_tcp_keepalive.conf diff --git a/bfe_modules/bfe_modules.go b/bfe_modules/bfe_modules.go index 6135fc7a6..326a9830a 100644 --- a/bfe_modules/bfe_modules.go +++ b/bfe_modules/bfe_modules.go @@ -39,6 +39,7 @@ import ( "github.com/bfenetworks/bfe/bfe_modules/mod_secure_link" "github.com/bfenetworks/bfe/bfe_modules/mod_static" "github.com/bfenetworks/bfe/bfe_modules/mod_tag" + "github.com/bfenetworks/bfe/bfe_modules/mod_tcp_keepalive" "github.com/bfenetworks/bfe/bfe_modules/mod_trace" "github.com/bfenetworks/bfe/bfe_modules/mod_trust_clientip" "github.com/bfenetworks/bfe/bfe_modules/mod_userid" @@ -54,6 +55,9 @@ var moduleList = []bfe_module.BfeModule{ // Requirement: After mod_trust_clientip mod_logid.NewModuleLogId(), + // mod_tcp_keepalive + mod_tcp_keepalive.NewModuleTcpKeepAlive(), + // mode_userid mod_userid.NewModuleUserID(), diff --git a/bfe_modules/mod_tcp_keepalive/conf_load.go b/bfe_modules/mod_tcp_keepalive/conf_load.go new file mode 100644 index 000000000..103dc60b1 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/conf_load.go @@ -0,0 +1,63 @@ +// Copyright (c) 2021 The BFE Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mod_tcp_keepalive + +import ( + "github.com/baidu/go-lib/log" + "github.com/bfenetworks/bfe/bfe_util" + gcfg "gopkg.in/gcfg.v1" +) + +type ConfModTcpKeepAlive struct { + Basic struct { + DataPath string // path of product keepalive rule data + } + + Log struct { + OpenDebug bool // whether open debug + } +} + +func ConfLoad(filePath string, confRoot string) (*ConfModTcpKeepAlive, error) { + var cfg ConfModTcpKeepAlive + var err error + + err = gcfg.ReadFileInto(&cfg, filePath) + if err != nil { + return &cfg, err + } + + // check conf of mod_tcp_keepalive + err = cfg.Check(confRoot) + if err != nil { + return &cfg, err + } + + return &cfg, nil +} + +func (cfg *ConfModTcpKeepAlive) Check(confRoot string) error { + return ConfModTcpKeepAliveCheck(cfg, confRoot) +} + +func ConfModTcpKeepAliveCheck(cfg *ConfModTcpKeepAlive, confRoot string) error { + if cfg.Basic.DataPath == "" { + log.Logger.Warn("ModTcpKeepAlive.DataPath not set, use default value") + cfg.Basic.DataPath = "mod_tcp_keepalive/tcp_keepalive.data" + } + cfg.Basic.DataPath = bfe_util.ConfPathProc(cfg.Basic.DataPath, confRoot) + + return nil +} diff --git a/bfe_modules/mod_tcp_keepalive/conf_load_test.go b/bfe_modules/mod_tcp_keepalive/conf_load_test.go new file mode 100644 index 000000000..7159efdc2 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/conf_load_test.go @@ -0,0 +1,51 @@ +// Copyright (c) 2021 The BFE Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mod_tcp_keepalive + +import ( + "testing" +) + +func TestConfModTcpKeepAlive_1(t *testing.T) { + config, err := ConfLoad("./testdata/mod_tcp_keepalive.conf", "") + if err != nil { + t.Errorf("TcpKeepAlive ConfLoad() error: %s", err.Error()) + return + } + + if config.Basic.DataPath != "../data/mod_tcp_keepalive/tcp_keepalive.data" { + t.Error("DataPath should be ../data/mod_tcp_keepalive/tcp_keepalive.data") + return + } + + if config.Log.OpenDebug != true { + t.Error("Log.OpenDebug shoule be true") + return + } +} + +func TestConfModTcpKeepAlive_2(t *testing.T) { + // invalid value + config, err := ConfLoad("./testdata/mod_tcp_keepalive_2.conf", "") + if err != nil { + t.Errorf("CondLoad() error: %s", err.Error()) + } + + // use default value + if config.Basic.DataPath != "mod_tcp_keepalive/tcp_keepalive.data" { + t.Error("DataPath shoule be mod_tcp_keepalive/tcp_keepalive.data") + return + } +} diff --git a/bfe_modules/mod_tcp_keepalive/data_load.go b/bfe_modules/mod_tcp_keepalive/data_load.go new file mode 100644 index 000000000..2d623d2eb --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/data_load.go @@ -0,0 +1,212 @@ +// Copyright (c) 2021 The BFE Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mod_tcp_keepalive + +import ( + "encoding/json" + "errors" + "fmt" + "net" + "os" +) + +/* +{ + "Version": "x", + "Config": { + "Product1": [{ + "VipConf": ["1.1.1.1", "1.1.1.2"], + "KeepAliveParam": { + "Disable": false, + "KeepIdle" : 70, + "KeepIntvl" : 15, + "KeepCnt": 9 + } + }] + } +} +*/ +// ProductRuleConf match the original tcp_keepalive.data +type ProductRuleConf struct { + Version string + Config map[string]ProductRulesFile +} + +type ProductRulesFile []ProductRuleFile +type ProductRuleFile struct { + VipConf []string + KeepAliveParam KeepAliveParam +} + +/* +{ + "Version": "x", + "Config": { + "Product1": { + "1.1.1.1": { + "Disable": false, + "KeepIdle" : 70, + "KeepIntvl" : 15, + "KeepCnt": 9 + }, + "1.1.1.2": { + "Disable": false, + "KeepIdle" : 70, + "KeepIntvl" : 15, + "KeepCnt": 9 + } + } + } +} +*/ +// ProductRuleData contains data convert from ProductRuleConf +type ProductRuleData struct { + Version string + Config ProductRules +} + +type KeepAliveParam struct { + Disable bool + KeepIdle int + KeepIntvl int + KeepCnt int +} +type KeepAliveRules map[string]KeepAliveParam +type ProductRules map[string]KeepAliveRules + +func ConvertConf(c ProductRuleConf) (ProductRuleData, error) { + data := ProductRuleData{} + data.Version = c.Version + data.Config = ProductRules{} + + for product, rules := range c.Config { + data.Config[product] = KeepAliveRules{} + for _, rule := range rules { + for _, val := range rule.VipConf { + ip, err := formatIP(val) + if err != nil { + return data, err + } + if _, ok := data.Config[product][ip]; ok { + return data, fmt.Errorf("duplicated ip[%s] in product[%s]", val, product) + } + data.Config[product][ip] = rule.KeepAliveParam + } + } + } + + return data, nil +} + +func RulesCheck(conf KeepAliveRules) error { + for ip, val := range conf { + if net.ParseIP(ip) == nil { + return fmt.Errorf("invalid ip: %s", ip) + } + + if val.KeepIdle < 0 || val.KeepIntvl < 0 || val.KeepCnt < 0 { + return fmt.Errorf("invalid keepalive param: %+v", val) + } + } + + return nil +} + +func ProductRulesCheck(conf ProductRules) error { + for product, rules := range conf { + if product == "" { + return fmt.Errorf("no product name") + } + if rules == nil { + return fmt.Errorf("no rules for product: %s", product) + } + + err := RulesCheck(rules) + if err != nil { + return fmt.Errorf("ProductRules:%s, %s", product, err.Error()) + } + } + + return nil +} + +func ProductRuleDataCheck(conf ProductRuleData) error { + var err error + + // check Version + if conf.Version == "" { + return errors.New("no Version") + } + + // check Config + if conf.Config == nil { + return errors.New("no Config") + } + + err = ProductRulesCheck(conf.Config) + if err != nil { + return fmt.Errorf("Config: %s", err.Error()) + } + + return nil +} + +func formatIP(s string) (string, error) { + ip := net.ParseIP(s) + if ip == nil { + return "", fmt.Errorf("formatIP: net.ParseIP() error, ip: %s", s) + } + + ret := ip.String() + if ret == "" { + return "", fmt.Errorf("formatIP: ip.String() error, ip: %s", s) + } + + return ret, nil +} + +func KeepAliveDataLoad(filename string) (ProductRuleData, error) { + var err error + var conf ProductRuleConf + var data ProductRuleData + + // open the file + file, err := os.Open(filename) + defer file.Close() + if err != nil { + return data, err + } + + // decode the file + decoder := json.NewDecoder(file) + err = decoder.Decode(&conf) + if err != nil { + return data, err + } + + // convert to ProductRuleData + data, err = ConvertConf(conf) + if err != nil { + return data, err + } + + // check data + err = ProductRuleDataCheck(data) + if err != nil { + return data, err + } + + return data, nil +} diff --git a/bfe_modules/mod_tcp_keepalive/data_load_test.go b/bfe_modules/mod_tcp_keepalive/data_load_test.go new file mode 100644 index 000000000..8c370e977 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/data_load_test.go @@ -0,0 +1,87 @@ +// Copyright (c) 2021 The BFE Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mod_tcp_keepalive + +import ( + "testing" +) + +func TestKeepAliveDataLoad_1(t *testing.T) { + data, err := KeepAliveDataLoad("./testdata/tcp_keepalive.data") + if err != nil { + t.Errorf("get err from ProductRuleConfLoad(): %s", err.Error()) + return + } + + if len(data.Config) != 2 { + t.Errorf("len(config.Config) should be 2, but is %d", len(data.Config)) + return + } + + if len(data.Config["product1"]) != 3 { + t.Errorf("len(data.Config[product1]) shoule be 3, but is %d", len(data.Config["product1"])) + return + } +} + +// invalid format of data +func TestKeepAliveDataLoad_2(t *testing.T) { + _, err := KeepAliveDataLoad("./testdata/tcp_keepalive_2.data") + if err == nil { + t.Error("err should not be nil") + return + } +} + +// invalid format of ip +func TestKeepAliveDataLoad_3(t *testing.T) { + _, err := KeepAliveDataLoad("./testdata/tcp_keepalive_3.data") + if err == nil { + t.Errorf("err should not be nil: %v", err) + return + } +} + +func TestFormatIP(t *testing.T) { + ret1, _ := formatIP("2001:0db8:02de:0000:0000:0000:0000:0e13") + ret2, _ := formatIP("2001:db8:2de:000:000:000:000:e13") + ret3, _ := formatIP("2001:db8:2de:0:0:0:0:e13") + expect1 := "2001:db8:2de::e13" + + if ret1 != expect1 || ret2 != expect1 || ret3 != expect1 { + t.Errorf("ret should equal to %s", expect1) + return + } + + ret5, _ := formatIP("2001:db8:2de:0:0:0:0:e13") + ret6, _ := formatIP("2001:db8:2de::e13") + expect2 := "2001:db8:2de::e13" + if ret5 != expect2 || ret6 != expect2 { + t.Errorf("ret should equal to %s", expect2) + return + } + + _, err := formatIP("2001::25de::cade") + if err == nil { + t.Error("err should not be nil, 2001::25de::cade is invalid ip") + return + } + + _, err = formatIP("127.1") + if err == nil { + t.Error("err should not be nil, 127.1 is invalid ip") + return + } +} diff --git a/bfe_modules/mod_tcp_keepalive/keepalive_drawin.go b/bfe_modules/mod_tcp_keepalive/keepalive_drawin.go new file mode 100644 index 000000000..ac03edfac --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/keepalive_drawin.go @@ -0,0 +1,38 @@ +// Copyright (c) 2021 The BFE Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mod_tcp_keepalive + +import ( + "os" + "syscall" +) + +// from netinet/tcp.h (OS X 10.9.4) +const ( + _TCP_KEEPINTVL = 0x101 /* interval between keepalives */ + _TCP_KEEPCNT = 0x102 /* number of keepalives before close */ +) + +func setIdle(fd int, secs int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE, secs)) +} + +func setCount(fd int, n int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, _TCP_KEEPCNT, n)) +} + +func setInterval(fd int, secs int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, _TCP_KEEPINTVL, secs)) +} diff --git a/bfe_modules/mod_tcp_keepalive/keepalive_linux.go b/bfe_modules/mod_tcp_keepalive/keepalive_linux.go new file mode 100644 index 000000000..150078d91 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/keepalive_linux.go @@ -0,0 +1,32 @@ +// Copyright (c) 2021 The BFE Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mod_tcp_keepalive + +import ( + "os" + "syscall" +) + +func setIdle(fd int, secs int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs)) +} + +func setCount(fd int, n int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPCNT, n)) +} + +func setInterval(fd int, secs int) error { + return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs)) +} diff --git a/bfe_modules/mod_tcp_keepalive/keepalive_table.go b/bfe_modules/mod_tcp_keepalive/keepalive_table.go new file mode 100644 index 000000000..d45a14a78 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/keepalive_table.go @@ -0,0 +1,48 @@ +// Copyright (c) 2021 The BFE Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mod_tcp_keepalive + +import ( + "sync" +) + +type KeepAliveTable struct { + lock sync.RWMutex + version string + productRules ProductRules +} + +func NewKeepAliveTable() *KeepAliveTable { + t := new(KeepAliveTable) + t.productRules = make(ProductRules) + + return t +} + +func (t *KeepAliveTable) Update(data ProductRuleData) { + t.lock.Lock() + t.version = data.Version + t.productRules = data.Config + t.lock.Unlock() +} + +func (t *KeepAliveTable) Search(product string) (KeepAliveRules, bool) { + t.lock.RLock() + productRules := t.productRules + t.lock.RUnlock() + + rules, ok := productRules[product] + return rules, ok +} diff --git a/bfe_modules/mod_tcp_keepalive/keepalive_table_test.go b/bfe_modules/mod_tcp_keepalive/keepalive_table_test.go new file mode 100644 index 000000000..739daa965 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/keepalive_table_test.go @@ -0,0 +1,41 @@ +// Copyright (c) 2021 The BFE Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mod_tcp_keepalive + +import ( + "testing" +) + +func TestKeepAliveTable(t *testing.T) { + table := NewKeepAliveTable() + path := "./testdata/tcp_keepalive.data" + data, err := KeepAliveDataLoad(path) + if err != nil { + t.Errorf("KeepAliveDataLoad(%s) error: %v", path, err) + return + } + + table.Update(data) + if len(table.productRules) != 2 { + t.Errorf("table.Update error: rules length should be 2 but %d", len(table.productRules)) + return + } + + _, ok := table.Search("product1") + if !ok { + t.Errorf("table.Search error: product1 should exist") + return + } +} diff --git a/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive.go b/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive.go new file mode 100644 index 000000000..36334d4c3 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive.go @@ -0,0 +1,283 @@ +// Copyright (c) 2021 The BFE Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mod_tcp_keepalive + +import ( + "fmt" + "net" + "net/url" + "os" + "reflect" + "syscall" + + "github.com/baidu/go-lib/log" + "github.com/baidu/go-lib/web-monitor/metrics" + "github.com/baidu/go-lib/web-monitor/web_monitor" + "github.com/bfenetworks/bfe/bfe_basic" + "github.com/bfenetworks/bfe/bfe_module" + "github.com/bfenetworks/bfe/bfe_util" +) + +const ( + ModTcpKeepAlive = "mod_tcp_keepalive" +) + +var ( + openDebug = false +) + +type ModuleTcpKeepAliveState struct { + ConnToSet *metrics.Counter // connection hit rule, to set or disable keeplaive + ConnSetKeepIdle *metrics.Counter // connection set keepalive idle + ConnSetKeepIdleError *metrics.Counter // connection set keepalive idle error + ConnSetKeepIntvl *metrics.Counter // connection set keepalive interval + ConnSetKeepIntvlError *metrics.Counter // connection set keepalive interval error + ConnSetKeepCnt *metrics.Counter // connection set keepalive retry count + ConnSetKeepCntError *metrics.Counter // connection set keepalive retry count error + ConnDisableKeepAlive *metrics.Counter // connection disable keepalive message + ConnDisableKeepAliveError *metrics.Counter // connection disable keepalive error + ConnConvertToTcpConnError *metrics.Counter // connection convert to TCPConn error +} + +type ModuleTcpKeepAlive struct { + name string // name of module + + state ModuleTcpKeepAliveState // module state + metrics metrics.Metrics // module metrics + + dataPath string // path of module data file + ruleTable *KeepAliveTable // table of keepalive rules +} + +func NewModuleTcpKeepAlive() *ModuleTcpKeepAlive { + m := new(ModuleTcpKeepAlive) + m.name = ModTcpKeepAlive + m.metrics.Init(&m.state, ModTcpKeepAlive, 0) + m.ruleTable = NewKeepAliveTable() + + return m +} + +func (m *ModuleTcpKeepAlive) Name() string { + return m.name +} + +func (m *ModuleTcpKeepAlive) Init(cbs *bfe_module.BfeCallbacks, whs *web_monitor.WebHandlers, cr string) error { + var conf *ConfModTcpKeepAlive + var err error + + // load module config + confPath := bfe_module.ModConfPath(cr, m.name) + if conf, err = ConfLoad(confPath, cr); err != nil { + return fmt.Errorf("%s: conf load err %s", m.name, err.Error()) + } + + m.dataPath = conf.Basic.DataPath + openDebug = conf.Log.OpenDebug + + // load conf data + if err = m.loadConfData(nil); err != nil { + return fmt.Errorf("%s: loadConfData() err %s", m.name, err.Error()) + } + + // register handler + err = cbs.AddFilter(bfe_module.HandleAccept, m.HandleAccept) + if err != nil { + return fmt.Errorf("%s.Init(): AddFilter(m.HandleAccept): %s", m.name, err.Error()) + } + + // register web handler for monitor + err = web_monitor.RegisterHandlers(whs, web_monitor.WebHandleMonitor, m.monitorHandlers()) + if err != nil { + return fmt.Errorf("%s.Init(): RegisterHandlers(m.monitorHandlers): %s", m.name, err.Error()) + } + + // register web handler for reload + err = web_monitor.RegisterHandlers(whs, web_monitor.WebHandleReload, m.reloadHandlers()) + if err != nil { + return fmt.Errorf("%s.Init(): RegisterHandlers(m.reloadHandlers): %s", m.name, err.Error()) + } + + return nil +} + +func (m *ModuleTcpKeepAlive) loadConfData(query url.Values) error { + path := query.Get("path") + if path == "" { + // use default + path = m.dataPath + } + + // load file + data, err := KeepAliveDataLoad(path) + if err != nil { + return fmt.Errorf("err in KeepAliveDataLoad(%s): %s", path, err.Error()) + } + + m.ruleTable.Update(data) + + return nil +} + +func (m *ModuleTcpKeepAlive) disableKeepAlive(tcpConn *net.TCPConn) error { + err := tcpConn.SetKeepAlive(false) + if err != nil { + m.state.ConnDisableKeepAliveError.Inc(1) + return fmt.Errorf("SetKeepAlive(false) failed: %v", err) + } + + m.state.ConnDisableKeepAlive.Inc(1) + return nil +} + +func setNonblock(fd int) error { + return os.NewSyscallError("setsockopt", syscall.SetNonblock(fd, true)) +} + +func (m *ModuleTcpKeepAlive) setKeepAliveParam(conn *net.TCPConn, p KeepAliveParam) error { + var err error + var f *os.File + + if f, err = conn.File(); err != nil { + return fmt.Errorf("get conn.File() error: %v", err) + } + defer f.Close() + fd := int(f.Fd()) + + if p.KeepIdle > 0 { + err = setIdle(fd, p.KeepIdle) + if err != nil { + m.state.ConnSetKeepIdleError.Inc(1) + return fmt.Errorf("set tcp keepIdle error: %v", err) + } + m.state.ConnSetKeepIdle.Inc(1) + } + + if p.KeepIntvl > 0 { + err = setInterval(fd, p.KeepIntvl) + if err != nil { + m.state.ConnSetKeepIntvlError.Inc(1) + return fmt.Errorf("set tcp keepIntvl error: %v", err) + } + m.state.ConnSetKeepIntvl.Inc(1) + } + + if p.KeepCnt > 0 { + err = setCount(fd, p.KeepCnt) + if err != nil { + m.state.ConnSetKeepCntError.Inc(1) + return fmt.Errorf("set tcp KeepCnt error: %v", err) + } + m.state.ConnSetKeepCnt.Inc(1) + } + + err = setNonblock(fd) + if err != nil { + return fmt.Errorf("setNonblock error: %v", err) + } + + return err +} + +func (m *ModuleTcpKeepAlive) handleTcpKeepAlive(conn *net.TCPConn, p KeepAliveParam) error { + if p.Disable { + return m.disableKeepAlive(conn) + } + + return m.setKeepAliveParam(conn, p) +} + +func (m *ModuleTcpKeepAlive) getTcpConn(conn net.Conn) (*net.TCPConn, error) { + if c, ok := conn.(bfe_util.ConnFetcher); ok { + conn = c.GetNetConn() + return m.getTcpConn(conn) + } + + tcpConn, ok := conn.(*net.TCPConn) + if !ok { + m.state.ConnConvertToTcpConnError.Inc(1) + if openDebug { + log.Logger.Debug("conn type[%s] connvert to TCPConn failed", reflect.TypeOf(conn)) + } + + return nil, fmt.Errorf("conn connvert to TCPConn failed") + } + + return tcpConn, nil +} + +func (m *ModuleTcpKeepAlive) HandleAccept(session *bfe_basic.Session) int { + vip := session.Vip.String() + if openDebug { + log.Logger.Debug("mod[%s] get connection, remote: %v, vip: %s", m.name, session.RemoteAddr, vip) + } + + rules, ok := m.ruleTable.Search(session.Product) + if !ok { + if openDebug { + log.Logger.Debug("mod[%s] product[%s] not found, just pass", m.name, session.Product) + } + return bfe_module.BfeHandlerGoOn + } + + if param, ok := rules[vip]; ok { + m.state.ConnToSet.Inc(1) + conn, err := m.getTcpConn(session.Connection) + if err != nil { + log.Logger.Error("mod[%s] vip[%s] getTcpConn error: %v", err) + return bfe_module.BfeHandlerGoOn + } + + err = m.handleTcpKeepAlive(conn, param) + if err != nil { + log.Logger.Error("mod[%s] vip[%s] remote[%v] handleTcpKeepAlive error: %v", m.name, vip, session.RemoteAddr, err) + } + + if openDebug { + log.Logger.Debug("mod[%s] vip[%s] product[%s] found, set keepalive success, param[%+v]", m.name, vip, session.Product, param) + } + + return bfe_module.BfeHandlerGoOn + } + + return bfe_module.BfeHandlerGoOn +} + +func (m *ModuleTcpKeepAlive) getState(params map[string][]string) ([]byte, error) { + s := m.metrics.GetAll() + return s.Format(params) +} + +func (m *ModuleTcpKeepAlive) getStateDiff(params map[string][]string) ([]byte, error) { + s := m.metrics.GetDiff() + return s.Format(params) +} + +func (m *ModuleTcpKeepAlive) monitorHandlers() map[string]interface{} { + handlers := map[string]interface{}{ + m.name: m.getState, + m.name + ".diff": m.getStateDiff, + } + + return handlers +} + +func (m *ModuleTcpKeepAlive) reloadHandlers() map[string]interface{} { + handlers := map[string]interface{}{ + m.name: m.loadConfData, + } + + return handlers +} diff --git a/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive_test.go b/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive_test.go new file mode 100644 index 000000000..d443173d3 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/mod_tcp_keepalive_test.go @@ -0,0 +1,90 @@ +// Copyright (c) 2021 The BFE Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mod_tcp_keepalive + +import ( + "net" + "testing" + + "github.com/baidu/go-lib/web-monitor/web_monitor" + "github.com/bfenetworks/bfe/bfe_basic" + "github.com/bfenetworks/bfe/bfe_http" + "github.com/bfenetworks/bfe/bfe_module" +) + +func prepareModule() (*ModuleTcpKeepAlive, error) { + m := NewModuleTcpKeepAlive() + err := m.Init(bfe_module.NewBfeCallbacks(), web_monitor.NewWebHandlers(), "./testdata") + return m, err +} + +func prepareRequest() *bfe_basic.Request { + request := new(bfe_basic.Request) + request.HttpRequest = new(bfe_http.Request) + request.Session = new(bfe_basic.Session) + request.Context = make(map[interface{}]interface{}) + return request +} + +func TestSetKeepAlive(t *testing.T) { + m, err := prepareModule() + if err != nil { + t.Errorf("prepareModule() error: %v", err) + return + } + s := new(bfe_basic.Session) + ip := "180.97.93.196" + address := "180.97.93.196:80" + + s.Product = "product1" + s.Vip = net.ParseIP(ip) + if s.Vip == nil { + t.Errorf("net.ParseIP(%s) == nil", ip) + } + + conn, err := net.Dial("tcp", address) + if err != nil { + t.Errorf("net.Dial(tcp, %s) error: %v", address, err) + return + } + s.Connection = conn + + m.HandleAccept(s) + metrics := m.metrics.GetAll() + if metrics.CounterData["CONN_TO_SET"] != 1 || + metrics.CounterData["CONN_SET_KEEP_IDLE"] != 1 || + metrics.CounterData["CONN_SET_KEEP_INTVL"] != 1 { + + t.Errorf("CONN_TO_SET and CONN_SET_KEEP_IDLE and CONN_SET_KEEP_INTVL should be 1") + return + } +} + +func TestModuleMisc(t *testing.T) { + m, err := prepareModule() + if err != nil { + t.Errorf("prepareModule() error: %v", err) + return + } + if s, _ := m.getState(nil); s == nil { + t.Errorf("Should return valid state") + } + if m.monitorHandlers() == nil { + t.Errorf("Should return valid monitor handlers") + } + if m.reloadHandlers() == nil { + t.Errorf("Should return valid reload handlers") + } +} diff --git a/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive.conf b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive.conf new file mode 100644 index 000000000..6799399ff --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive.conf @@ -0,0 +1,5 @@ +[basic] +DataPath = ../data/mod_tcp_keepalive/tcp_keepalive.data + +[log] +OpenDebug = true \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/mod_tcp_keepalive.conf b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/mod_tcp_keepalive.conf new file mode 100644 index 000000000..961996d40 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/mod_tcp_keepalive.conf @@ -0,0 +1,5 @@ +[basic] +DataPath = ./mod_tcp_keepalive/tcp_keepalive.data + +[log] +OpenDebug = true \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/tcp_keepalive.data b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/tcp_keepalive.data new file mode 100644 index 000000000..d56982a32 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive/tcp_keepalive.data @@ -0,0 +1,14 @@ +{ + "Config": { + "product1": [ + { + "VipConf": ["180.97.93.196"], + "KeepAliveParam": { + "KeepIdle": 270, + "KeepIntvl": 9 + } + } + ] + }, + "Version": "2021-06-25 14:31:05" +} \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive_2.conf b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive_2.conf new file mode 100644 index 000000000..18639b4dc --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/mod_tcp_keepalive_2.conf @@ -0,0 +1 @@ +[basic] \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive.data b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive.data new file mode 100644 index 000000000..0844357c2 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive.data @@ -0,0 +1,30 @@ +{ + "Config": { + "product1": [ + { + "VipConf": ["10.1.1.1", "10.1.1.2"], + "KeepAliveParam": { + "KeepIdle": 70, + "KeepIntvl": 15, + "KeepCnt": 9 + } + }, + { + "VipConf": ["10.1.1.3"], + "KeepAliveParam": { + "Disable": true + } + } + ], + "product2": [ + { + "VipConf": ["10.2.1.1"], + "KeepAliveParam": { + "KeepIdle": 20, + "KeepIntvl": 15 + } + } + ] + }, + "Version": "2021-06-25 14:31:05" +} \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_2.data b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_2.data new file mode 100644 index 000000000..75d1da671 --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_2.data @@ -0,0 +1,6 @@ +{ + "Config": { + "product1": {} + }, + "Version": "2021-06-25 14:31:05", +} \ No newline at end of file diff --git a/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_3.data b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_3.data new file mode 100644 index 000000000..b35b3669e --- /dev/null +++ b/bfe_modules/mod_tcp_keepalive/testdata/tcp_keepalive_3.data @@ -0,0 +1,14 @@ +{ + "Config": { + "product1": [ + { + "VipConf": ["10.1"], + "KeepAliveParam": { + "KeepIdle": 20, + "KeepIntvl": 15 + } + } + ] + }, + "Version": "2021-06-25 14:31:05" +} \ No newline at end of file diff --git a/conf/mod_tcp_keepalive/mod_tcp_keepalive.conf b/conf/mod_tcp_keepalive/mod_tcp_keepalive.conf new file mode 100644 index 000000000..a68c030f6 --- /dev/null +++ b/conf/mod_tcp_keepalive/mod_tcp_keepalive.conf @@ -0,0 +1,5 @@ +[basic] +DataPath = ../data/mod_tcp_keepalive/tcp_keepalive.data + +[log] +OpenDebug = false From d938087f0704e7979ebfdd36782e322412618445 Mon Sep 17 00:00:00 2001 From: yuhui06 Date: Sun, 7 Nov 2021 19:08:24 +0800 Subject: [PATCH 03/33] add mod_tcp_keepalive Signed-off-by: yuhui06 --- .../{keepalive_drawin.go => keepalive_darwin.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename bfe_modules/mod_tcp_keepalive/{keepalive_drawin.go => keepalive_darwin.go} (100%) diff --git a/bfe_modules/mod_tcp_keepalive/keepalive_drawin.go b/bfe_modules/mod_tcp_keepalive/keepalive_darwin.go similarity index 100% rename from bfe_modules/mod_tcp_keepalive/keepalive_drawin.go rename to bfe_modules/mod_tcp_keepalive/keepalive_darwin.go From 21b0468b363f6cbae829a87442cb100385c0ba89 Mon Sep 17 00:00:00 2001 From: yuhui06 Date: Tue, 23 Nov 2021 21:58:02 +0800 Subject: [PATCH 04/33] add mod_tcp_keepalive Signed-off-by: yuhui06 --- bfe_modules/mod_tcp_keepalive/data_load.go | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/bfe_modules/mod_tcp_keepalive/data_load.go b/bfe_modules/mod_tcp_keepalive/data_load.go index 2d623d2eb..59ad8267f 100644 --- a/bfe_modules/mod_tcp_keepalive/data_load.go +++ b/bfe_modules/mod_tcp_keepalive/data_load.go @@ -29,10 +29,10 @@ import ( "Product1": [{ "VipConf": ["1.1.1.1", "1.1.1.2"], "KeepAliveParam": { - "Disable": false, + "Disable": false, "KeepIdle" : 70, "KeepIntvl" : 15, - "KeepCnt": 9 + "KeepCnt": 9 } }] } @@ -55,18 +55,18 @@ type ProductRuleFile struct { "Version": "x", "Config": { "Product1": { - "1.1.1.1": { - "Disable": false, + "1.1.1.1": { + "Disable": false, "KeepIdle" : 70, "KeepIntvl" : 15, - "KeepCnt": 9 - }, - "1.1.1.2": { - "Disable": false, + "KeepCnt": 9 + }, + "1.1.1.2": { + "Disable": false, "KeepIdle" : 70, "KeepIntvl" : 15, - "KeepCnt": 9 - } + "KeepCnt": 9 + } } } } @@ -78,10 +78,10 @@ type ProductRuleData struct { } type KeepAliveParam struct { - Disable bool - KeepIdle int - KeepIntvl int - KeepCnt int + Disable bool // close the TCP-KeepAlive heartbeat message sending strategy + KeepIdle int // period to send heartbeat message since there is no data transport in tcp connection + KeepIntvl int // period to send heartbeat message again when last message is not applied + KeepCnt int // count to resend heartbeat message when last message is not applied } type KeepAliveRules map[string]KeepAliveParam type ProductRules map[string]KeepAliveRules From f34a535598296418612c1fb594210b0c589ba456 Mon Sep 17 00:00:00 2001 From: clarinette9 <83874119+clarinette9@users.noreply.github.com> Date: Fri, 10 Dec 2021 17:15:25 +0800 Subject: [PATCH 05/33] Merge master into develop for release of 1.4.0 (#905) * Update CHANGELOG * add v1.4.0 to changelog Co-authored-by: Sijie Yang Co-authored-by: Sijie Yang --- CHANGELOG.md | 17 +++++++++++++++++ VERSION | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3d4e5772..5e0ef8106 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v1.4.0] - 2021-12-10 + +### Added + +- Documents optimization + +### Changed + +- Upgrade golang version from 1.13 to 1.17 +- mod_markdown: upgrade bluemonday version to 1.0.16 +- Optimize mutex +- Improve Makefile and pre-commit + ## [v1.3.0] - 2021-09-16 ### Added @@ -262,6 +275,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Flexible plugin framework to extend functionality. Based on the framework, developer can add new features rapidly - Detailed built-in metrics available for service status monitor +<<<<<<< HEAD +======= +[v1.4.0]: https://github.com/bfenetworks/bfe/compare/v1.3.0...v1.4.0 +>>>>>>> release/v1.4.0 [v1.3.0]: https://github.com/bfenetworks/bfe/compare/v1.2.0...v1.3.0 [v1.2.0]: https://github.com/bfenetworks/bfe/compare/v1.1.0...v1.2.0 [v1.1.0]: https://github.com/bfenetworks/bfe/compare/v1.0.0...v1.1.0 diff --git a/VERSION b/VERSION index f0bb29e76..88c5fb891 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.0 +1.4.0 From fd9cd9c228fc10fda03cabb08864b927d8516c93 Mon Sep 17 00:00:00 2001 From: clarinette9 Date: Fri, 10 Dec 2021 17:52:17 +0800 Subject: [PATCH 06/33] update DOWNLOAD.md to provide v1.4.0 downloads --- docs/en_us/DOWNLOAD.md | 13 ++++++++++++- docs/zh_cn/DOWNLOAD.md | 13 ++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/docs/en_us/DOWNLOAD.md b/docs/en_us/DOWNLOAD.md index e0967dac0..e13f66a0c 100644 --- a/docs/en_us/DOWNLOAD.md +++ b/docs/en_us/DOWNLOAD.md @@ -1,5 +1,17 @@ We provide precompiled binaries for bfe components. [Download the latest release](https://github.com/bfenetworks/bfe/releases) of BFE for your platform. +## bfe v1.4.0 + +* 2021-12-10 [Release notes](https://github.com/bfenetworks/bfe/releases/tag/v1.4.0) + +| File name | OS | Arch | Size | SHA256 Checksum | +| --------- | -------- | ---- | ---- | ------------ | +| [bfe_1.4.0_darwin_amd64.tar.gz](https://github.com/bfenetworks/bfe/releases/download/v1.4.0/bfe_1.4.0_darwin_amd64.tar.gz) | darwin | amd 64 | 9.26M | 03940a193b3e6a18b9f0f0f0ad344110e362f511c7582d21f39c4b4581ff6fd1 | +| [bfe_1.4.0_linux_amd64.tar.gz](https://github.com/bfenetworks/bfe/releases/download/v1.4.0/bfe_1.4.0_linux_amd64.tar.gz) | linux | amd64 | 9.51 MB | 62535dd2025be9bd5484d92bb991c6f8080c7e7d69911fd7eef4fd5235cf61ab | +| [bfe_1.4.0_linux_arm64.tar.gz](https://github.com/bfenetworks/bfe/releases/download/v1.4.0/bfe_1.4.0_linux_arm64.tar.gz) | linux | arm64 | 8.8 MB | 33de43a45fd6c6414b4359aa2c3e1141d2299ee07ad6dfb48d2afd1af1561734 | +| [bfe_1.4.0_windows_amd64.tar.gz](https://github.com/bfenetworks/bfe/releases/download/v1.4.0/bfe_1.4.0_windows_amd64.tar.gz) | windows | amd64 | 9.59 MB | c637b5917a428850dde470e915eaac3076707da8959392d38bce70eee2190767 | + + ## bfe v1.3.0 * 2021-09-16 [Release notes](https://github.com/bfenetworks/bfe/releases/tag/v1.3.0) @@ -69,4 +81,3 @@ We provide precompiled binaries for bfe components. [Download the latest release | [bfe_0.9.0_linux_amd64.tar.gz](https://github.com/bfenetworks/bfe/releases/download/v0.9.0/bfe_0.9.0_linux_amd64.tar.gz) | linux | amd64 | 10.90 MB | 9b6aaac88651d88e86e67835b5ae0bdbe1c76076382b198f0aeb0b94b7572887 | | [bfe_0.9.0_windows_amd64.zip](https://github.com/bfenetworks/bfe/releases/download/v0.9.0/bfe_0.9.0_windows_amd64.zip) | windows | amd64 | 9.75 MB | 4079f97b544b3070bec3ad65a28ccb816290890a278a51c88c81c15405c1f8cf | - diff --git a/docs/zh_cn/DOWNLOAD.md b/docs/zh_cn/DOWNLOAD.md index b2907d2c9..4056616bb 100644 --- a/docs/zh_cn/DOWNLOAD.md +++ b/docs/zh_cn/DOWNLOAD.md @@ -1,5 +1,17 @@ BFE提供预编译二进制文件供下载。也可在GitHub下载各平台[最新版本BFE](https://github.com/bfenetworks/bfe/releases)。 +## bfe v1.4.0 + +* 2021-12-10 [发布说明](https://github.com/bfenetworks/bfe/releases/tag/v1.4.0) + +| 文件名 | 操作系统 | 平台 | 大小 | SHA256检验和 | +| --------- | -------- | ---- | ---- | ------------ | +| [bfe_1.4.0_darwin_amd64.tar.gz](https://github.com/bfenetworks/bfe/releases/download/v1.4.0/bfe_1.4.0_darwin_amd64.tar.gz) | darwin | amd 64 | 9.26M | 03940a193b3e6a18b9f0f0f0ad344110e362f511c7582d21f39c4b4581ff6fd1 | +| [bfe_1.4.0_linux_amd64.tar.gz](https://github.com/bfenetworks/bfe/releases/download/v1.4.0/bfe_1.4.0_linux_amd64.tar.gz) | linux | amd64 | 9.51 MB | 62535dd2025be9bd5484d92bb991c6f8080c7e7d69911fd7eef4fd5235cf61ab | +| [bfe_1.4.0_linux_arm64.tar.gz](https://github.com/bfenetworks/bfe/releases/download/v1.4.0/bfe_1.4.0_linux_arm64.tar.gz) | linux | arm64 | 8.8 MB | 33de43a45fd6c6414b4359aa2c3e1141d2299ee07ad6dfb48d2afd1af1561734 | +| [bfe_1.4.0_windows_amd64.tar.gz](https://github.com/bfenetworks/bfe/releases/download/v1.4.0/bfe_1.4.0_windows_amd64.tar.gz) | windows | amd64 | 9.59 MB | c637b5917a428850dde470e915eaac3076707da8959392d38bce70eee2190767 | + + ## bfe v1.3.0 * 2021-09-16 [发布说明](https://github.com/bfenetworks/bfe/releases/tag/v1.3.0) @@ -67,4 +79,3 @@ BFE提供预编译二进制文件供下载。也可在GitHub下载各平台[最 | [bfe_0.9.0_linux_amd64.tar.gz](https://github.com/bfenetworks/bfe/releases/download/v0.9.0/bfe_0.9.0_linux_amd64.tar.gz) | linux | amd64 | 10.90 MB | 9b6aaac88651d88e86e67835b5ae0bdbe1c76076382b198f0aeb0b94b7572887 | | [bfe_0.9.0_windows_amd64.zip](https://github.com/bfenetworks/bfe/releases/download/v0.9.0/bfe_0.9.0_windows_amd64.zip) | windows | amd64 | 9.75 MB | 4079f97b544b3070bec3ad65a28ccb816290890a278a51c88c81c15405c1f8cf | - From ffdc8f9a830d6c44186a7f06fb9e6f8801217ff7 Mon Sep 17 00:00:00 2001 From: clarinette9 Date: Mon, 13 Dec 2021 10:41:15 +0800 Subject: [PATCH 07/33] document: fix format in CHANGELOG.md and update required golang version to 1.17 --- CHANGELOG.md | 3 +-- docs/en_us/faq/installation.md | 2 +- docs/en_us/installation/install_from_source.md | 2 +- docs/en_us/installation/install_using_go.md | 2 +- docs/zh_cn/faq/installation.md | 2 +- docs/zh_cn/installation/install_from_source.md | 2 +- docs/zh_cn/installation/install_using_go.md | 2 +- 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e0ef8106..58a981afd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -275,10 +275,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Flexible plugin framework to extend functionality. Based on the framework, developer can add new features rapidly - Detailed built-in metrics available for service status monitor -<<<<<<< HEAD + ======= [v1.4.0]: https://github.com/bfenetworks/bfe/compare/v1.3.0...v1.4.0 ->>>>>>> release/v1.4.0 [v1.3.0]: https://github.com/bfenetworks/bfe/compare/v1.2.0...v1.3.0 [v1.2.0]: https://github.com/bfenetworks/bfe/compare/v1.1.0...v1.2.0 [v1.1.0]: https://github.com/bfenetworks/bfe/compare/v1.0.0...v1.1.0 diff --git a/docs/en_us/faq/installation.md b/docs/en_us/faq/installation.md index 2e5110d43..37c6edb97 100644 --- a/docs/en_us/faq/installation.md +++ b/docs/en_us/faq/installation.md @@ -1,7 +1,7 @@ # Installation FAQ ## Go get timeout during installation -- Set GOPROXY enviroment variable as follows (go1.13+): +- Set GOPROXY enviroment variable as follows (go1.17+): ```bash $ go env -w GO111MODULE=on $ go env -w GOPROXY=https://goproxy.cn,direct diff --git a/docs/en_us/installation/install_from_source.md b/docs/en_us/installation/install_from_source.md index 6112b97a9..bd1aba957 100644 --- a/docs/en_us/installation/install_from_source.md +++ b/docs/en_us/installation/install_from_source.md @@ -1,7 +1,7 @@ # Install from source code ## Prerequisites -- golang 1.13+ +- golang 1.17+ - git 2.0+ - glibc-static 2.17+ diff --git a/docs/en_us/installation/install_using_go.md b/docs/en_us/installation/install_using_go.md index 3409a359d..99d381922 100644 --- a/docs/en_us/installation/install_using_go.md +++ b/docs/en_us/installation/install_using_go.md @@ -1,7 +1,7 @@ # Install using go ## Prerequisites -- golang 1.13+ +- golang 1.17+ ## Installation - Get the source code and install diff --git a/docs/zh_cn/faq/installation.md b/docs/zh_cn/faq/installation.md index 8eb65dc29..87ee67fc0 100644 --- a/docs/zh_cn/faq/installation.md +++ b/docs/zh_cn/faq/installation.md @@ -1,7 +1,7 @@ # 安装常见问题 ## 安装时遇到go get超时错误 -- 设置GOPROXY环境变量(go1.13及以上版本) +- 设置GOPROXY环境变量(go1.17及以上版本) ```bash $ go env -w GO111MODULE=on $ go env -w GOPROXY=https://goproxy.cn,direct diff --git a/docs/zh_cn/installation/install_from_source.md b/docs/zh_cn/installation/install_from_source.md index 5054a6ced..30cd81393 100644 --- a/docs/zh_cn/installation/install_from_source.md +++ b/docs/zh_cn/installation/install_from_source.md @@ -1,7 +1,7 @@ # 源码编译安装 ## 环境准备 -- golang 1.13+ +- golang 1.17+ - git 2.0+ - glibc-static 2.17+ diff --git a/docs/zh_cn/installation/install_using_go.md b/docs/zh_cn/installation/install_using_go.md index f50c7619e..6e5534702 100644 --- a/docs/zh_cn/installation/install_using_go.md +++ b/docs/zh_cn/installation/install_using_go.md @@ -1,7 +1,7 @@ # go方式安装 ## 环境准备 -* golang 1.13+ +* golang 1.17+ ## 安装 - 获取并安装 From c1dd30a0d15fef4c220b86c6ce83ce757d704161 Mon Sep 17 00:00:00 2001 From: clarinette9 <83874119+clarinette9@users.noreply.github.com> Date: Mon, 13 Dec 2021 11:09:32 +0800 Subject: [PATCH 08/33] fix format of CHANGELOG.md Signed-off-by: clarinette9 --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58a981afd..b5ba3f1c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -275,8 +275,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Flexible plugin framework to extend functionality. Based on the framework, developer can add new features rapidly - Detailed built-in metrics available for service status monitor - -======= [v1.4.0]: https://github.com/bfenetworks/bfe/compare/v1.3.0...v1.4.0 [v1.3.0]: https://github.com/bfenetworks/bfe/compare/v1.2.0...v1.3.0 [v1.2.0]: https://github.com/bfenetworks/bfe/compare/v1.1.0...v1.2.0 From 79b895a506e1e48d99605426fa2202264be78667 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Mon, 13 Dec 2021 14:53:40 +0800 Subject: [PATCH 09/33] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 01ac56bd4..2ec9fc257 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,8 @@ English | [中文](README-CN.md) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fbfenetworks%2Fbfe.svg?type=shield)](https://app.fossa.com/reports/1f05f9f0-ac3d-486e-8ba9-ad95dabd4768) [![Slack Widget](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=green)](https://slack.cncf.io) -BFE is a modern layer 7 load balancer from baidu. +BFE (Beyond Front End) is a modern layer 7 load balancer from baidu. +![bfe logo](./docs/images/logo/horizontal/color/bfe-horizontal-color.png) ## Introduction From df3b2ab2e02103fdc2ef59e456b66700bd53d18b Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Mon, 13 Dec 2021 14:55:01 +0800 Subject: [PATCH 10/33] Update README-CN.md --- README-CN.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README-CN.md b/README-CN.md index 62ce69b4a..aa5d7adca 100644 --- a/README-CN.md +++ b/README-CN.md @@ -11,7 +11,8 @@ [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fbfenetworks%2Fbfe.svg?type=shield)](https://app.fossa.com/reports/1f05f9f0-ac3d-486e-8ba9-ad95dabd4768) [![Slack Widget](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=green)](https://slack.cncf.io) -BFE是百度开源的现代化、企业级的七层负载均衡系统 +BFE (Beyond Front End) 是百度开源的现代化、企业级的七层负载均衡系统 +![bfe logo](./docs/images/logo/horizontal/color/bfe-horizontal-color.png) ## 简介 From a9f95a199a091b7193e4dfe0edb799bec694e2cb Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Mon, 13 Dec 2021 15:33:19 +0800 Subject: [PATCH 11/33] Update condition_primitive_index.md --- .../condition/condition_primitive_index.md | 88 +++++++++---------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/docs/en_us/condition/condition_primitive_index.md b/docs/en_us/condition/condition_primitive_index.md index bd19dd5c8..659451deb 100644 --- a/docs/en_us/condition/condition_primitive_index.md +++ b/docs/en_us/condition/condition_primitive_index.md @@ -1,54 +1,54 @@ # Condition Primitive Index ## Request Primitive - * req_cip_hash_in(value_list) - * req_cip_range(start_ip, end_ip) - * req_cip_trusted() - * req_cookie_key_in(key_list) - * req_cookie_value_contain(key, value, case_insensitive) - * req_cookie_value_in(key, value_list, case_insensitive) - * req_cookie_value_hash_in(key, value_list, case_insensitive) - * req_cookie_value_prefix_in(key, value_prefix_list, case_insensitive) - * req_cookie_value_suffix_in(key, value_suffix_list, case_insensitive) - * req_header_key_in(key_list) - * req_header_value_contain(key, value_list, case_insensitive) - * req_header_value_in(header_name, value_list, case_insensitive) - * req_header_value_hash_in(header_name, value_list, case_insensitive) - * req_header_value_prefix_in(header_name, value_prefix_list, case_insensitive) - * req_header_value_suffix_in(header_name, value_suffix_list, case_insensitive) - * req_host_in(host_list) - * req_method_in(method_list) - * req_proto_secure() - * req_tag_match(tagName, tagValue) - * req_path_in(path_list, case_insensitive) - * req_path_contain(path_list, case_insensitive) - * req_path_prefix_in(prefix_list, case_insensitive) - * req_path_element_prefix_in(prefix_list, case_insensitive) - * req_path_suffix_in(suffix_list, case_insensitive) - * req_query_key_in(key_list) - * req_query_key_prefix_in(prefix_list) - * req_query_value_in(key, value_list, case_insensitive) - * req_query_value_hash_in(key, value_list, case_insensitive) - * req_query_value_prefix_in(key, prefix_list, case_insensitive) - * req_query_value_suffix_in(key, suffix_list, case_insensitive) - * req_port_in(port_list) - * req_url_regmatch(reg_exp) - * req_vip_in(vip_list) - * req_vip_range(start_ip, end_ip) + * [req_cip_hash_in(value_list)](./request/ip.md#req_cip_hash_invalue_list) + * [req_cip_range(start_ip, end_ip)](./request/ip.md#req_cip_rangestart_ip-end_ip) + * [req_cip_trusted()](./request/ip.md#req_cip_trusted) + * [req_cookie_key_in(key_list)](./request/cookie.md#req_cookie_key_inkey_list) + * [req_cookie_value_contain(key, value, case_insensitive)](./request/cookie.md#req_cookie_value_containkey-value-case_insensitive) + * [req_cookie_value_in(key, value_list, case_insensitive)](./request/cookie.md#req_cookie_value_inkey-value_list-case_insensitive) + * [req_cookie_value_hash_in(key, value_list, case_insensitive)](./request/cookie.md#req_cookie_value_hash_inkey-value_list-case_insensitive) + * [req_cookie_value_prefix_in(key, value_prefix_list, case_insensitive)](./request/cookie.md#req_cookie_value_prefix_inkey-value_prefix_list-case_insensitive) + * [req_cookie_value_suffix_in(key, value_suffix_list, case_insensitive)](./request/cookie.md#req_cookie_value_suffix_inkey-value_suffix_list-case_insensitive) + * [req_header_key_in(key_list)](./request/header.md#req_header_key_inkey_list) + * [req_header_value_contain(key, value_list, case_insensitive)](./request/header.md#req_header_value_containheader_name-value_list-case_insensitive) + * [req_header_value_in(header_name, value_list, case_insensitive)](./request/header.md#req_header_value_inheader_name-value_list-case_insensitive) + * [req_header_value_hash_in(header_name, value_list, case_insensitive)](./request/header.md#req_header_value_hash_inheader_name-value_list-case_insensitive) + * [req_header_value_prefix_in(header_name, value_prefix_list, case_insensitive)](./request/header.md#req_header_value_prefix_inheader_name-value_prefix_list-case_insensitive) + * [req_header_value_suffix_in(header_name, value_suffix_list, case_insensitive)](./request/header.md#req_header_value_suffix_inheader_name-value_suffix_list-case_insensitive) + * [req_host_in(host_list)](./request/uri.md#req_host_inhost_list) + * [req_method_in(method_list)](./request/method.md#req_method_inmethod_list) + * [req_proto_secure()](./request/protocol.md#req_proto_secure) + * [req_tag_match(tagName, tagValue)](./request/tag.md#req_tag_matchtagname-tagvalue) + * [req_path_in(path_list, case_insensitive)](./request/uri.md#req_path_inpath_list-case_insensitive) + * [req_path_contain(path_list, case_insensitive)](./request/uri.md#req_path_containpath_list-case_insensitive) + * [req_path_prefix_in(prefix_list, case_insensitive)](./request/uri.md#req_path_prefix_inprefix_list-case_insensitive) + * [req_path_element_prefix_in(prefix_list, case_insensitive)](./request/uri.md#req_path_element_prefix_inprefix_list-case_insensitive) + * [req_path_suffix_in(suffix_list, case_insensitive)](./request/uri.md#req_path_suffix_insuffix_list-case_insensitive) + * [req_query_key_in(key_list)](./request/uri.md#req_query_key_inkey_list) + * [req_query_key_prefix_in(prefix_list)](./request/uri.md#req_query_key_prefix_inprefix_list) + * [req_query_value_in(key, value_list, case_insensitive)](./request/uri.md#req_query_value_inkey-value_list-case_insensitive) + * [req_query_value_hash_in(key, value_list, case_insensitive)](./request/uri.md#req_query_value_hash_inkey-value_list-case_insensitive) + * [req_query_value_prefix_in(key, prefix_list, case_insensitive)](./request/uri.md#req_query_value_prefix_inkey-prefix_list-case_insensitive) + * [req_query_value_suffix_in(key, suffix_list, case_insensitive)](./request/uri.md#req_query_value_suffix_inkey-suffix_list-case_insensitive) + * [req_port_in(port_list)](./request/uri.md#req_port_inport_list) + * [req_url_regmatch(reg_exp)](./request/uri.md#req_url_regmatchreg_exp) + * [req_vip_in(vip_list)](./request/ip.md#req_vip_invip_list) + * [req_vip_range(start_ip, end_ip)](./request/ip.md#req_vip_rangestart_ip-end_ip) ## Response Primitive - * res_code_in(codes) - * res_header_key_in(key_list) - * res_header_value_in(key, value_list, case_insensitive) + * [res_code_in(codes)](./response/code.md#res_code_incodes) + * [res_header_key_in(key_list)](./response/header.md#res_header_key_inkey_list) + * [res_header_value_in(key, value_list, case_insensitive)](./response/header.md#res_header_value_inkey-value_list-case_insensitive) ## Session Primitive - * ses_sip_range(start_ip, end_ip) - * ses_vip_range(start_ip, end_ip) - * ses_tls_sni_in(host_list) - * ses_tls_client_auth() - * ses_tls_client_ca_in(ca_list) + * [ses_sip_range(start_ip, end_ip)](./session/ip.md#ses_sip_rangestart_ip-end_ip) + * [ses_vip_range(start_ip, end_ip)](./session/ip.md#ses_vip_rangestart_ip-end_ip) + * [ses_tls_sni_in(host_list)](./session/tls.md#ses_tls_sni_inhost_list) + * [ses_tls_client_auth()](./session/tls.md#ses_tls_client_auth) + * [ses_tls_client_ca_in(ca_list)](./session/tls.md#ses_tls_client_ca_inca_list) ## System Primitive - * bfe_time_range(start_time, end_time) - * bfe_periodic_time_range(start_time, end_time, period) + * [bfe_time_range(start_time, end_time)](./system/time.md#bfe_time_rangestart_time-end_time) + * [bfe_periodic_time_range(start_time, end_time, period)](./system/time.md#bfe_periodic_time_rangestart_time-end_time-period) From 0960b44b06499f61ea71e55efde623543f4222e8 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Mon, 13 Dec 2021 15:36:03 +0800 Subject: [PATCH 12/33] Update condition_primitive_index.md --- .../condition/condition_primitive_index.md | 88 +++++++++---------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/docs/zh_cn/condition/condition_primitive_index.md b/docs/zh_cn/condition/condition_primitive_index.md index 2585de2f9..12b235b63 100644 --- a/docs/zh_cn/condition/condition_primitive_index.md +++ b/docs/zh_cn/condition/condition_primitive_index.md @@ -1,54 +1,54 @@ # 条件原语索引 ## 请求相关 - * req_cip_hash_in(value_list) - * req_cip_range(start_ip, end_ip) - * req_cip_trusted() - * req_cookie_key_in(key_list) - * req_cookie_value_contain(key, value, case_insensitive) - * req_cookie_value_in(key, value_list, case_insensitive) - * req_cookie_value_hash_in(key, value_list, case_insensitive) - * req_cookie_value_prefix_in(key, value_prefix_list, case_insensitive) - * req_cookie_value_suffix_in(key, value_suffix_list, case_insensitive) - * req_header_key_in(key_list) - * req_header_value_contain(key, value_list, case_insensitive) - * req_header_value_in(header_name, value_list, case_insensitive) - * req_header_value_hash_in(header_name, value_list, case_insensitive) - * req_header_value_prefix_in(header_name, value_prefix_list, case_insensitive) - * req_header_value_suffix_in(header_name, value_suffix_list, case_insensitive) - * req_host_in(host_list) - * req_method_in(method_list) - * req_proto_secure() - * req_tag_match(tagName, tagValue) - * req_path_in(path_list, case_insensitive) - * req_path_contain(path_list, case_insensitive) - * req_path_prefix_in(prefix_list, case_insensitive) - * req_path_suffix_in(suffix_list, case_insensitive) - * req_path_element_suffix_in(suffix_list, case_insensitive) - * req_query_key_in(key_list) - * req_query_key_prefix_in(prefix_list) - * req_query_value_in(key, value_list, case_insensitive) - * req_query_value_hash_in(key, value_list, case_insensitive) - * req_query_value_prefix_in(key, prefix_list, case_insensitive) - * req_query_value_suffix_in(key, suffix_list, case_insensitive) - * req_port_in(port_list) - * req_url_regmatch(reg_exp) - * req_vip_in(vip_list) - * req_vip_range(start_ip, end_ip) + * [req_cip_hash_in(value_list)](./request/ip.md#req_cip_hash_invalue_list) + * [req_cip_range(start_ip, end_ip)](./request/ip.md#req_cip_rangestart_ip-end_ip) + * [req_cip_trusted()](./request/ip.md#req_cip_trusted) + * [req_cookie_key_in(key_list)](./request/cookie.md#req_cookie_key_inkey_list) + * [req_cookie_value_contain(key, value, case_insensitive)](./request/cookie.md#req_cookie_value_containkey-value-case_insensitive) + * [req_cookie_value_in(key, value_list, case_insensitive)](./request/cookie.md#req_cookie_value_inkey-value_list-case_insensitive) + * [req_cookie_value_hash_in(key, value_list, case_insensitive)](./request/cookie.md#req_cookie_value_hash_inkey-value_list-case_insensitive) + * [req_cookie_value_prefix_in(key, value_prefix_list, case_insensitive)](./request/cookie.md#req_cookie_value_prefix_inkey-value_prefix_list-case_insensitive) + * [req_cookie_value_suffix_in(key, value_suffix_list, case_insensitive)](./request/cookie.md#req_cookie_value_suffix_inkey-value_suffix_list-case_insensitive) + * [req_header_key_in(key_list)](./request/header.md#req_header_key_inkey_list) + * [req_header_value_contain(key, value_list, case_insensitive)](./request/header.md#req_header_value_containheader_name-value_list-case_insensitive) + * [req_header_value_in(header_name, value_list, case_insensitive)](./request/header.md#req_header_value_inheader_name-value_list-case_insensitive) + * [req_header_value_hash_in(header_name, value_list, case_insensitive)](./request/header.md#req_header_value_hash_inheader_name-value_list-case_insensitive) + * [req_header_value_prefix_in(header_name, value_prefix_list, case_insensitive)](./request/header.md#req_header_value_prefix_inheader_name-value_prefix_list-case_insensitive) + * [req_header_value_suffix_in(header_name, value_suffix_list, case_insensitive)](./request/header.md#req_header_value_suffix_inheader_name-value_suffix_list-case_insensitive) + * [req_host_in(host_list)](./request/uri.md#req_host_inhost_list) + * [req_method_in(method_list)](./request/method.md#req_method_inmethod_list) + * [req_proto_secure()](./request/protocol.md#req_proto_secure) + * [req_tag_match(tagName, tagValue)](./request/tag.md#req_tag_matchtagname-tagvalue) + * [req_path_in(path_list, case_insensitive)](./request/uri.md#req_path_inpath_list-case_insensitive) + * [req_path_contain(path_list, case_insensitive)](./request/uri.md#req_path_containpath_list-case_insensitive) + * [req_path_prefix_in(prefix_list, case_insensitive)](./request/uri.md#req_path_prefix_inprefix_list-case_insensitive) + * [req_path_element_prefix_in(prefix_list, case_insensitive)](./request/uri.md#req_path_element_prefix_inprefix_list-case_insensitive) + * [req_path_suffix_in(suffix_list, case_insensitive)](./request/uri.md#req_path_suffix_insuffix_list-case_insensitive) + * [req_query_key_in(key_list)](./request/uri.md#req_query_key_inkey_list) + * [req_query_key_prefix_in(prefix_list)](./request/uri.md#req_query_key_prefix_inprefix_list) + * [req_query_value_in(key, value_list, case_insensitive)](./request/uri.md#req_query_value_inkey-value_list-case_insensitive) + * [req_query_value_hash_in(key, value_list, case_insensitive)](./request/uri.md#req_query_value_hash_inkey-value_list-case_insensitive) + * [req_query_value_prefix_in(key, prefix_list, case_insensitive)](./request/uri.md#req_query_value_prefix_inkey-prefix_list-case_insensitive) + * [req_query_value_suffix_in(key, suffix_list, case_insensitive)](./request/uri.md#req_query_value_suffix_inkey-suffix_list-case_insensitive) + * [req_port_in(port_list)](./request/uri.md#req_port_inport_list) + * [req_url_regmatch(reg_exp)](./request/uri.md#req_url_regmatchreg_exp) + * [req_vip_in(vip_list)](./request/ip.md#req_vip_invip_list) + * [req_vip_range(start_ip, end_ip)](./request/ip.md#req_vip_rangestart_ip-end_ip) ## 响应相关 - * res_code_in(codes) - * res_header_key_in(key_list) - * res_header_value_in(key, value_list, case_insensitive) + * [res_code_in(codes)](./response/code.md#res_code_incodes) + * [res_header_key_in(key_list)](./response/header.md#res_header_key_inkey_list) + * [res_header_value_in(key, value_list, case_insensitive)](./response/header.md#res_header_value_inkey-value_list-case_insensitive) ## 会话相关 - * ses_sip_range(start_ip, end_ip) - * ses_vip_range(start_ip, end_ip) - * ses_tls_sni_in(host_list) - * ses_tls_client_auth() - * ses_tls_client_ca_in(ca_list) + * [ses_sip_range(start_ip, end_ip)](./session/ip.md#ses_sip_rangestart_ip-end_ip) + * [ses_vip_range(start_ip, end_ip)](./session/ip.md#ses_vip_rangestart_ip-end_ip) + * [ses_tls_sni_in(host_list)](./session/tls.md#ses_tls_sni_inhost_list) + * [ses_tls_client_auth()](./session/tls.md#ses_tls_client_auth) + * [ses_tls_client_ca_in(ca_list)](./session/tls.md#ses_tls_client_ca_inca_list) ## 系统相关 - * bfe_time_range(start_time, end_time) - * bfe_periodic_time_range(start_time, end_time, period) + * [bfe_time_range(start_time, end_time)](./system/time.md#bfe_time_rangestart_time-end_time) + * [bfe_periodic_time_range(start_time, end_time, period)](./system/time.md#bfe_periodic_time_rangestart_time-end_time-period) From 18f4398d9a921a53ab7f577f685efe61795ce03b Mon Sep 17 00:00:00 2001 From: clarinette9 Date: Mon, 13 Dec 2021 15:43:59 +0800 Subject: [PATCH 13/33] change required golang version back to 1.13 for install from source and go Signed-off-by: clarinette9 --- docs/en_us/faq/installation.md | 2 +- docs/en_us/installation/install_from_source.md | 2 +- docs/en_us/installation/install_using_go.md | 2 +- docs/zh_cn/faq/installation.md | 2 +- docs/zh_cn/installation/install_from_source.md | 2 +- docs/zh_cn/installation/install_using_go.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/en_us/faq/installation.md b/docs/en_us/faq/installation.md index 37c6edb97..2e5110d43 100644 --- a/docs/en_us/faq/installation.md +++ b/docs/en_us/faq/installation.md @@ -1,7 +1,7 @@ # Installation FAQ ## Go get timeout during installation -- Set GOPROXY enviroment variable as follows (go1.17+): +- Set GOPROXY enviroment variable as follows (go1.13+): ```bash $ go env -w GO111MODULE=on $ go env -w GOPROXY=https://goproxy.cn,direct diff --git a/docs/en_us/installation/install_from_source.md b/docs/en_us/installation/install_from_source.md index bd1aba957..6112b97a9 100644 --- a/docs/en_us/installation/install_from_source.md +++ b/docs/en_us/installation/install_from_source.md @@ -1,7 +1,7 @@ # Install from source code ## Prerequisites -- golang 1.17+ +- golang 1.13+ - git 2.0+ - glibc-static 2.17+ diff --git a/docs/en_us/installation/install_using_go.md b/docs/en_us/installation/install_using_go.md index 99d381922..3409a359d 100644 --- a/docs/en_us/installation/install_using_go.md +++ b/docs/en_us/installation/install_using_go.md @@ -1,7 +1,7 @@ # Install using go ## Prerequisites -- golang 1.17+ +- golang 1.13+ ## Installation - Get the source code and install diff --git a/docs/zh_cn/faq/installation.md b/docs/zh_cn/faq/installation.md index 87ee67fc0..8eb65dc29 100644 --- a/docs/zh_cn/faq/installation.md +++ b/docs/zh_cn/faq/installation.md @@ -1,7 +1,7 @@ # 安装常见问题 ## 安装时遇到go get超时错误 -- 设置GOPROXY环境变量(go1.17及以上版本) +- 设置GOPROXY环境变量(go1.13及以上版本) ```bash $ go env -w GO111MODULE=on $ go env -w GOPROXY=https://goproxy.cn,direct diff --git a/docs/zh_cn/installation/install_from_source.md b/docs/zh_cn/installation/install_from_source.md index 30cd81393..5054a6ced 100644 --- a/docs/zh_cn/installation/install_from_source.md +++ b/docs/zh_cn/installation/install_from_source.md @@ -1,7 +1,7 @@ # 源码编译安装 ## 环境准备 -- golang 1.17+ +- golang 1.13+ - git 2.0+ - glibc-static 2.17+ diff --git a/docs/zh_cn/installation/install_using_go.md b/docs/zh_cn/installation/install_using_go.md index 6e5534702..f50c7619e 100644 --- a/docs/zh_cn/installation/install_using_go.md +++ b/docs/zh_cn/installation/install_using_go.md @@ -1,7 +1,7 @@ # go方式安装 ## 环境准备 -* golang 1.17+ +* golang 1.13+ ## 安装 - 获取并安装 From eb10dcd0e58ff916aee9f951047cab2252e1b51d Mon Sep 17 00:00:00 2001 From: Dai Ming Date: Fri, 17 Dec 2021 17:52:25 +0800 Subject: [PATCH 14/33] Upgrade to golang 1.17 in Dockerfile (#909) --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 70a8d16de..19f50ddd8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. # -FROM golang:1.13.11-alpine AS build +FROM golang:1.17.5-alpine3.15 AS build WORKDIR /bfe COPY . . RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-X main.version=`cat VERSION`" -FROM alpine:3.10 AS run +FROM alpine:3.15 AS run RUN apk update && apk add --no-cache ca-certificates COPY --from=build /bfe/bfe /bfe/bin/ COPY conf /bfe/conf/ From 8c9ebaa0331118a94d3fc187b43331823cc064ad Mon Sep 17 00:00:00 2001 From: Lanco <35420416+lancoLiu@users.noreply.github.com> Date: Fri, 17 Dec 2021 18:35:36 +0800 Subject: [PATCH 15/33] Add errInvalidWrite for CopyWithoutBuffer (#797) For buggy io.Writer which sometimes writes too many bytes, it is not inappropriate to return ErrShortWrite Signed-off-by: lancoLiu <1105635443@qq.com> --- bfe_util/copy_util.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bfe_util/copy_util.go b/bfe_util/copy_util.go index 2421fac3f..68db19fe5 100644 --- a/bfe_util/copy_util.go +++ b/bfe_util/copy_util.go @@ -15,6 +15,7 @@ package bfe_util import ( + "errors" "io" "sync" ) @@ -25,6 +26,9 @@ import ( var copyPool sync.Pool +// errInvalidWrite means that a writer returned an impossible count. +var errInvalidWrite = errors.New("invalid write result") + func newByteBuf() []byte { if v := copyPool.Get(); v != nil { return v.([]byte) @@ -45,9 +49,13 @@ func CopyWithoutBuffer(wf bfe_http.WriteFlusher, src io.Reader) (written int64, nw, ew := wf.Write(buf[0:nr]) // flush immediately regardless of write result. ef := wf.Flush() - if nw > 0 { - written += int64(nw) + if nw < 0 || nr < nw { + nw = 0 + if ew == nil { + ew = errInvalidWrite + } } + written += int64(nw) if ew != nil { err = ew break From f49e9cd99e2fc2b485b729a3c8647f04e1c38b88 Mon Sep 17 00:00:00 2001 From: yuhui06 Date: Sun, 19 Dec 2021 15:28:48 +0800 Subject: [PATCH 16/33] add zh_cn doc for mod_tcp_keepalive Signed-off-by: yuhui06 --- .../mod_tcp_keepalive/mod_tcp_keepalive.md | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md diff --git a/docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md b/docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md new file mode 100644 index 000000000..284af026e --- /dev/null +++ b/docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md @@ -0,0 +1,95 @@ +# mod_tcp_keepalive + +## 模块简介 + +mod_tcp_keepalive管理TCP长连接心跳包的发送策略。 + +在某些场景下可能对耗电量十分敏感,比如智能手表待机状态,希望能够停止发送TCP长连接时的心跳包,或者降低其发送频率,此模块即可以用来处理此类或者其他需要管理TCP心跳包发送策略的场景。 + +## 基础配置 + +### 配置描述 + +模块配置文件: conf/mod_tcp_keepalive/mod_tcp_keepalive.conf + +| 配置项 | 描述 | +| ----- | --- | +| Basic.DataPath | String
规则文件路径 | +| Log.OpenDebug | Boolean
是否开启debug模式 | + +### 配置示例 +```ini +[Basic] +DataPath = ../data/mod_tcp_keepalive/tcp_keepalive.data + +[Log] +OpenDebug = false +``` + +## 规则配置 + +### 配置描述 + +| 配置项 | 描述 | +| ----- | --- | +| Version | String
配置文件版本 | +| Config | Object
各产品线(租户)的TCP心跳包管理规则 | +| Config{k} | String
产品线名称 | +| Config{v} | Array
产品线下规则列表 | +| Config{v}[] | Object
某一条规则详细信息 | +| Config{v}[].VipConf | Array
需要配置的IP数组,数组中的IP共用以下同一套策略 | +| Config{v}[].KeepAliveParam | Object
TCP长连接心跳包发送策略 | +| Config{v}[].KeepaliveParam.Disable | Bool
是否关闭心跳包发送,默认false | +| Config{v}[].KeepaliveParam.KeepIdle | Int
长连接中多长时间无数据发送后,开始发送心跳包 | +| Config{v}[].KeepaliveParam.KeepIntvl | Int
如果上个心跳包未收到回应,多长时间后再次发送心跳包 | +| Config{v}[].KeepaliveParam.KeepCnt | Int
心跳包未收到回应,再次发送心跳包的重试次数 | + +### 配置示例 + +```json +{ + "Config": { + "product1": [ + { + "VipConf": ["10.1.1.1", "10.1.1.2"], + "KeepAliveParam": { + "KeepIdle": 70, + "KeepIntvl": 15, + "KeepCnt": 9 + } + }, + { + "VipConf": ["10.1.1.3"], + "KeepAliveParam": { + "Disable": true + } + } + ], + "product2": [ + { + "VipConf": ["10.2.1.1"], + "KeepAliveParam": { + "KeepIdle": 20, + "KeepIntvl": 15 + } + } + ] + }, + "Version": "2021-06-25 14:31:05" +} +``` + +## 监控项 + +| 监控项 | 描述 | +| ------------- | ---------------------------- | +| CONN_TO_SET | 命中配置规则的连接总数 | +| CONN_SET_KEEP_IDLE | 设置keepIdle属性的连接数 | +| CONN_SET_KEEP_IDLE_ERROR | 设置keepIdle属性失败的连接数 | +| CONN_SET_KEEP_INTVL | 设置keepIntvl属性的连接数 | +| CONN_SET_KEEP_INTVL_ERROR | 设置keepIntvl属性失败的连接数 | +| CONN_SET_KEEP_CNT | 设置keepCnt属性的连接数 | +| CONN_SET_KEEP_CNT_ERROR | 设置keepCnt属性失败的连接数 | +| CONN_DISABLE_KEEP_ALIVE | 设置disable属性的连接数 | +| CONN_DISABLE_KEEP_ALIVE_ERROR | 设置disable属性失败的连接数 | +| CONN_COVERT_TO_TCP_CONN_ERROR | 将连接类型转换为TCPConn类型失败的次数 | From 176fd6e8b35409ad00f131c719089a1488241522 Mon Sep 17 00:00:00 2001 From: yuhui06 Date: Sun, 19 Dec 2021 15:40:01 +0800 Subject: [PATCH 17/33] add zh_cn doc for mod_tcp_keepalive(#910) Signed-off-by: yuhui06 --- docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md b/docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md index 284af026e..04a7a8917 100644 --- a/docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md +++ b/docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md @@ -75,7 +75,7 @@ OpenDebug = false } ] }, - "Version": "2021-06-25 14:31:05" + "Version": "2021-06-25 14:31:06" } ``` From 4cdb7324839a9d49eb2f30809277cd90aab12eaa Mon Sep 17 00:00:00 2001 From: yuhui06 Date: Sun, 19 Dec 2021 15:49:57 +0800 Subject: [PATCH 18/33] add en_us doc for mod_tcp_keepalive(#910) Signed-off-by: yuhui06 --- .../mod_tcp_keepalive/mod_tcp_keepalive.md | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 docs/en_us/modules/mod_tcp_keepalive/mod_tcp_keepalive.md diff --git a/docs/en_us/modules/mod_tcp_keepalive/mod_tcp_keepalive.md b/docs/en_us/modules/mod_tcp_keepalive/mod_tcp_keepalive.md new file mode 100644 index 000000000..413379794 --- /dev/null +++ b/docs/en_us/modules/mod_tcp_keepalive/mod_tcp_keepalive.md @@ -0,0 +1,95 @@ +# mod_tcp_keepalive + +## Introduction + +mod_tcp_keepalive set tcp connection keepalive message sending strategy based on defined rules. + +In some situation, like smart watch, which is sensitive to power consumption, may need to close the TCP-KeepAlive heartbeat message or increase the interval to send TCP-KeepAlive heartbeat message, mod_tcp_keepalive can help handle situation like this. + +## Module Configuration + +### Description + +conf/mod_tcp_keepalive/mod_tcp_keepalive.conf + +| Config Item | Description | +| ----- | --- | +| Basic.DataPath | String
Path of product rule configuration | +| Log.OpenDebug | Boolean
Open debug mode or not | + +### Example +```ini +[Basic] +DataPath = ../data/mod_tcp_keepalive/tcp_keepalive.data + +[Log] +OpenDebug = false +``` + +## Rule Configuration + +### Description + +| Config Item | Description | +| ----- | --- | +| Version | String
Version of config file | +| Config | Object
Rules for each product | +| Config{k} | String
Product name | +| Config{v} | Array
A list of rules | +| Config{v}[] | Object
A specific rule | +| Config{v}[].VipConf | Array
The IP list to set the keepalive message strategy | +| Config{v}[].KeepAliveParam | Object
The specific keepalive message strategy| +| Config{v}[].KeepaliveParam.Disable | Bool
Disable sending keepalive message or not, default false | +| Config{v}[].KeepaliveParam.KeepIdle | Int
Period to send heartbeat message since there is no data transport in tcp connection | +| Config{v}[].KeepaliveParam.KeepIntvl | Int
Period to send heartbeat message again when last message is not applied | +| Config{v}[].KeepaliveParam.KeepCnt | Int
Counter to resend heartbeat message when last message is not applied | + +### Example + +```json +{ + "Config": { + "product1": [ + { + "VipConf": ["10.1.1.1", "10.1.1.2"], + "KeepAliveParam": { + "KeepIdle": 70, + "KeepIntvl": 15, + "KeepCnt": 9 + } + }, + { + "VipConf": ["10.1.1.3"], + "KeepAliveParam": { + "Disable": true + } + } + ], + "product2": [ + { + "VipConf": ["10.2.1.1"], + "KeepAliveParam": { + "KeepIdle": 20, + "KeepIntvl": 15 + } + } + ] + }, + "Version": "2021-06-25 14:31:05" +} +``` + +## Metrics + +| Metric | Description | +| ------------- | ---------------------------- | +| CONN_TO_SET | Counter for connection which hit rule, to set or disable keeplaive | +| CONN_SET_KEEP_IDLE | Counter for connection set keepalive idle | +| CONN_SET_KEEP_IDLE_ERROR | Counter for connection set keepalive idle error | +| CONN_SET_KEEP_INTVL | Counter for connection set keepalive interval | +| CONN_SET_KEEP_INTVL_ERROR | Counter for connection set keepalive interval error | +| CONN_SET_KEEP_CNT | Counter for connection set keepalive retry count | +| CONN_SET_KEEP_CNT_ERROR | Counter for connection set keepalive retry count error | +| CONN_DISABLE_KEEP_ALIVE | Counter for connection disable keepalive message | +| CONN_DISABLE_KEEP_ALIVE_ERROR | Counter for connection disable keepalive error | +| CONN_COVERT_TO_TCP_CONN_ERROR | Counter for connection convert to TCPConn error | From 3ce5c0582848ad7095a06bf4b9aae8f62b49ff4e Mon Sep 17 00:00:00 2001 From: yuhui06 Date: Mon, 20 Dec 2021 11:28:24 +0800 Subject: [PATCH 19/33] update doc according to the comments Signed-off-by: yuhui06 --- docs/en_us/modules/mod_tcp_keepalive/mod_tcp_keepalive.md | 6 +++--- docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/en_us/modules/mod_tcp_keepalive/mod_tcp_keepalive.md b/docs/en_us/modules/mod_tcp_keepalive/mod_tcp_keepalive.md index 413379794..cecaadd46 100644 --- a/docs/en_us/modules/mod_tcp_keepalive/mod_tcp_keepalive.md +++ b/docs/en_us/modules/mod_tcp_keepalive/mod_tcp_keepalive.md @@ -2,9 +2,9 @@ ## Introduction -mod_tcp_keepalive set tcp connection keepalive message sending strategy based on defined rules. +mod_tcp_keepalive is used to set strategy of sending keepalive message in tcp connection. -In some situation, like smart watch, which is sensitive to power consumption, may need to close the TCP-KeepAlive heartbeat message or increase the interval to send TCP-KeepAlive heartbeat message, mod_tcp_keepalive can help handle situation like this. +In some situation, like smart watch, the device is sensitive to power consumption, it may be necessary to close the TCP-KeepAlive heartbeat message or increase the interval of sending TCP-KeepAlive heartbeat message. mod_tcp_keepalive can help to handle situation like this. ## Module Configuration @@ -37,7 +37,7 @@ OpenDebug = false | Config{k} | String
Product name | | Config{v} | Array
A list of rules | | Config{v}[] | Object
A specific rule | -| Config{v}[].VipConf | Array
The IP list to set the keepalive message strategy | +| Config{v}[].VipConf | Array
The list of virtual IPs to set the keepalive message strategy | | Config{v}[].KeepAliveParam | Object
The specific keepalive message strategy| | Config{v}[].KeepaliveParam.Disable | Bool
Disable sending keepalive message or not, default false | | Config{v}[].KeepaliveParam.KeepIdle | Int
Period to send heartbeat message since there is no data transport in tcp connection | diff --git a/docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md b/docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md index 04a7a8917..699450e6a 100644 --- a/docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md +++ b/docs/zh_cn/modules/mod_tcp_keepalive/mod_tcp_keepalive.md @@ -35,9 +35,9 @@ OpenDebug = false | Version | String
配置文件版本 | | Config | Object
各产品线(租户)的TCP心跳包管理规则 | | Config{k} | String
产品线名称 | -| Config{v} | Array
产品线下规则列表 | +| Config{v} | Array
产品线的规则列表 | | Config{v}[] | Object
某一条规则详细信息 | -| Config{v}[].VipConf | Array
需要配置的IP数组,数组中的IP共用以下同一套策略 | +| Config{v}[].VipConf | Array
需要配置的VIP(Virtual IP)数组,数组中的VIP共用以下同一套策略 | | Config{v}[].KeepAliveParam | Object
TCP长连接心跳包发送策略 | | Config{v}[].KeepaliveParam.Disable | Bool
是否关闭心跳包发送,默认false | | Config{v}[].KeepaliveParam.KeepIdle | Int
长连接中多长时间无数据发送后,开始发送心跳包 | From d2fd6b93034e94d56a2c4cd5441db03c701c6942 Mon Sep 17 00:00:00 2001 From: shiw Date: Tue, 21 Dec 2021 11:30:44 +0800 Subject: [PATCH 20/33] Fix unused param rwc Signed-off-by: shiw --- bfe_server/http_server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bfe_server/http_server.go b/bfe_server/http_server.go index 0cf08ddb1..ffd5052cb 100644 --- a/bfe_server/http_server.go +++ b/bfe_server/http_server.go @@ -100,7 +100,7 @@ func (srv *BfeServer) Serve(l net.Listener, raw net.Listener, proto string) erro // start go-routine for new connection go func(rwc net.Conn, srv *BfeServer) { // create data structure for new connection - c, err := newConn(rw, srv) + c, err := newConn(rwc, srv) if err != nil { // current, here is unreachable return From 412a746e4884d2f5252e757638ded39b5191fc6e Mon Sep 17 00:00:00 2001 From: clarinette9 Date: Wed, 22 Dec 2021 19:06:28 +0800 Subject: [PATCH 21/33] improve README.md Signed-off-by: clarinette9 --- docs/images/cncf-logo.png | Bin 0 -> 4678 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/images/cncf-logo.png diff --git a/docs/images/cncf-logo.png b/docs/images/cncf-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..fc25a46607b53b29780ed84734ab7985c44e826f GIT binary patch literal 4678 zcmcInc{J32+a4iX8cWtN29cdoKa#PVA^TQJ$k-ywShCGnLP*Tmm#j0ENl^(+h-4f4 zo~#jBvke&<^vv(^oX&gR^ZxNW&pGco_qosYxxV*(-Ph;)J>Ng>cvE92D>FYc003as zhv}FD05m`rul7Gj-`3Cnh1&l| z%O6YsP@L-gpO~l0QbWrF@7wl|Zb~iwBYOfg-O7Ah$NrEf_Nd1b<^=pFxBXp44d?Ps zYWDd!@*n=+NAP6tBkNKOU&#{s{g7)|duri+y3MA*#y0sFjNS zJI9T}s&su`__dD(4@{j{rSjg5!_-++pH6t9OGOuzr|v zp!3V$ElndQL#dc*FL-E*dS9vt^+Q~@!&1j--Y?T|Eq|vO}Qs|hUspKZ1(ZhQSpW|`*Wy15bK$3)2AP9%q+EZP?AYZmoA#^_8T6H z#Yge}1$Ftcw!b28Z=$~g7FZr|?CRM%`X*lO^)hTFc6!8wsD2|HtG$JN)YUb{DKqQ0 zha%s;c@J^vLsq>`LMsm2<*3l5N{%AXa_l73k=9qjJ|;|F@0pyK+dSQyDOs2U0Gwsk z*U_{Lnpn?q4Z1TH-0_=^mJPu4h*kjHj45qZ6ZYb;ot=@1ZIu;Ifjtq87c;=>ys4Fe zN?S{-R<5<;lBPqP%Jg$apO)&^k!M25veVPzc`BP~3ptN4F|`TFku2D7E)%;UpUZ>H^c;XlXFyl0PPHdr8sz-zycYd{A} zM{KW-7EBIf=VmEB_FJcMXlU5S<#~p1;_|$avWAttwT)-kSkS4g$KASnSWbmu#HEVb ztKos?H1($UN}kMWZr2G$ym~|IdoYqmh@(}SI(M@IIJ#V0j~3N|59UzLD&=lOmQg0{hT<*Q2fRBr&Ht_)4~|UU{QLC*;(|)m_p{~V)!VLRO#o?t9mmdO-kg;GpXoFCuMkQTo;=Y zhAzWJA=F8PN!jp`P7e>;AQx=)Ksxs{cPG(+4&;3}KxVf4wFP>Emax0ta@hOz_xBrz zE3pu^jTR&Ep@?WF5vk~;R3%%v1b^-)@uC<@4l_;)3@p0xQxBxyD)2}T#BNhWFg5P! zjN1mIZgGI&MIe5}5IczoyGxa)2zAakNg|PRk`3D0sQqLGkX36?DGxtSs6HFd20SLK zbT8n}sDh%J8S0E2VJE4Y9nMNdcnD9$GKcgd6~c=rZX9Tx&sFyaSsVuJf_Gu+bSpUF zJKv^qpUlo5nO<*{SKbkLdWg&duFJh$Z5G%p1xFwFfCq|=q`r-0sl+1S`#9<%{7}$7*)?0lUo=cZ)YIz1c z)dA*EF1jcZshR^EEvEspk3Oap-kXlK(+s9rV)i2$sV&c6Vp=SeA{$D9I?0RLOe#AM zlt9A*pGF6m$jSZS6%CAy$ZFz-cK@_M2V9pWDm(bh3gou3 zw3C~sOcUF5ME#uVZo;_xjd+!1m%6$6dIxC*fx3_L-e(nP|i`gMQ4>9b!k z%No)Te7lQaO|i&L1^#-C01dkBnML2{NOMqKz-7b3Sz)swkFgX$U}Sfdi6JX_kdd?L zxZu&N-=})C^23i0)LoWs7l_Kksz7dNXvo?Shcrk zt?Y0&r1mey@xo*JFED?wHu4<@k^2++pa!*A7_%Z z(bBBxU$3E7-qq2Q7?#L+H7jV=KI`ZxP~_>Fe4`BKOY3jFjBj*qS4*vW>uj;R@*h|c zlZ$)e=v4rgc+~(TKG8jen!yxY8v-6Lx_Hh*H&^`(d+NglprN6 z##Oh8aySixI9zaPwOGASs&lX`=jLo{49II;SX?UO9A2b-E3RI%$niF!5NP7%wIYiG z2yM{v)Rh27$GLy-LVbD%QM+vOZ}^b8y;cO0$bQgH!r^9z!#6pPU)x{XLO-Dv(vli+Ce#hFCx%Gq%cw;)<@BoVUR^nDe!PUKvhKId5cP6Vmu#-5TY z6(|Ib1Zf&0=tpe{mN5dj&r#=4rGb6ktMioYH1UNHI`FFoivCKAVYt1`N?hA$>0&pN z&C0fBh85#k<%)`#w|v#wYhUgw!71bD?C9#<{dm@kmn6PP z7+~IB;Z{emf;n8m+KVQP-zf|_R}r4$rQ6QjiTHRGQV`C@KenT8aejdFa>D;f}whm5KEm z_8`LXG7r1l!ZB$(JKQOZg&(b+$f#vE`~=BNrf(v7_mmawlQQj4KS#?PzTNoUq8r9U zrk6jI-a%Y!tdb8RDe@j9{$3O*_=sw5{`sbZFo{agCr#Eou7#gu%`AW+)FH;R5_hod1 zBakM=u}n(xR<>8U3^M@sMR~kgqE&^0a1BKWJ`zIQRdVTQlkH{I_-5}z%aI#NwgmK65Pjlm61B>iYB1!#OKOpL?XCW+J(9>XtLFSSxQ< zJ5$muWaWIdL=$bTUtCc!c{bxMTX8$C-1PE|XXXx~Pe%DY&s&{xPD`cfv=++87J1&$5ISR)AzQfqWp<9v4r7{hYk*3NQDa1c z_@VE*HyY)$Civd>K&_w_FnJ~&{48U`~GEqQzGp5qG_BRHV z0I{wPuE~(XnOG+SX1VSw&roR|FRDC;I$lp@Jg0wm<#NIh=K`|M@Ib>zdhDguI_ciy z7aNhPSaiXo_zQPN!e{Dk5Kv7 zdZfW%bHWyT4bCDgl`lS?ud5@jdvx7MmwEkk*-IS32z6-wYs)Kem^-8d%`v{QE09!u z{whm_z?PZ12sSfYlwadI>(7+7Kou++9k%7!b4UG%^0foG%@c$Et-d1>-VO@eLNOp^ zFeNI*i!Uwxo`%Grlgpjzbd>%QLj_$@2^Vk#spO!meL&VD=4x?39Hg%$Ji#k?MY(P{ z1*Flmfm`2NX)SjL%ka44D)?{SH#L}qgJNTJ6QIAcGE~>CZF#|+OmBhUS{_44&1WBE zVKPxSKlB(i0D|tBUDg!!W8x(^vW_gIyc5J%UNBfdUZV#l3*H}sBKwQXn$8heiaEGq zC@^!?KIy60&!1_f>(Fq<$K+YD0eF!ir1wr_v?2dM`-Q9;7cwQ?zY+ti^1p}|Eq{y+m(-?;D0g(Tt zj`JOzB{_a1{&=t9_Wr~$_t@R+57RmlX=pptlGM8@!`w{<<6FxQCS(T1zd+N)pGl2F zJ-o9M@SJ=?U3CfyKKHWfUW`L4c9YklaEZ%E=S%Y9e&O{@NK4cQD!h0;dH+5uX_Xtn0TVZxriCK(>O;@*22huc(0fyMrcNm%9hGm9*UaRHd0K3&r)`Wyk34YwJ85wC$3gNc4WJv7Z zcxKxxL>JHEcl&3o1 v>$e#*`$E&{X~7awn(Mpp$uhRzx6N7!e(`K;(V&#N3 Date: Wed, 22 Dec 2021 19:08:00 +0800 Subject: [PATCH 22/33] improve README.md Signed-off-by: clarinette9 --- README-CN.md | 9 ++++++--- README.md | 18 +++++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/README-CN.md b/README-CN.md index aa5d7adca..3b21d7807 100644 --- a/README-CN.md +++ b/README-CN.md @@ -6,13 +6,16 @@ [![Travis](https://img.shields.io/travis/com/bfenetworks/bfe)](https://travis-ci.com/bfenetworks/bfe) [![Go Report Card](https://goreportcard.com/badge/github.com/bfenetworks/bfe)](https://goreportcard.com/report/github.com/bfenetworks/bfe) [![GoDoc](https://godoc.org/github.com/bfenetworks/bfe?status.svg)](https://godoc.org/github.com/bfenetworks/bfe/bfe_module) -[![Snap Status](https://build.snapcraft.io/badge/bfenetworks/bfe.svg)](https://build.snapcraft.io/user/bfenetworks/bfe) +[![Snap Status](https://snapcraft.io/bfe/badge.svg)](https://snapcraft.io/bfe) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/3209/badge)](https://bestpractices.coreinfrastructure.org/projects/3209) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fbfenetworks%2Fbfe.svg?type=shield)](https://app.fossa.com/reports/1f05f9f0-ac3d-486e-8ba9-ad95dabd4768) [![Slack Widget](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=green)](https://slack.cncf.io) BFE (Beyond Front End) 是百度开源的现代化、企业级的七层负载均衡系统 -![bfe logo](./docs/images/logo/horizontal/color/bfe-horizontal-color.png) + +bfe logo + + ## 简介 @@ -83,7 +86,7 @@ BFE的架构说明见[概览](docs/zh_cn/introduction/overview.md)文档 - +
diff --git a/README.md b/README.md index 2ec9fc257..40146dd9d 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,27 @@ -# BFE - -English | [中文](README-CN.md) +bfe logo +------ [![GitHub](https://img.shields.io/github/license/bfenetworks/bfe)](https://github.com/bfenetworks/bfe/blob/develop/LICENSE) [![Travis](https://img.shields.io/travis/com/bfenetworks/bfe)](https://travis-ci.com/bfenetworks/bfe) [![Go Report Card](https://goreportcard.com/badge/github.com/bfenetworks/bfe)](https://goreportcard.com/report/github.com/bfenetworks/bfe) [![GoDoc](https://godoc.org/github.com/bfenetworks/bfe?status.svg)](https://godoc.org/github.com/bfenetworks/bfe/bfe_module) -[![Snap Status](https://build.snapcraft.io/badge/bfenetworks/bfe.svg)](https://build.snapcraft.io/user/bfenetworks/bfe) +[![Snap Status](https://snapcraft.io/bfe/badge.svg)](https://snapcraft.io/bfe) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/3209/badge)](https://bestpractices.coreinfrastructure.org/projects/3209) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fbfenetworks%2Fbfe.svg?type=shield)](https://app.fossa.com/reports/1f05f9f0-ac3d-486e-8ba9-ad95dabd4768) [![Slack Widget](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=green)](https://slack.cncf.io) +English | [中文](README-CN.md) + +------ + BFE (Beyond Front End) is a modern layer 7 load balancer from baidu. -![bfe logo](./docs/images/logo/horizontal/color/bfe-horizontal-color.png) + +BFE is a sandbox project of the [Cloud Native Computing Foundation](https://cncf.io/) (CNCF). + +![](./docs/images/cncf-logo.png) + + ## Introduction From 9a22cf9dfbabed142d4e3ea8342356a12cf17133 Mon Sep 17 00:00:00 2001 From: clarinette9 Date: Wed, 22 Dec 2021 19:14:36 +0800 Subject: [PATCH 23/33] improve README.md Signed-off-by: clarinette9 --- README-CN.md | 12 +++++++++--- README.md | 8 ++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/README-CN.md b/README-CN.md index 3b21d7807..08af0624a 100644 --- a/README-CN.md +++ b/README-CN.md @@ -1,7 +1,5 @@ # BFE -[English](README.md) | 中文 - [![GitHub](https://img.shields.io/github/license/bfenetworks/bfe)](https://github.com/bfenetworks/bfe/blob/develop/LICENSE) [![Travis](https://img.shields.io/travis/com/bfenetworks/bfe)](https://travis-ci.com/bfenetworks/bfe) [![Go Report Card](https://goreportcard.com/badge/github.com/bfenetworks/bfe)](https://goreportcard.com/report/github.com/bfenetworks/bfe) @@ -11,9 +9,17 @@ [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fbfenetworks%2Fbfe.svg?type=shield)](https://app.fossa.com/reports/1f05f9f0-ac3d-486e-8ba9-ad95dabd4768) [![Slack Widget](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=green)](https://slack.cncf.io) +[English](README.md) | 中文 + + + BFE (Beyond Front End) 是百度开源的现代化、企业级的七层负载均衡系统 -bfe logo +bfe logo + +BFE is a sandbox project of the [Cloud Native Computing Foundation](https://cncf.io/) (CNCF). + +![](./docs/images/cncf-logo.png) diff --git a/README.md b/README.md index 40146dd9d..a03778b4b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -bfe logo - ------- +# BFE [![GitHub](https://img.shields.io/github/license/bfenetworks/bfe)](https://github.com/bfenetworks/bfe/blob/develop/LICENSE) [![Travis](https://img.shields.io/travis/com/bfenetworks/bfe)](https://travis-ci.com/bfenetworks/bfe) @@ -13,10 +11,12 @@ English | [中文](README-CN.md) ------- + BFE (Beyond Front End) is a modern layer 7 load balancer from baidu. +bfe logo + BFE is a sandbox project of the [Cloud Native Computing Foundation](https://cncf.io/) (CNCF). ![](./docs/images/cncf-logo.png) From 862473372f89e3205dac515cd85ba2a838cf2378 Mon Sep 17 00:00:00 2001 From: clarinette9 Date: Wed, 22 Dec 2021 19:22:02 +0800 Subject: [PATCH 24/33] improve README.md Signed-off-by: clarinette9 --- README-CN.md | 3 +-- README.md | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README-CN.md b/README-CN.md index 08af0624a..24f55429d 100644 --- a/README-CN.md +++ b/README-CN.md @@ -17,8 +17,7 @@ BFE (Beyond Front End) 是百度开源的现代化、企业级的七层负载均 bfe logo -BFE is a sandbox project of the [Cloud Native Computing Foundation](https://cncf.io/) (CNCF). - +BFE is a [Cloud Native Computing Foundation](https://cncf.io/) (CNCF) sandbox project. ![](./docs/images/cncf-logo.png) diff --git a/README.md b/README.md index a03778b4b..2db3c4f76 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,7 @@ BFE (Beyond Front End) is a modern layer 7 load balancer from baidu. bfe logo -BFE is a sandbox project of the [Cloud Native Computing Foundation](https://cncf.io/) (CNCF). - +BFE is a [Cloud Native Computing Foundation](https://cncf.io/) (CNCF) sandbox project. ![](./docs/images/cncf-logo.png) From b572d1c27b4985687bbbc360a373651c3601d492 Mon Sep 17 00:00:00 2001 From: clarinette9 Date: Wed, 22 Dec 2021 19:23:13 +0800 Subject: [PATCH 25/33] improve README.md Signed-off-by: clarinette9 --- README-CN.md | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README-CN.md b/README-CN.md index 24f55429d..84e2b108c 100644 --- a/README-CN.md +++ b/README-CN.md @@ -18,6 +18,7 @@ BFE (Beyond Front End) 是百度开源的现代化、企业级的七层负载均 bfe logo BFE is a [Cloud Native Computing Foundation](https://cncf.io/) (CNCF) sandbox project. + ![](./docs/images/cncf-logo.png) diff --git a/README.md b/README.md index 2db3c4f76..a21980357 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ BFE (Beyond Front End) is a modern layer 7 load balancer from baidu. bfe logo BFE is a [Cloud Native Computing Foundation](https://cncf.io/) (CNCF) sandbox project. + ![](./docs/images/cncf-logo.png) From 88f22ff907e224e9dc4b10b305cd4cb894e77604 Mon Sep 17 00:00:00 2001 From: clarinette9 Date: Wed, 22 Dec 2021 19:32:29 +0800 Subject: [PATCH 26/33] improve README.md Signed-off-by: clarinette9 --- README-CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-CN.md b/README-CN.md index 84e2b108c..936997e1d 100644 --- a/README-CN.md +++ b/README-CN.md @@ -17,7 +17,7 @@ BFE (Beyond Front End) 是百度开源的现代化、企业级的七层负载均 bfe logo -BFE is a [Cloud Native Computing Foundation](https://cncf.io/) (CNCF) sandbox project. +BFE 是 [云原生计算基金会 (Cloud Native Computing Foundation, CNCF)](https://cncf.io/) 的一个沙箱项目 ![](./docs/images/cncf-logo.png) From 3d12ee858f7e4f167dcae7dd6ff90c68f0bc8939 Mon Sep 17 00:00:00 2001 From: clarinette9 Date: Fri, 24 Dec 2021 16:06:16 +0800 Subject: [PATCH 27/33] Docs: change required golang version to 1.15 for install from source and go Signed-off-by: clarinette9 --- docs/en_us/faq/installation.md | 2 +- docs/en_us/installation/install_from_source.md | 2 +- docs/en_us/installation/install_using_go.md | 2 +- docs/zh_cn/faq/installation.md | 2 +- docs/zh_cn/installation/install_from_source.md | 2 +- docs/zh_cn/installation/install_using_go.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/en_us/faq/installation.md b/docs/en_us/faq/installation.md index 2e5110d43..735bd5fdf 100644 --- a/docs/en_us/faq/installation.md +++ b/docs/en_us/faq/installation.md @@ -1,7 +1,7 @@ # Installation FAQ ## Go get timeout during installation -- Set GOPROXY enviroment variable as follows (go1.13+): +- Set GOPROXY enviroment variable as follows (go1.15+): ```bash $ go env -w GO111MODULE=on $ go env -w GOPROXY=https://goproxy.cn,direct diff --git a/docs/en_us/installation/install_from_source.md b/docs/en_us/installation/install_from_source.md index 6112b97a9..e29271890 100644 --- a/docs/en_us/installation/install_from_source.md +++ b/docs/en_us/installation/install_from_source.md @@ -1,7 +1,7 @@ # Install from source code ## Prerequisites -- golang 1.13+ +- golang 1.15+ - git 2.0+ - glibc-static 2.17+ diff --git a/docs/en_us/installation/install_using_go.md b/docs/en_us/installation/install_using_go.md index 3409a359d..f0699625e 100644 --- a/docs/en_us/installation/install_using_go.md +++ b/docs/en_us/installation/install_using_go.md @@ -1,7 +1,7 @@ # Install using go ## Prerequisites -- golang 1.13+ +- golang 1.15+ ## Installation - Get the source code and install diff --git a/docs/zh_cn/faq/installation.md b/docs/zh_cn/faq/installation.md index 8eb65dc29..12cc0dc9d 100644 --- a/docs/zh_cn/faq/installation.md +++ b/docs/zh_cn/faq/installation.md @@ -1,7 +1,7 @@ # 安装常见问题 ## 安装时遇到go get超时错误 -- 设置GOPROXY环境变量(go1.13及以上版本) +- 设置GOPROXY环境变量(go1.15及以上版本) ```bash $ go env -w GO111MODULE=on $ go env -w GOPROXY=https://goproxy.cn,direct diff --git a/docs/zh_cn/installation/install_from_source.md b/docs/zh_cn/installation/install_from_source.md index 5054a6ced..c2b30ec4d 100644 --- a/docs/zh_cn/installation/install_from_source.md +++ b/docs/zh_cn/installation/install_from_source.md @@ -1,7 +1,7 @@ # 源码编译安装 ## 环境准备 -- golang 1.13+ +- golang 1.15+ - git 2.0+ - glibc-static 2.17+ diff --git a/docs/zh_cn/installation/install_using_go.md b/docs/zh_cn/installation/install_using_go.md index f50c7619e..df3266c8d 100644 --- a/docs/zh_cn/installation/install_using_go.md +++ b/docs/zh_cn/installation/install_using_go.md @@ -1,7 +1,7 @@ # go方式安装 ## 环境准备 -* golang 1.13+ +* golang 1.15+ ## 安装 - 获取并安装 From 3d399e4d50752fe939490efcd40df7f6490ec086 Mon Sep 17 00:00:00 2001 From: halst Date: Wed, 5 Jan 2022 13:24:30 +0800 Subject: [PATCH 28/33] Use json-iterator in mod_tcp_keepalive (#931) Signed-off-by: liu-song --- bfe_modules/mod_tcp_keepalive/data_load.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bfe_modules/mod_tcp_keepalive/data_load.go b/bfe_modules/mod_tcp_keepalive/data_load.go index 59ad8267f..0fda25a1d 100644 --- a/bfe_modules/mod_tcp_keepalive/data_load.go +++ b/bfe_modules/mod_tcp_keepalive/data_load.go @@ -15,13 +15,16 @@ package mod_tcp_keepalive import ( - "encoding/json" "errors" "fmt" "net" "os" ) +import ( + "github.com/bfenetworks/bfe/bfe_util/json" +) + /* { "Version": "x", From ed73a2a94ae1790a6386bd7a2d8544b5ce39958b Mon Sep 17 00:00:00 2001 From: halst Date: Wed, 5 Jan 2022 15:08:27 +0800 Subject: [PATCH 29/33] Use json-iterator instead of encoding/json (#932) Signed-off-by: liu-song --- bfe_basic/condition/parser/parser_test.go | 5 ++++- bfe_http/cookie_test.go | 5 ++++- bfe_modules/mod_prison/rule_test.go | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bfe_basic/condition/parser/parser_test.go b/bfe_basic/condition/parser/parser_test.go index c7cedecdc..cb815e2ce 100644 --- a/bfe_basic/condition/parser/parser_test.go +++ b/bfe_basic/condition/parser/parser_test.go @@ -15,10 +15,13 @@ package parser import ( - "encoding/json" "testing" ) +import ( + "github.com/bfenetworks/bfe/bfe_util/json" +) + func TestParserParse(t *testing.T) { testCases := []struct { condStr string diff --git a/bfe_http/cookie_test.go b/bfe_http/cookie_test.go index 077c8949e..3b26fbab2 100644 --- a/bfe_http/cookie_test.go +++ b/bfe_http/cookie_test.go @@ -19,13 +19,16 @@ package bfe_http import ( - "encoding/json" "fmt" "reflect" "testing" "time" ) +import ( + "github.com/bfenetworks/bfe/bfe_util/json" +) + var writeSetCookiesTests = []struct { Cookie *Cookie Raw string diff --git a/bfe_modules/mod_prison/rule_test.go b/bfe_modules/mod_prison/rule_test.go index b4a42118e..0e9473388 100644 --- a/bfe_modules/mod_prison/rule_test.go +++ b/bfe_modules/mod_prison/rule_test.go @@ -16,7 +16,6 @@ package mod_prison import ( "crypto/md5" - "encoding/json" "testing" "time" ) @@ -27,6 +26,7 @@ import ( import ( "github.com/bfenetworks/bfe/bfe_basic" + "github.com/bfenetworks/bfe/bfe_util/json" ) func newPrisonRuleConfTest() (*PrisonRuleConf, error) { From 68b570b9c4774d0cf5271947e385509f805bfd24 Mon Sep 17 00:00:00 2001 From: wolfCoder Date: Wed, 5 Jan 2022 19:58:47 +0800 Subject: [PATCH 30/33] Update go.mod and fix build error (#933) Signed-off-by: chenchen.ccqy66 --- go.mod | 7 +++---- go.sum | 21 ++++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 29b04262b..fcae9fbdf 100644 --- a/go.mod +++ b/go.mod @@ -32,9 +32,9 @@ require ( go.uber.org/atomic v1.6.0 // indirect go.uber.org/automaxprocs v1.4.0 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 - golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d - golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e - golang.org/x/tools v0.1.7 // indirect + golang.org/x/net v0.0.0-20211216030914-fe4d6282115f + golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e + golang.org/x/tools v0.1.8 // indirect gopkg.in/gcfg.v1 v1.2.3 gopkg.in/square/go-jose.v2 v2.4.1 gopkg.in/warnings.v0 v0.1.2 // indirect @@ -58,7 +58,6 @@ require ( go.elastic.co/apm/module/apmhttp v1.7.2 // indirect go.elastic.co/fastjson v1.1.0 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/text v0.3.6 // indirect google.golang.org/grpc v1.22.1 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect diff --git a/go.sum b/go.sum index 862322360..143ea1ad1 100644 --- a/go.sum +++ b/go.sum @@ -123,7 +123,7 @@ github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMW github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zmap/go-iptree v0.0.0-20170831022036-1948b1097e25 h1:LRoXAcKX48QV4LV23W5ZtsG/MbJOgNUNvWiXwM0iLWw= github.com/zmap/go-iptree v0.0.0-20170831022036-1948b1097e25/go.mod h1:qOasALtPByO1Jk6LhgpNv6htPMK2QJfiGorUk57nO/U= go.elastic.co/apm v1.7.2/go.mod h1:tCw6CkOJgkWnzEthFN9HUP1uL3Gjc/Ur6m7gRPLaoH0= @@ -150,7 +150,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -159,8 +159,9 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -178,13 +179,15 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/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-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -192,8 +195,8 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= +golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= From 36af9a49ea12e21d5cf9867ec7573b7104fc485d Mon Sep 17 00:00:00 2001 From: Dai Ming Date: Sat, 8 Jan 2022 19:40:24 +0800 Subject: [PATCH 31/33] fix some http security issues (#921) Signed-off-by: daiming --- bfe_http/transfer.go | 68 ++++++++++++++++++++++++---- bfe_server/chunk_writer.go | 6 ++- bfe_server/expect_continue_reader.go | 53 +++++++++++----------- bfe_server/http_conn.go | 1 + bfe_server/response.go | 28 ++++++++++++ 5 files changed, 121 insertions(+), 35 deletions(-) diff --git a/bfe_http/transfer.go b/bfe_http/transfer.go index 2f5f1c883..e02d91e3b 100644 --- a/bfe_http/transfer.go +++ b/bfe_http/transfer.go @@ -145,6 +145,9 @@ func (t *transferWriter) shouldSendContentLength() bool { // contentLength is 0, but have Content-Length in origin header // Some backends expect a Content-Length header if t.ContentLength == 0 && t.Header.Get("Content-Length") != "" { + if t.Method == "GET" || t.Method == "HEAD" { + return false + } return true } @@ -291,6 +294,7 @@ func readTransfer(msg interface{}, r *bfe_bufio.Reader) (err error) { } case *Request: t.Header = rr.Header + t.RequestMethod = rr.Method t.ProtoMajor = rr.ProtoMajor t.ProtoMinor = rr.ProtoMinor // Transfer semantics for Requests are exactly like those for @@ -306,7 +310,7 @@ func readTransfer(msg interface{}, r *bfe_bufio.Reader) (err error) { } // Transfer encoding, content length - t.TransferEncoding, err = fixTransferEncoding(t.RequestMethod, t.Header) + t.TransferEncoding, err = fixTransferEncoding(isResponse, t.RequestMethod, t.Header) if err != nil { return err } @@ -395,7 +399,7 @@ func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" } func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" } // Sanitize transfer encoding -func fixTransferEncoding(requestMethod string, header Header) ([]string, error) { +func fixTransferEncoding(isResponse bool, requestMethod string, header Header) ([]string, error) { raw, present := header["Transfer-Encoding"] if !present { return nil, nil @@ -425,9 +429,22 @@ func fixTransferEncoding(requestMethod string, header Header) ([]string, error) return nil, &badStringError{"too many transfer encodings", strings.Join(te, ",")} } if len(te) > 0 { - // Chunked encoding trumps Content-Length. See RFC 2616 - // Section 4.4. Currently len(te) > 0 implies chunked - // encoding. + // RFC 7230 3.3.2 says "A sender MUST NOT send a + // Content-Length header field in any message that + // contains a Transfer-Encoding header field." + // + // but also: + // "If a message is received with both a + // Transfer-Encoding and a Content-Length header + // field, the Transfer-Encoding overrides the + // Content-Length. Such a message might indicate an + // attempt to perform request smuggling (Section 9.5) + // or response splitting (Section 9.4) and ought to be + // handled as an error. A sender MUST remove the + // received Content-Length field prior to forwarding + // such a message downstream." + // + // Reportedly, these appear in the wild. delete(header, "Content-Length") return te, nil } @@ -439,9 +456,38 @@ func fixTransferEncoding(requestMethod string, header Header) ([]string, error) // function is not a method, because ultimately it should be shared by // ReadResponse and ReadRequest. func fixLength(isResponse bool, status int, requestMethod string, header Header, te []string) (int64, error) { + isRequest := !isResponse + contentLens := header["Content-Length"] + + // Hardening against HTTP request smuggling + if len(contentLens) > 1 { + // Per RFC 7230 Section 3.3.2, prevent multiple + // Content-Length headers if they differ in value. + // If there are dups of the value, remove the dups. + // See Issue 16490. + first := textproto.TrimString(contentLens[0]) + for _, ct := range contentLens[1:] { + if first != textproto.TrimString(ct) { + return 0, fmt.Errorf("http: message cannot contain multiple Content-Length headers; got %q", contentLens) + } + } + + // deduplicate Content-Length + header.Del("Content-Length") + header.Add("Content-Length", first) + + contentLens = header["Content-Length"] + } // Logic based on response type or status if noBodyExpected(requestMethod) { + // For HTTP requests, as part of hardening against request + // smuggling (RFC 7230), don't allow a Content-Length header for + // methods which don't permit bodies. As an exception, allow + // exactly one Content-Length header if its value is "0". + if isRequest && len(contentLens) > 0 && !(len(contentLens) == 1 && contentLens[0] == "0") { + return 0, fmt.Errorf("http: method cannot contain a Content-Length; got %q", contentLens) + } return 0, nil } if status/100 == 1 { @@ -458,7 +504,10 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header, } // Logic based on Content-Length - cl := strings.TrimSpace(header.GetDirect("Content-Length")) + var cl string + if len(contentLens) == 1 { + cl = textproto.TrimString(contentLens[0]) + } if cl != "" { n, err := parseContentLength(cl) if err != nil { @@ -469,11 +518,14 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header, header.Del("Content-Length") } - if !isResponse && requestMethod == MethodGet { - // RFC 2616 doesn't explicitly permit nor forbid an + if !isResponse { + // RFC 2616 neither explicitly permits nor forbids an // entity-body on a GET request so we permit one if // declared, but we default to 0 here (not -1 below) // if there's no mention of a body. + // Likewise, all other request methods are assumed to have + // no body if neither Transfer-Encoding chunked nor a + // Content-Length are set. return 0, nil } diff --git a/bfe_server/chunk_writer.go b/bfe_server/chunk_writer.go index aca07bd61..e74946933 100644 --- a/bfe_server/chunk_writer.go +++ b/bfe_server/chunk_writer.go @@ -33,7 +33,7 @@ import ( "github.com/baidu/go-lib/log" ) -import ( +import ( "github.com/bfenetworks/bfe/bfe_bufio" "github.com/bfenetworks/bfe/bfe_http" ) @@ -344,6 +344,10 @@ func (cw *chunkWriter) writeHeader(p []byte) { w.closeAfterReply = true } + if ecr, ok := w.req.Body.(*expectContinueReader); ok && !ecr.sawEOF.isSet() { + w.closeAfterReply = true + } + // Per RFC 2616, we should consume the request body before // replying, if the handler hasn't already done so. But we // don't want to do an unbounded amount of reading here for diff --git a/bfe_server/expect_continue_reader.go b/bfe_server/expect_continue_reader.go index a79d7992e..8205accdc 100644 --- a/bfe_server/expect_continue_reader.go +++ b/bfe_server/expect_continue_reader.go @@ -23,7 +23,6 @@ package bfe_server import ( "errors" "io" - "sync" ) import ( @@ -35,35 +34,40 @@ import ( type expectContinueReader struct { resp *response readCloser io.ReadCloser - closed bool - mu sync.Mutex + closed atomicBool + sawEOF atomicBool } func (ecr *expectContinueReader) tryWriteContinue() { - if !ecr.resp.wroteContinue { - ecr.resp.wroteContinue = true - ecr.resp.conn.buf.WriteString("HTTP/1.1 100 Continue\r\n\r\n") - ecr.resp.conn.buf.Flush() + w := ecr.resp + + if !w.wroteContinue && w.canWriteContinue.isSet() { + w.wroteContinue = true + w.writeContinueMu.Lock() + if w.canWriteContinue.isSet() { + ecr.resp.conn.buf.WriteString("HTTP/1.1 100 Continue\r\n\r\n") + ecr.resp.conn.buf.Flush() + w.canWriteContinue.setFalse() + } + w.writeContinueMu.Unlock() } } func (ecr *expectContinueReader) Read(p []byte) (n int, err error) { - ecr.mu.Lock() - defer ecr.mu.Unlock() - - if ecr.closed { + if ecr.closed.isSet() { return 0, bfe_http.ErrBodyReadAfterClose } ecr.tryWriteContinue() - return ecr.readCloser.Read(p) + n, err = ecr.readCloser.Read(p) + if err == io.EOF { + ecr.sawEOF.setTrue() + } + return } func (ecr *expectContinueReader) Close() error { - ecr.mu.Lock() - defer ecr.mu.Unlock() - - ecr.closed = true + ecr.closed.setTrue() return ecr.readCloser.Close() } @@ -71,26 +75,23 @@ var ErrExpectContinueReaderPeek = errors.New("http: expect continue reader peek // add peek function which is used by access log module func (ecr *expectContinueReader) Peek(n int) ([]byte, error) { - ecr.mu.Lock() - defer ecr.mu.Unlock() - - if ecr.closed { + if ecr.closed.isSet() { return nil, bfe_http.ErrBodyReadAfterClose } // Ensure that "100-continue" has been written before peeking ecr.tryWriteContinue() if p, ok := ecr.readCloser.(bfe_http.Peeker); ok { - return p.Peek(n) + n, err := p.Peek(n) + if err == io.EOF { + ecr.sawEOF.setTrue() + } + return n, err } return nil, ErrExpectContinueReaderPeek } // check whether expectContinueReader has sent 100-Continue response func (ecr *expectContinueReader) WroteContinue() bool { - ecr.mu.Lock() - wroteContinue := ecr.resp.wroteContinue - ecr.mu.Unlock() - - return wroteContinue + return ecr.resp.wroteContinue } diff --git a/bfe_server/http_conn.go b/bfe_server/http_conn.go index e81732fe8..32cf03176 100644 --- a/bfe_server/http_conn.go +++ b/bfe_server/http_conn.go @@ -451,6 +451,7 @@ func (c *conn) serve() { if req.ProtoAtLeast(1, 1) { // Wrap the Body reader with one that replies on the connection req.Body = &expectContinueReader{readCloser: req.Body, resp: w} + w.canWriteContinue.setTrue() } if req.ContentLength == 0 { session.SetError(bfe_basic.ErrClientZeroContentlen, "content length is zero") diff --git a/bfe_server/response.go b/bfe_server/response.go index 5067b1ec2..38899b5b0 100644 --- a/bfe_server/response.go +++ b/bfe_server/response.go @@ -26,6 +26,8 @@ import ( "net" "os" "strconv" + "sync" + "sync/atomic" "time" ) @@ -66,6 +68,12 @@ type switchWriter struct { io.Writer } +type atomicBool int32 + +func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 } +func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) } +func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) } + // A response represents the server side of an HTTP response. type response struct { conn *conn @@ -73,6 +81,16 @@ type response struct { wroteHeader bool // reply header has been (logically) written wroteContinue bool // 100 Continue response was written + // canWriteContinue is a boolean value accessed as an atomic int32 + // that says whether or not a 100 Continue header can be written + // to the connection. + // writeContinueMu must be held while writing the header. + // These two fields together synchronize the body reader + // (the expectContinueReader, which wants to write 100 Continue) + // against the main writer. + canWriteContinue atomicBool + writeContinueMu sync.Mutex + w *bfe_bufio.Writer // buffers output in chunks to chunkWriter cw chunkWriter sw *switchWriter // of the bufio.Writer, for return to putBufioWriter @@ -307,6 +325,16 @@ func (w *response) WriteString(data string) (n int, err error) { // either dataB or dataS is non-zero. func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) { + if w.canWriteContinue.isSet() { + // Body reader wants to write 100 Continue but hasn't yet. + // Tell it not to. The store must be done while holding the lock + // because the lock makes sure that there is not an active write + // this very moment. + w.writeContinueMu.Lock() + w.canWriteContinue.setFalse() + w.writeContinueMu.Unlock() + } + if !w.wroteHeader { w.WriteHeader(bfe_http.StatusOK) } From 984738576458d80bf211ad11a9cf277799dc494d Mon Sep 17 00:00:00 2001 From: clarinette9 Date: Tue, 11 Jan 2022 10:00:55 +0800 Subject: [PATCH 32/33] add v1.5.0 info in CHANGELOG.md and VERSION --- CHANGELOG.md | 19 +++++++++++++++++-- VERSION | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5ba3f1c4..1a615616a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,14 +10,29 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [v1.4.0] - 2021-12-10 +## [v1.5.0] - 2022-01-11 ### Added - +- Add mod_tcp_keepalive to support custom TCP KeepAlive configuration - Documents optimization ### Changed +- Change JSON parser: use json-iterator to replace encoding/json +- Optimize error handling in io.Write + +### Fixed +- Fix issue in go.mod which may cause build error (Issue #933) + +### Security +- Fix http security issue (Issue #940) +- Fix http security issue (Issue #941) +## [v1.4.0] - 2021-12-10 + +### Added +- Documents optimization + +### Changed - Upgrade golang version from 1.13 to 1.17 - mod_markdown: upgrade bluemonday version to 1.0.16 - Optimize mutex diff --git a/VERSION b/VERSION index 88c5fb891..bc80560fa 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.4.0 +1.5.0 From 8b3771a60b5fe4ab9000dcce7bdac4478e6e75d7 Mon Sep 17 00:00:00 2001 From: clarinette9 <83874119+clarinette9@users.noreply.github.com> Date: Tue, 11 Jan 2022 10:14:31 +0800 Subject: [PATCH 33/33] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a615616a..6ac1cf289 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -290,6 +290,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Flexible plugin framework to extend functionality. Based on the framework, developer can add new features rapidly - Detailed built-in metrics available for service status monitor +[v1.5.0]: https://github.com/bfenetworks/bfe/compare/v1.4.0...v1.5.0 [v1.4.0]: https://github.com/bfenetworks/bfe/compare/v1.3.0...v1.4.0 [v1.3.0]: https://github.com/bfenetworks/bfe/compare/v1.2.0...v1.3.0 [v1.2.0]: https://github.com/bfenetworks/bfe/compare/v1.1.0...v1.2.0