Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(transparent-proxy): add experimental tproxy iptables generation #4114

Merged
merged 1 commit into from
Apr 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/kumactl/cmd/completion/testdata/bash.golden
Original file line number Diff line number Diff line change
Expand Up @@ -3931,6 +3931,8 @@ _kumactl_install_transparent-proxy()
two_word_flags+=("--exclude-outbound-ports")
local_nonpersistent_flags+=("--exclude-outbound-ports")
local_nonpersistent_flags+=("--exclude-outbound-ports=")
flags+=("--experimental-transparent-proxy-engine")
local_nonpersistent_flags+=("--experimental-transparent-proxy-engine")
flags+=("--kuma-cp-ip=")
two_word_flags+=("--kuma-cp-ip")
local_nonpersistent_flags+=("--kuma-cp-ip")
Expand Down
97 changes: 54 additions & 43 deletions app/kumactl/cmd/install/install_transparent_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,48 +22,50 @@ import (
)

type transparentProxyArgs struct {
DryRun bool
Verbose bool
RedirectPortOutBound string
RedirectInbound bool
RedirectPortInBound string
RedirectPortInBoundV6 string
ExcludeInboundPorts string
ExcludeOutboundPorts string
UID string
User string
RedirectDNS bool
RedirectAllDNSTraffic bool
AgentDNSListenerPort string
DNSUpstreamTargetChain string
SkipResolvConf bool
StoreFirewalld bool
KumaCpIP net.IP
SkipDNSConntrackZoneSplit bool
DryRun bool
Verbose bool
RedirectPortOutBound string
RedirectInbound bool
RedirectPortInBound string
RedirectPortInBoundV6 string
ExcludeInboundPorts string
ExcludeOutboundPorts string
UID string
User string
RedirectDNS bool
RedirectAllDNSTraffic bool
AgentDNSListenerPort string
DNSUpstreamTargetChain string
SkipResolvConf bool
StoreFirewalld bool
KumaCpIP net.IP
SkipDNSConntrackZoneSplit bool
ExperimentalTransparentProxyEngine bool
}

var defaultCpIP = net.IPv4(0, 0, 0, 0)

func newInstallTransparentProxy() *cobra.Command {
args := transparentProxyArgs{
DryRun: false,
Verbose: false,
RedirectPortOutBound: "15001",
RedirectInbound: true,
RedirectPortInBound: "15006",
RedirectPortInBoundV6: "15010",
ExcludeInboundPorts: "",
ExcludeOutboundPorts: "",
UID: "",
User: "",
RedirectDNS: false,
RedirectAllDNSTraffic: false,
AgentDNSListenerPort: "15053",
DNSUpstreamTargetChain: "RETURN",
SkipResolvConf: false,
StoreFirewalld: false,
KumaCpIP: defaultCpIP,
SkipDNSConntrackZoneSplit: false,
DryRun: false,
Verbose: false,
RedirectPortOutBound: "15001",
RedirectInbound: true,
RedirectPortInBound: "15006",
RedirectPortInBoundV6: "15010",
ExcludeInboundPorts: "",
ExcludeOutboundPorts: "",
UID: "",
User: "",
RedirectDNS: false,
RedirectAllDNSTraffic: false,
AgentDNSListenerPort: "15053",
DNSUpstreamTargetChain: "RETURN",
SkipResolvConf: false,
StoreFirewalld: false,
KumaCpIP: defaultCpIP,
SkipDNSConntrackZoneSplit: false,
ExperimentalTransparentProxyEngine: false,
}
cmd := &cobra.Command{
Use: "transparent-proxy",
Expand Down Expand Up @@ -178,6 +180,7 @@ runuser -u kuma-dp -- \
cmd.Flags().BoolVar(&args.StoreFirewalld, "store-firewalld", args.StoreFirewalld, "store the iptables changes with firewalld")
cmd.Flags().IPVar(&args.KumaCpIP, "kuma-cp-ip", args.KumaCpIP, "the IP address of the Kuma CP which exposes the DNS service on port 53.")
cmd.Flags().BoolVar(&args.SkipDNSConntrackZoneSplit, "skip-dns-conntrack-zone-split", args.SkipDNSConntrackZoneSplit, "skip applying conntrack zone splitting iptables rules")
cmd.Flags().BoolVar(&args.ExperimentalTransparentProxyEngine, "experimental-transparent-proxy-engine", args.ExperimentalTransparentProxyEngine, "use experimental transparent proxy engine")

return cmd
}
Expand All @@ -203,12 +206,17 @@ func findUidGid(uid, user string) (string, string, error) {
}

func modifyIpTables(cmd *cobra.Command, args *transparentProxyArgs) error {
tp := transparentproxy.DefaultTransparentProxy()
var tp transparentproxy.TransparentProxy
if !args.ExperimentalTransparentProxyEngine {
tp = transparentproxy.DefaultTransparentProxy()

// best effort cleanup before we apply the rules (again?)
_, err := tp.Cleanup(args.DryRun, args.Verbose)
if err != nil {
return errors.Wrapf(err, "unable to invoke cleanup")
// best effort cleanup before we apply the rules (again?)
_, err := tp.Cleanup(args.DryRun, args.Verbose)
if err != nil {
return errors.Wrapf(err, "unable to invoke cleanup")
}
} else {
tp = &transparentproxy.ExperimentalTransparentProxy{}
}

uid, gid, err := findUidGid(args.UID, args.User)
Expand All @@ -219,7 +227,8 @@ func modifyIpTables(cmd *cobra.Command, args *transparentProxyArgs) error {
if !args.DryRun {
_, _ = cmd.OutOrStdout().Write([]byte("kumactl is about to apply the iptables rules that will enable transparent proxying on the machine. The SSH connection may drop. If that happens, just reconnect again.\n"))
}
output, err := tp.Setup(&config.TransparentProxyConfig{

cfg := &config.TransparentProxyConfig{
DryRun: args.DryRun,
Verbose: args.Verbose,
RedirectPortOutBound: args.RedirectPortOutBound,
Expand All @@ -235,7 +244,9 @@ func modifyIpTables(cmd *cobra.Command, args *transparentProxyArgs) error {
AgentDNSListenerPort: args.AgentDNSListenerPort,
DNSUpstreamTargetChain: args.DNSUpstreamTargetChain,
SkipDNSConntrackZoneSplit: args.SkipDNSConntrackZoneSplit,
})
}

output, err := tp.Setup(cfg)
if err != nil {
return errors.Wrap(err, "failed to setup transparent proxy")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ kumactl install transparent-proxy [flags]
--dry-run dry run
--exclude-inbound-ports string a comma separated list of inbound ports to exclude from redirect to Envoy
--exclude-outbound-ports string a comma separated list of outbound ports to exclude from redirect to Envoy
--experimental-transparent-proxy-engine use experimental transparent proxy engine
-h, --help help for transparent-proxy
--kuma-cp-ip ip the IP address of the Kuma CP which exposes the DNS service on port 53. (default 0.0.0.0)
--kuma-dp-uid string the UID of the user that will run kuma-dp
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
github.com/hoisie/mustache v0.0.0-20160804235033-6375acf62c69
github.com/iancoleman/orderedmap v0.2.0
github.com/kelseyhightower/envconfig v1.4.0
github.com/kumahq/kuma-net v0.1.3
github.com/kumahq/protoc-gen-kumadoc v0.1.7
github.com/lib/pq v1.10.4
github.com/miekg/dns v1.1.47
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4=
github.com/kumahq/go-control-plane v0.9.10-0.20211022075049-d35edcf0813a h1:RtOjGzZDv0JDtpWthWmxDHXhZRnJBaeIoIHcQrigWdE=
github.com/kumahq/go-control-plane v0.9.10-0.20211022075049-d35edcf0813a/go.mod h1:utjuSZ1DPHuYf0cTZ8WEsaQf5bwmT1TZiWaQjpJtBF0=
github.com/kumahq/kuma-net v0.1.3 h1:ZMvPuOf6V6q0dTTz55jpNIF9Py4RvP8Z4U/owg4+xy4=
github.com/kumahq/kuma-net v0.1.3/go.mod h1:s/78MDdwEnFwTYCcwguYa4EosjGkBouVIPJM79jvync=
github.com/kumahq/protoc-gen-kumadoc v0.1.7 h1:WgwGa7QgVbj2QVzRU5hQaMxSJ29WppDHVczo3FUIc84=
github.com/kumahq/protoc-gen-kumadoc v0.1.7/go.mod h1:F+c9RjgKlv1Q3UEoPJCtMJw8Fd+X5PfG5jlkTSfZOMA=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
Expand Down
117 changes: 117 additions & 0 deletions pkg/transparentproxy/transparentproxy_experimental.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package transparentproxy

import (
"strconv"
"strings"

"github.com/pkg/errors"

"github.com/kumahq/kuma-net/iptables/builder"
kumanet_config "github.com/kumahq/kuma-net/iptables/config"
"github.com/kumahq/kuma/pkg/transparentproxy/config"
)

var _ TransparentProxy = &ExperimentalTransparentProxy{}

type ExperimentalTransparentProxy struct{}

func splitPorts(ports string) ([]uint16, error) {
var result []uint16

for _, port := range strings.Split(ports, ",") {
p, err := strconv.ParseUint(port, 10, 16)
if err != nil {
return nil, errors.Wrapf(err, "port (%s), is not valid uint16", port)
}

result = append(result, uint16(p))
}

return result, nil
}

func (tp *ExperimentalTransparentProxy) Setup(tpConfig *config.TransparentProxyConfig) (string, error) {
redirectInboundPort, err := strconv.ParseUint(tpConfig.RedirectPortInBound, 10, 16)
if err != nil {
return "", errors.Wrapf(
err,
"inbound redirect port (%s), is not valid uint16",
tpConfig.RedirectPortInBound,
)
}

redirectOutboundPort, err := strconv.ParseUint(tpConfig.RedirectPortOutBound, 10, 16)
if err != nil {
return "", errors.Wrapf(
err,
"outbound redirect port (%s), is not valid uint16",
tpConfig.RedirectPortOutBound,
)
}

agentDNSListenerPort, err := strconv.ParseUint(tpConfig.AgentDNSListenerPort, 10, 16)
if err != nil {
return "", errors.Wrapf(
err,
"outbound redirect port (%s), is not valid uint16",
tpConfig.RedirectPortOutBound,
)
}

var excludeInboundPorts []uint16
if tpConfig.ExcludeInboundPorts != "" {
excludeInboundPorts, err = splitPorts(tpConfig.ExcludeInboundPorts)
if err != nil {
return "", errors.Wrap(err, "cannot parse inbound ports to exclude")
}
}

var excludeOutboundPorts []uint16
if tpConfig.ExcludeOutboundPorts != "" {
excludeOutboundPorts, err = splitPorts(tpConfig.ExcludeOutboundPorts)
if err != nil {
return "", errors.Wrap(err, "cannot parse outbound ports to exclude")
}
}

defaultConfig := kumanet_config.DefaultConfig()

cfg := &kumanet_config.Config{
Owner: &kumanet_config.Owner{
UID: tpConfig.UID,
GID: tpConfig.GID,
},
Redirect: &kumanet_config.Redirect{
NamePrefix: "KUMA_",
Inbound: &kumanet_config.TrafficFlow{
Port: uint16(redirectInboundPort),
Chain: defaultConfig.Redirect.Inbound.Chain,
RedirectChain: defaultConfig.Redirect.Inbound.RedirectChain,
ExcludePorts: excludeInboundPorts,
},
Outbound: &kumanet_config.TrafficFlow{
Port: uint16(redirectOutboundPort),
Chain: defaultConfig.Redirect.Outbound.Chain,
RedirectChain: defaultConfig.Redirect.Outbound.RedirectChain,
ExcludePorts: excludeOutboundPorts,
},
DNS: &kumanet_config.DNS{
Enabled: tpConfig.RedirectAllDNSTraffic,
Port: uint16(agentDNSListenerPort),
ConntrackZoneSplit: tpConfig.SkipDNSConntrackZoneSplit,
},
},
Verbose: tpConfig.Verbose,
}

if tpConfig.DryRun {
return builder.BuildIPTables(cfg)
}

return builder.RestoreIPTables(cfg)
}

func (tp *ExperimentalTransparentProxy) Cleanup(dryRun, verbose bool) (string, error) {
// TODO implement me
panic("implement me")
lahabana marked this conversation as resolved.
Show resolved Hide resolved
}