diff --git a/example.yaml b/example.yaml index 15c9bcca..43604f3b 100644 --- a/example.yaml +++ b/example.yaml @@ -100,6 +100,8 @@ watcher: # Optional ports: - 8080:8080 +# SSH Forwards + # Example of SSH local forward: forward a specific remote port locally # Here, I'm forwarding on port 8080 locally my production website (port 80) <: &composieux-fr-local @@ -126,6 +128,19 @@ watcher: # Optional ports: - 8080:80 +# Proxy forwards + +# Example of Proxy forward type: this will allow you to call locally elasticsearch.svc.local:9200 +# and your call will be proxified to vpc-xxx-rO6gjlqbkwzmzde.eu-west-3.es.amazonaws.com:443 +<: &elasticsearch-proxy + name: elasticsearch-proxy + type: proxy + values: + hostname: elasticsearch.svc.local + proxy_hostname: vpc-xxx-rO6gjlqbkwzmzde.eu-west-3.es.amazonaws.com + ports: + - 9200:443 + # Projects projects: diff --git a/internal/config/model.go b/internal/config/model.go index f8fc97d1..73e94bf0 100644 --- a/internal/config/model.go +++ b/internal/config/model.go @@ -11,6 +11,7 @@ const ( ForwarderKubernetes = "kubernetes" ForwarderKubernetesRemote = "kubernetes-remote" + ForwarderProxy = "proxy" ForwarderSSH = "ssh" ForwarderSSHRemote = "ssh-remote" ) @@ -20,6 +21,7 @@ var ( AvailableForwarders = map[string]bool{ ForwarderKubernetes: true, ForwarderKubernetesRemote: true, + ForwarderProxy: true, ForwarderSSH: true, ForwarderSSHRemote: true, } @@ -28,6 +30,7 @@ var ( ProxifiedForwarders = map[string]bool{ ForwarderKubernetes: true, ForwarderKubernetesRemote: true, + ForwarderProxy: true, ForwarderSSH: true, } ) @@ -98,13 +101,14 @@ func (f *Forward) IsProxified() bool { // ForwardValues represents the available values for each forward type type ForwardValues struct { - Context string `yaml:"context"` - Namespace string `yaml:"namespace"` - Labels map[string]string `yaml:"labels"` - Hostname string `yaml:"hostname"` - Ports []string `yaml:"ports"` - Remote string `yaml:"remote"` - Args []string `yaml:"args"` + Context string `yaml:"context"` + Namespace string `yaml:"namespace"` + Labels map[string]string `yaml:"labels"` + Hostname string `yaml:"hostname"` + ProxyHostname string `yaml:"proxy_hostname"` + Ports []string `yaml:"ports"` + Remote string `yaml:"remote"` + Args []string `yaml:"args"` } // Watcher represents the configuration values for the file watcher component diff --git a/pkg/forwarder/forwarder.go b/pkg/forwarder/forwarder.go index 7d3a708b..992a5c44 100644 --- a/pkg/forwarder/forwarder.go +++ b/pkg/forwarder/forwarder.go @@ -111,7 +111,7 @@ func (f *Forwarder) forward(forward *config.Forward, wg *sync.WaitGroup) { switch forward.Type { case config.ForwarderKubernetesRemote: remoteProxyPort := strconv.Itoa(kubernetes.RemoteSSHProxyPort) - proxyForward = proxy.NewProxyForward(forward.Name, values.Hostname, remoteProxyPort, remoteProxyPort) + proxyForward = proxy.NewProxyForward(forward.Name, values.Hostname, values.ProxyHostname, remoteProxyPort, remoteProxyPort) proxyForwards = append(proxyForwards, proxyForward) f.proxy.AddProxyForward(forward.Name, proxyForward) @@ -119,13 +119,16 @@ func (f *Forwarder) forward(forward *config.Forward, wg *sync.WaitGroup) { break PortsLoop + case config.ForwarderProxy: + proxyForward = proxy.NewProxyForward(forward.Name, values.Hostname, values.ProxyHostname, localPort, forwardPort) default: - proxyForward = proxy.NewProxyForward(forward.Name, values.Hostname, localPort, forwardPort) - proxyForwards = append(proxyForwards, proxyForward) - f.proxy.AddProxyForward(forward.Name, proxyForward) - - proxifiedPorts = append(proxifiedPorts, proxyForward.GetProxifiedPorts()) + proxyForward = proxy.NewProxyForward(forward.Name, values.Hostname, values.ProxyHostname, localPort, forwardPort) } + + proxyForwards = append(proxyForwards, proxyForward) + f.proxy.AddProxyForward(forward.Name, proxyForward) + proxifiedPorts = append(proxifiedPorts, proxyForward.GetProxifiedPorts()) + } } diff --git a/pkg/proxy/proxy.go b/pkg/proxy/proxy.go index 3f2e991a..3bc7d027 100644 --- a/pkg/proxy/proxy.go +++ b/pkg/proxy/proxy.go @@ -58,7 +58,7 @@ func (p *Proxy) Listen() error { return nil } - fmt.Printf("🔌 Proxifying %s locally on %s (port %s) - forwarding to port %s\n", pf.GetHostname(), pf.LocalIP, pf.LocalPort, pf.ProxyPort) + fmt.Printf("🔌 Proxifying %s locally (%s:%s) <-> forwarding to %s:%s\n", pf.GetHostname(), pf.LocalIP, pf.LocalPort, pf.GetProxyHostname(), pf.ProxyPort) go p.handleConnections(pf, key) } @@ -101,7 +101,7 @@ func (p *Proxy) handleConnections(pf *ProxyForward, key string) { fmt.Printf("❌ Could not accept client connection for '%s:%s' (%s): %v\n", pf.LocalIP, pf.LocalPort, pf.GetHostname(), err) } - target, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%s", pf.ProxyPort)) + target, err := net.Dial("tcp", fmt.Sprintf("%s:%s", pf.GetProxyHostname(), pf.ProxyPort)) if err != nil { fmt.Printf("❌ Error when dialing with forwarder for '%s:%s' (%s): %v\n", pf.LocalIP, pf.LocalPort, pf.GetHostname(), err) } @@ -126,7 +126,10 @@ func (p *Proxy) AddProxyForward(name string, proxyForward *ProxyForward) { defer p.addProxyForwardMux.Unlock() p.generateIP(proxyForward) - p.generateProxyPort(proxyForward) + + if proxyForward.ProxyPort == "" { + p.generateProxyPort(proxyForward) + } err := hostfile.AddHost(proxyForward.LocalIP, proxyForward.GetHostname()) if err != nil { diff --git a/pkg/proxy/proxy_forward.go b/pkg/proxy/proxy_forward.go index 5fc9d01c..2195f9ce 100644 --- a/pkg/proxy/proxy_forward.go +++ b/pkg/proxy/proxy_forward.go @@ -3,21 +3,31 @@ package proxy import "fmt" type ProxyForward struct { - Name string - Hostname string - LocalPort string - ForwardPort string - LocalIP string - ProxyPort string + Name string + Hostname string + ProxyHostname string + LocalPort string + ForwardPort string + LocalIP string + ProxyPort string } -func NewProxyForward(name, hostname, localPort, forwardPort string) *ProxyForward { - return &ProxyForward{ - Name: name, - Hostname: hostname, - LocalPort: localPort, - ForwardPort: forwardPort, +func NewProxyForward(name, hostname, proxyHostname, localPort, forwardPort string) *ProxyForward { + proxyForward := &ProxyForward{ + Name: name, + Hostname: hostname, + ProxyHostname: proxyHostname, + LocalPort: localPort, + ForwardPort: forwardPort, } + + // In case of a forward type 'proxy', just set the proxy port with + // the given forward port (proxy component will not generate one) + if proxyHostname != "" { + proxyForward.ProxyPort = forwardPort + } + + return proxyForward } func (p *ProxyForward) SetLocalIP(ip string) { @@ -39,3 +49,14 @@ func (p *ProxyForward) GetHostname() string { return p.Name } + +// GetProxyHostname returns the proxy sender hostname depending on forward type +// In case of a forward type 'proxy', it will return the specified proxy hostname, elsewhere +// it will return 127.0.0.1 because other forwards forward traffic locally +func (p *ProxyForward) GetProxyHostname() string { + if p.ProxyHostname != "" { + return p.ProxyHostname + } + + return "127.0.0.1" +} diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 65e39aa6..0c722610 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -49,7 +49,7 @@ func (r *Runner) RunAll() { go r.Run(application) if application.Hostname != "" { - proxyForward := proxy.NewProxyForward(application.Name, application.Hostname, "", "") + proxyForward := proxy.NewProxyForward(application.Name, application.Hostname, "", "", "") r.proxy.AddProxyForward(application.Name, proxyForward) } }