feat: add in flight connection middleware
This commit is contained in:
parent
95fabeae73
commit
93de7cf0c0
14 changed files with 326 additions and 4 deletions
63
docs/content/middlewares/tcp/inflightconn.md
Normal file
63
docs/content/middlewares/tcp/inflightconn.md
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# InFlightConn
|
||||||
|
|
||||||
|
Limiting the Number of Simultaneous connections.
|
||||||
|
{: .subtitle }
|
||||||
|
|
||||||
|
To proactively prevent services from being overwhelmed with high load, the number of allowed simultaneous connections by IP can be limited.
|
||||||
|
|
||||||
|
## Configuration Examples
|
||||||
|
|
||||||
|
```yaml tab="Docker"
|
||||||
|
labels:
|
||||||
|
- "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Kubernetes"
|
||||||
|
apiVersion: traefik.containo.us/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: test-inflightconn
|
||||||
|
spec:
|
||||||
|
inFlightConn:
|
||||||
|
amount: 10
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Consul Catalog"
|
||||||
|
# Limiting to 10 simultaneous connections
|
||||||
|
- "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10"
|
||||||
|
```
|
||||||
|
|
||||||
|
```json tab="Marathon"
|
||||||
|
"labels": {
|
||||||
|
"traefik.tcp.middlewares.test-inflightconn.inflightconn.amount": "10"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="Rancher"
|
||||||
|
# Limiting to 10 simultaneous connections.
|
||||||
|
labels:
|
||||||
|
- "traefik.tcp.middlewares.test-inflightconn.inflightconn.amount=10"
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml tab="File (YAML)"
|
||||||
|
# Limiting to 10 simultaneous connections.
|
||||||
|
tcp:
|
||||||
|
middlewares:
|
||||||
|
test-inflightconn:
|
||||||
|
inFlightConn:
|
||||||
|
amount: 10
|
||||||
|
```
|
||||||
|
|
||||||
|
```toml tab="File (TOML)"
|
||||||
|
# Limiting to 10 simultaneous connections
|
||||||
|
[tcp.middlewares]
|
||||||
|
[tcp.middlewares.test-inflightconn.inFlightConn]
|
||||||
|
amount = 10
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
### `amount`
|
||||||
|
|
||||||
|
The `amount` option defines the maximum amount of allowed simultaneous connections.
|
||||||
|
The middleware closes the connection if there are already `amount` connections opened.
|
|
@ -131,4 +131,5 @@ tcp:
|
||||||
|
|
||||||
| Middleware | Purpose | Area |
|
| Middleware | Purpose | Area |
|
||||||
|-------------------------------------------|---------------------------------------------------|-----------------------------|
|
|-------------------------------------------|---------------------------------------------------|-----------------------------|
|
||||||
| [IPWhiteList](ipwhitelist.md) | Limit the allowed client IPs | Security, Request lifecycle |
|
| [InFlightConn](inflightconn.md) | Limits the number of simultaneous connections. | Security, Request lifecycle |
|
||||||
|
| [IPWhiteList](ipwhitelist.md) | Limit the allowed client IPs. | Security, Request lifecycle |
|
||||||
|
|
|
@ -36,6 +36,13 @@ spec:
|
||||||
spec:
|
spec:
|
||||||
description: MiddlewareTCPSpec holds the MiddlewareTCP configuration.
|
description: MiddlewareTCPSpec holds the MiddlewareTCP configuration.
|
||||||
properties:
|
properties:
|
||||||
|
inFlightConn:
|
||||||
|
description: TCPInFlightConn holds the TCP in flight connection configuration.
|
||||||
|
properties:
|
||||||
|
amount:
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
ipWhiteList:
|
ipWhiteList:
|
||||||
description: TCPIPWhiteList holds the TCP ip white list configuration.
|
description: TCPIPWhiteList holds the TCP ip white list configuration.
|
||||||
properties:
|
properties:
|
||||||
|
|
|
@ -132,6 +132,7 @@ nav:
|
||||||
- 'StripPrefixRegex': 'middlewares/http/stripprefixregex.md'
|
- 'StripPrefixRegex': 'middlewares/http/stripprefixregex.md'
|
||||||
- 'TCP':
|
- 'TCP':
|
||||||
- 'Overview': 'middlewares/tcp/overview.md'
|
- 'Overview': 'middlewares/tcp/overview.md'
|
||||||
|
- 'InFlightConn': 'middlewares/tcp/inflightconn.md'
|
||||||
- 'IpWhitelist': 'middlewares/tcp/ipwhitelist.md'
|
- 'IpWhitelist': 'middlewares/tcp/ipwhitelist.md'
|
||||||
- 'Plugins & Traefik Pilot': 'plugins/index.md'
|
- 'Plugins & Traefik Pilot': 'plugins/index.md'
|
||||||
- 'Operations':
|
- 'Operations':
|
||||||
|
|
|
@ -1050,6 +1050,13 @@ spec:
|
||||||
spec:
|
spec:
|
||||||
description: MiddlewareTCPSpec holds the MiddlewareTCP configuration.
|
description: MiddlewareTCPSpec holds the MiddlewareTCP configuration.
|
||||||
properties:
|
properties:
|
||||||
|
inFlightConn:
|
||||||
|
description: TCPInFlightConn holds the TCP in flight connection configuration.
|
||||||
|
properties:
|
||||||
|
amount:
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
ipWhiteList:
|
ipWhiteList:
|
||||||
description: TCPIPWhiteList holds the TCP ip white list configuration.
|
description: TCPIPWhiteList holds the TCP ip white list configuration.
|
||||||
properties:
|
properties:
|
||||||
|
|
|
@ -4,7 +4,15 @@ package dynamic
|
||||||
|
|
||||||
// TCPMiddleware holds the TCPMiddleware configuration.
|
// TCPMiddleware holds the TCPMiddleware configuration.
|
||||||
type TCPMiddleware struct {
|
type TCPMiddleware struct {
|
||||||
IPWhiteList *TCPIPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty" export:"true"`
|
InFlightConn *TCPInFlightConn `json:"InFlightConn,omitempty" toml:"InFlightConn,omitempty" yaml:"InFlightConn,omitempty" export:"true"`
|
||||||
|
IPWhiteList *TCPIPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty" export:"true"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
|
// TCPInFlightConn holds the TCP in flight connection configuration.
|
||||||
|
type TCPInFlightConn struct {
|
||||||
|
Amount int64 `json:"amount,omitempty" toml:"amount,omitempty" yaml:"amount,omitempty" export:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
|
@ -1350,9 +1350,30 @@ func (in *TCPIPWhiteList) DeepCopy() *TCPIPWhiteList {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *TCPInFlightConn) DeepCopyInto(out *TCPInFlightConn) {
|
||||||
|
*out = *in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPInFlightConn.
|
||||||
|
func (in *TCPInFlightConn) DeepCopy() *TCPInFlightConn {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(TCPInFlightConn)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *TCPMiddleware) DeepCopyInto(out *TCPMiddleware) {
|
func (in *TCPMiddleware) DeepCopyInto(out *TCPMiddleware) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.InFlightConn != nil {
|
||||||
|
in, out := &in.InFlightConn, &out.InFlightConn
|
||||||
|
*out = new(TCPInFlightConn)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
if in.IPWhiteList != nil {
|
if in.IPWhiteList != nil {
|
||||||
in, out := &in.IPWhiteList, &out.IPWhiteList
|
in, out := &in.IPWhiteList, &out.IPWhiteList
|
||||||
*out = new(TCPIPWhiteList)
|
*out = new(TCPIPWhiteList)
|
||||||
|
|
|
@ -174,6 +174,7 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"traefik.http.services.Service1.loadbalancer.sticky.cookie.name": "fui",
|
"traefik.http.services.Service1.loadbalancer.sticky.cookie.name": "fui",
|
||||||
|
|
||||||
"traefik.tcp.middlewares.Middleware0.ipwhitelist.sourcerange": "foobar, fiibar",
|
"traefik.tcp.middlewares.Middleware0.ipwhitelist.sourcerange": "foobar, fiibar",
|
||||||
|
"traefik.tcp.middlewares.Middleware2.inflightconn.amount": "42",
|
||||||
"traefik.tcp.routers.Router0.rule": "foobar",
|
"traefik.tcp.routers.Router0.rule": "foobar",
|
||||||
"traefik.tcp.routers.Router0.entrypoints": "foobar, fiibar",
|
"traefik.tcp.routers.Router0.entrypoints": "foobar, fiibar",
|
||||||
"traefik.tcp.routers.Router0.service": "foobar",
|
"traefik.tcp.routers.Router0.service": "foobar",
|
||||||
|
@ -236,6 +237,11 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
SourceRange: []string{"foobar", "fiibar"},
|
SourceRange: []string{"foobar", "fiibar"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"Middleware2": {
|
||||||
|
InFlightConn: &dynamic.TCPInFlightConn{
|
||||||
|
Amount: 42,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"Service0": {
|
"Service0": {
|
||||||
|
@ -719,6 +725,11 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
SourceRange: []string{"foobar", "fiibar"},
|
SourceRange: []string{"foobar", "fiibar"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"Middleware2": {
|
||||||
|
InFlightConn: &dynamic.TCPInFlightConn{
|
||||||
|
Amount: 42,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Services: map[string]*dynamic.TCPService{
|
Services: map[string]*dynamic.TCPService{
|
||||||
"Service0": {
|
"Service0": {
|
||||||
|
@ -1320,6 +1331,7 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"traefik.HTTP.Services.Service0.LoadBalancer.HealthCheck.Headers.name0": "foobar",
|
"traefik.HTTP.Services.Service0.LoadBalancer.HealthCheck.Headers.name0": "foobar",
|
||||||
|
|
||||||
"traefik.TCP.Middlewares.Middleware0.IPWhiteList.SourceRange": "foobar, fiibar",
|
"traefik.TCP.Middlewares.Middleware0.IPWhiteList.SourceRange": "foobar, fiibar",
|
||||||
|
"traefik.TCP.Middlewares.Middleware2.InFlightConn.Amount": "42",
|
||||||
"traefik.TCP.Routers.Router0.Rule": "foobar",
|
"traefik.TCP.Routers.Router0.Rule": "foobar",
|
||||||
"traefik.TCP.Routers.Router0.EntryPoints": "foobar, fiibar",
|
"traefik.TCP.Routers.Router0.EntryPoints": "foobar, fiibar",
|
||||||
"traefik.TCP.Routers.Router0.Service": "foobar",
|
"traefik.TCP.Routers.Router0.Service": "foobar",
|
||||||
|
|
92
pkg/middlewares/tcp/inflightconn/inflight_conn.go
Normal file
92
pkg/middlewares/tcp/inflightconn/inflight_conn.go
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
package tcpinflightconn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/log"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/middlewares"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/tcp"
|
||||||
|
)
|
||||||
|
|
||||||
|
const typeName = "InFlightConnTCP"
|
||||||
|
|
||||||
|
type inFlightConn struct {
|
||||||
|
name string
|
||||||
|
next tcp.Handler
|
||||||
|
maxConnections int64
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
connections map[string]int64 // current number of connections by remote IP.
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a max connections middleware.
|
||||||
|
// The connections are identified and grouped by remote IP.
|
||||||
|
func New(ctx context.Context, next tcp.Handler, config dynamic.TCPInFlightConn, name string) (tcp.Handler, error) {
|
||||||
|
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName))
|
||||||
|
logger.Debug("Creating middleware")
|
||||||
|
|
||||||
|
return &inFlightConn{
|
||||||
|
name: name,
|
||||||
|
next: next,
|
||||||
|
connections: make(map[string]int64),
|
||||||
|
maxConnections: config.Amount,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeTCP serves the given TCP connection.
|
||||||
|
func (i *inFlightConn) ServeTCP(conn tcp.WriteCloser) {
|
||||||
|
ctx := middlewares.GetLoggerCtx(context.Background(), i.name, typeName)
|
||||||
|
logger := log.FromContext(ctx)
|
||||||
|
|
||||||
|
ip, _, err := net.SplitHostPort(conn.RemoteAddr().String())
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("Cannot parse IP from remote addr: %v", err)
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = i.increment(ip); err != nil {
|
||||||
|
logger.Errorf("Connection rejected: %v", err)
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer i.decrement(ip)
|
||||||
|
|
||||||
|
i.next.ServeTCP(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// increment increases the counter for the number of connections tracked for the
|
||||||
|
// given IP.
|
||||||
|
// It returns an error if the counter would go above the max allowed number of
|
||||||
|
// connections.
|
||||||
|
func (i *inFlightConn) increment(ip string) error {
|
||||||
|
i.mu.Lock()
|
||||||
|
defer i.mu.Unlock()
|
||||||
|
|
||||||
|
if i.connections[ip] >= i.maxConnections {
|
||||||
|
return fmt.Errorf("max number of connections reached for %s", ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
i.connections[ip]++
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// decrement decreases the counter for the number of connections tracked for the
|
||||||
|
// given IP.
|
||||||
|
// It ensures that the counter does not go below zero.
|
||||||
|
func (i *inFlightConn) decrement(ip string) {
|
||||||
|
i.mu.Lock()
|
||||||
|
defer i.mu.Unlock()
|
||||||
|
|
||||||
|
if i.connections[ip] <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
i.connections[ip]--
|
||||||
|
}
|
95
pkg/middlewares/tcp/inflightconn/inflight_conn_test.go
Normal file
95
pkg/middlewares/tcp/inflightconn/inflight_conn_test.go
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
package tcpinflightconn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/traefik/traefik/v2/pkg/tcp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInFlightConn_ServeTCP(t *testing.T) {
|
||||||
|
proceedCh := make(chan struct{})
|
||||||
|
waitCh := make(chan struct{})
|
||||||
|
finishCh := make(chan struct{})
|
||||||
|
|
||||||
|
next := tcp.HandlerFunc(func(conn tcp.WriteCloser) {
|
||||||
|
proceedCh <- struct{}{}
|
||||||
|
|
||||||
|
if fc, ok := conn.(fakeConn); !ok || !fc.wait {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
<-waitCh
|
||||||
|
finishCh <- struct{}{}
|
||||||
|
})
|
||||||
|
|
||||||
|
middleware, err := New(context.Background(), next, dynamic.TCPInFlightConn{Amount: 1}, "foo")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// The first connection should succeed and wait.
|
||||||
|
go middleware.ServeTCP(fakeConn{addr: "127.0.0.1:9000", wait: true})
|
||||||
|
requireMessage(t, proceedCh)
|
||||||
|
|
||||||
|
closeCh := make(chan struct{})
|
||||||
|
|
||||||
|
// The second connection from the same remote address should be closed as the maximum number of connections is exceeded.
|
||||||
|
go middleware.ServeTCP(fakeConn{addr: "127.0.0.1:9000", closeCh: closeCh})
|
||||||
|
requireMessage(t, closeCh)
|
||||||
|
|
||||||
|
// The connection from another remote address should succeed.
|
||||||
|
go middleware.ServeTCP(fakeConn{addr: "127.0.0.2:9000"})
|
||||||
|
requireMessage(t, proceedCh)
|
||||||
|
|
||||||
|
// Once the first connection is closed, next connection with the same remote address should succeed.
|
||||||
|
close(waitCh)
|
||||||
|
requireMessage(t, finishCh)
|
||||||
|
|
||||||
|
go middleware.ServeTCP(fakeConn{addr: "127.0.0.1:9000"})
|
||||||
|
requireMessage(t, proceedCh)
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireMessage(t *testing.T, c chan struct{}) {
|
||||||
|
t.Helper()
|
||||||
|
select {
|
||||||
|
case <-c:
|
||||||
|
case <-time.After(time.Second):
|
||||||
|
t.Fatal("Timeout waiting for message")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeConn struct {
|
||||||
|
net.Conn
|
||||||
|
|
||||||
|
addr string
|
||||||
|
wait bool
|
||||||
|
closeCh chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c fakeConn) RemoteAddr() net.Addr {
|
||||||
|
return fakeAddr{addr: c.addr}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c fakeConn) Close() error {
|
||||||
|
close(c.closeCh)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c fakeConn) CloseWrite() error {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeAddr struct {
|
||||||
|
addr string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a fakeAddr) Network() string {
|
||||||
|
return "tcp"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a fakeAddr) String() string {
|
||||||
|
return a.addr
|
||||||
|
}
|
|
@ -273,7 +273,8 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
|
||||||
id := provider.Normalize(makeID(middlewareTCP.Namespace, middlewareTCP.Name))
|
id := provider.Normalize(makeID(middlewareTCP.Namespace, middlewareTCP.Name))
|
||||||
|
|
||||||
conf.TCP.Middlewares[id] = &dynamic.TCPMiddleware{
|
conf.TCP.Middlewares[id] = &dynamic.TCPMiddleware{
|
||||||
IPWhiteList: middlewareTCP.Spec.IPWhiteList,
|
InFlightConn: middlewareTCP.Spec.InFlightConn,
|
||||||
|
IPWhiteList: middlewareTCP.Spec.IPWhiteList,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ type MiddlewareTCP struct {
|
||||||
|
|
||||||
// MiddlewareTCPSpec holds the MiddlewareTCP configuration.
|
// MiddlewareTCPSpec holds the MiddlewareTCP configuration.
|
||||||
type MiddlewareTCPSpec struct {
|
type MiddlewareTCPSpec struct {
|
||||||
IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"`
|
InFlightConn *dynamic.TCPInFlightConn `json:"inFlightConn,omitempty"`
|
||||||
|
IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||||
|
|
|
@ -820,6 +820,11 @@ func (in *MiddlewareTCPList) DeepCopyObject() runtime.Object {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *MiddlewareTCPSpec) DeepCopyInto(out *MiddlewareTCPSpec) {
|
func (in *MiddlewareTCPSpec) DeepCopyInto(out *MiddlewareTCPSpec) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.InFlightConn != nil {
|
||||||
|
in, out := &in.InFlightConn, &out.InFlightConn
|
||||||
|
*out = new(dynamic.TCPInFlightConn)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
if in.IPWhiteList != nil {
|
if in.IPWhiteList != nil {
|
||||||
in, out := &in.IPWhiteList, &out.IPWhiteList
|
in, out := &in.IPWhiteList, &out.IPWhiteList
|
||||||
*out = new(dynamic.TCPIPWhiteList)
|
*out = new(dynamic.TCPIPWhiteList)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/traefik/traefik/v2/pkg/config/runtime"
|
"github.com/traefik/traefik/v2/pkg/config/runtime"
|
||||||
|
inflightconn "github.com/traefik/traefik/v2/pkg/middlewares/tcp/inflightconn"
|
||||||
ipwhitelist "github.com/traefik/traefik/v2/pkg/middlewares/tcp/ipwhitelist"
|
ipwhitelist "github.com/traefik/traefik/v2/pkg/middlewares/tcp/ipwhitelist"
|
||||||
"github.com/traefik/traefik/v2/pkg/server/provider"
|
"github.com/traefik/traefik/v2/pkg/server/provider"
|
||||||
"github.com/traefik/traefik/v2/pkg/tcp"
|
"github.com/traefik/traefik/v2/pkg/tcp"
|
||||||
|
@ -86,6 +87,13 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) (
|
||||||
|
|
||||||
var middleware tcp.Constructor
|
var middleware tcp.Constructor
|
||||||
|
|
||||||
|
// InFlightConn
|
||||||
|
if config.InFlightConn != nil {
|
||||||
|
middleware = func(next tcp.Handler) (tcp.Handler, error) {
|
||||||
|
return inflightconn.New(ctx, next, *config.InFlightConn, middlewareName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// IPWhiteList
|
// IPWhiteList
|
||||||
if config.IPWhiteList != nil {
|
if config.IPWhiteList != nil {
|
||||||
middleware = func(next tcp.Handler) (tcp.Handler, error) {
|
middleware = func(next tcp.Handler) (tcp.Handler, error) {
|
||||||
|
|
Loading…
Reference in a new issue