Skip to content

Commit

Permalink
Merge pull request #942 from bfenetworks/release/v1.5.0
Browse files Browse the repository at this point in the history
Release/v1.5.0
  • Loading branch information
clarinette9 authored Jan 11, 2022
2 parents 826f6c8 + 28fdf0e commit 3ed1851
Show file tree
Hide file tree
Showing 49 changed files with 1,547 additions and 168 deletions.
24 changes: 19 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -275,10 +290,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.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
>>>>>>> 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
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down
20 changes: 15 additions & 5 deletions README-CN.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
# 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)
[![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是百度开源的现代化、企业级的七层负载均衡系统
[English](README.md) | 中文



BFE (Beyond Front End) 是百度开源的现代化、企业级的七层负载均衡系统

<img src="./docs/images/logo/horizontal/color/bfe-horizontal-color.png" alt="bfe logo" width="300" />

BFE 是 [云原生计算基金会 (Cloud Native Computing Foundation, CNCF)](https://cncf.io/) 的一个沙箱项目

![](./docs/images/cncf-logo.png)



## 简介

Expand Down Expand Up @@ -82,7 +92,7 @@ BFE的架构说明见[概览](docs/zh_cn/introduction/overview.md)文档

<table>
<tr>
<td><img src="https://bfeopensource.bj.bcebos.com/wechatQRCode.png" width="100"></td>
<td><img src="https://raw.githubusercontent.com/clarinette9/bfe-external-resource/main/wechatQRCode.png" width="100"></td>
</tr>
</table>

Expand Down
19 changes: 14 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
# BFE

English | [中文](README-CN.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)
[![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 is a modern layer 7 load balancer from baidu.
English | [中文](README-CN.md)



BFE (Beyond Front End) is a modern layer 7 load balancer from baidu.

<img src="./docs/images/logo/horizontal/color/bfe-horizontal-color.png" alt="bfe logo" width="300" />

BFE is a [Cloud Native Computing Foundation](https://cncf.io/) (CNCF) sandbox project.

![](./docs/images/cncf-logo.png)



## Introduction

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.4.0
1.5.0
5 changes: 4 additions & 1 deletion bfe_basic/condition/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion bfe_http/cookie_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
68 changes: 60 additions & 8 deletions bfe_http/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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
}

Expand Down
4 changes: 4 additions & 0 deletions bfe_modules/bfe_modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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(),

Expand Down
2 changes: 1 addition & 1 deletion bfe_modules/mod_prison/rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package mod_prison

import (
"crypto/md5"
"encoding/json"
"testing"
"time"
)
Expand All @@ -27,6 +26,7 @@ import (

import (
"github.com/bfenetworks/bfe/bfe_basic"
"github.com/bfenetworks/bfe/bfe_util/json"
)

func newPrisonRuleConfTest() (*PrisonRuleConf, error) {
Expand Down
63 changes: 63 additions & 0 deletions bfe_modules/mod_tcp_keepalive/conf_load.go
Original file line number Diff line number Diff line change
@@ -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
}
Loading

0 comments on commit 3ed1851

Please sign in to comment.