Skip to content

Commit

Permalink
Re-enable non-transparent proxy mode
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Chacin <[email protected]>
  • Loading branch information
pablochacin committed Jun 16, 2023
1 parent 4838f24 commit c9403f9
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 33 deletions.
1 change: 1 addition & 0 deletions cmd/agent/commands/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func BuildGrpcCmd(env runtime.Environment, config *agent.Config) *cobra.Command
}

disruptorConfig := protocol.DisruptorConfig{
Transparent: transparent,
TargetPort: target,
RedirectPort: port,
Iface: iface,
Expand Down
1 change: 1 addition & 0 deletions cmd/agent/commands/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func BuildHTTPCmd(env runtime.Environment, config *agent.Config) *cobra.Command
}

disruptorConfig := protocol.DisruptorConfig{
Transparent: transparent,
TargetPort: target,
RedirectPort: port,
Iface: iface,
Expand Down
79 changes: 46 additions & 33 deletions pkg/agent/protocol/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type Disruptor interface {

// DisruptorConfig defines the configuration options for the Disruptor
type DisruptorConfig struct {
// Transparent indicates if the disruption will set a transparent proxy or not
Transparent bool
// Destination port to intercept protocol
TargetPort uint
// Network interface where the traffic will be intercepted
Expand All @@ -41,8 +43,8 @@ type disruptor struct {
config DisruptorConfig
// Proxy
proxy Proxy
// TrafficRedirect
redirector iptables.TrafficRedirector
// Executor used for running commands
executor runtime.Executor
}

// NewDisruptor creates a new instance of a Disruptor that applies a disruptions to a target
Expand All @@ -52,40 +54,32 @@ func NewDisruptor(
config DisruptorConfig,
proxy Proxy,
) (Disruptor, error) {
if config.RedirectPort == 0 {
return nil, fmt.Errorf("redirect port must be valid tcp port")
}
if config.Transparent {
if config.RedirectPort == 0 {
return nil, fmt.Errorf("redirect port must be valid tcp port")
}

if config.TargetPort == 0 {
return nil, fmt.Errorf("target port must be valid tcp port")
}
if config.TargetPort == 0 {
return nil, fmt.Errorf("target port must be valid tcp port")
}

if config.TargetPort == config.RedirectPort {
return nil, fmt.Errorf("target and destination ports cannot be the same")
}

if config.Iface == "" {
return nil, fmt.Errorf("disruption must specify an interface")
if config.Iface == "" {
return nil, fmt.Errorf("disruption must specify an interface")
}
}

if proxy == nil {
return nil, fmt.Errorf("proxy cannot be null")
}

trCfg := iptables.TrafficRedirectorConfig{
Executor: executor,
}
// Redirect traffic to the proxy
tr := &iptables.TrafficRedirectionSpec{
Iface: config.Iface,
DestinationPort: config.TargetPort,
RedirectPort: config.RedirectPort,
}
redirector, err := iptables.NewTrafficRedirectorWithConfig(tr, trCfg)
if err != nil {
return nil, err
}

return &disruptor{
config: config,
proxy: proxy,
redirector: redirector,
config: config,
proxy: proxy,
executor: executor,
}, nil
}

Expand All @@ -100,17 +94,36 @@ func (d *disruptor) Apply(ctx context.Context, duration time.Duration) error {
wc <- d.proxy.Start()
}()

if err := d.redirector.Start(); err != nil {
return fmt.Errorf(" failed traffic redirection: %w", err)
}

// On termination, restore traffic and stop proxy
defer func() {
// ignore errors when stopping. Nothing to do
_ = d.redirector.Stop()
_ = d.proxy.Stop()
}()

if d.config.Transparent {
trCfg := iptables.TrafficRedirectorConfig{
Executor: d.executor,
}
// Redirect traffic to the proxy
tr := &iptables.TrafficRedirectionSpec{
Iface: d.config.Iface,
DestinationPort: d.config.TargetPort,
RedirectPort: d.config.RedirectPort,
}

redirector, err := iptables.NewTrafficRedirectorWithConfig(tr, trCfg)
if err != nil {
return err
}

if err := redirector.Start(); err != nil {
return fmt.Errorf(" failed traffic redirection: %w", err)
}

defer func() {
_ = redirector.Stop()
}()
}

// Wait for request duration, context cancellation or proxy server error
for {
select {
Expand Down
18 changes: 18 additions & 0 deletions pkg/agent/protocol/protocol_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func Test_Validations(t *testing.T) {
title: "valid defaults",
duration: time.Second * 1,
config: DisruptorConfig{
Transparent: true,
TargetPort: 80,
Iface: "eth0",
RedirectPort: 8080,
Expand All @@ -44,6 +45,7 @@ func Test_Validations(t *testing.T) {
title: "invalid RedirectPort port",
duration: time.Second * 1,
config: DisruptorConfig{
Transparent: true,
TargetPort: 80,
Iface: "eth0",
RedirectPort: 0,
Expand All @@ -55,6 +57,7 @@ func Test_Validations(t *testing.T) {
title: "invalid target port",
duration: time.Second * 1,
config: DisruptorConfig{
Transparent: true,
TargetPort: 0,
Iface: "eth0",
RedirectPort: 8080,
Expand All @@ -66,6 +69,7 @@ func Test_Validations(t *testing.T) {
title: "target port equals redirect port",
duration: time.Second * 1,
config: DisruptorConfig{
Transparent: true,
Iface: "eth0",
TargetPort: 8080,
RedirectPort: 8080,
Expand All @@ -77,6 +81,7 @@ func Test_Validations(t *testing.T) {
title: "missing iface",
duration: time.Second * 1,
config: DisruptorConfig{
Transparent: true,
Iface: "",
TargetPort: 80,
RedirectPort: 8080,
Expand All @@ -88,13 +93,26 @@ func Test_Validations(t *testing.T) {
title: "missing proxy",
duration: time.Second * 1,
config: DisruptorConfig{
Transparent: true,
Iface: "",
TargetPort: 80,
RedirectPort: 8080,
},
proxy: nil,
expectError: true,
},
{
title: "non-transparent proxy",
duration: time.Second * 1,
config: DisruptorConfig{
Transparent: false,
Iface: "",
TargetPort: 80,
RedirectPort: 8080,
},
proxy: &fakeProxy{},
expectError: false,
},
}

for _, tc := range testCases {
Expand Down

0 comments on commit c9403f9

Please sign in to comment.