[lxc-devel] [lxd/master] lxd/proxy: Add support for PROXY header
stgraber on Github
lxc-bot at linuxcontainers.org
Wed Jul 18 21:46:43 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 370 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180718/195111d1/attachment.bin>
-------------- next part --------------
From 24c5be8d5b67a1e5fc5c2085dccd2dfdf5ebdb76 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 18 Jul 2018 17:46:08 -0400
Subject: [PATCH] lxd/proxy: Add support for PROXY header
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #4786
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
doc/api-extensions.md | 3 +++
doc/containers.md | 1 +
lxd/container.go | 6 ++++++
lxd/container_lxc.go | 4 +++-
lxd/main_forkproxy.go | 33 ++++++++++++++++++++++++++++++---
lxd/proxy_device_utils.go | 2 ++
shared/version/api.go | 1 +
7 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 96b8f0b67..cc4f65543 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -551,3 +551,6 @@ This adds a new core.debug\_address config option to start a debugging HTTP serv
That server currently includes a pprof API and replaces the old
cpu-profile, memory-profile and print-goroutines debug options.
+
+## proxy\_protocol
+Adds a proxy\_protocol key to the proxy device which controls the use of the HAProxy PROXY protocol header.
diff --git a/doc/containers.md b/doc/containers.md
index 0f3f9af63..fab75c025 100644
--- a/doc/containers.md
+++ b/doc/containers.md
@@ -451,6 +451,7 @@ bind | string | host | no | Which side to bind
uid | int | 0 | no | UID of the owner of the listening Unix socket
gid | int | 0 | no | GID of the owner of the listening Unix socket
mode | int | 0755 | no | Mode for the listening Unix socket
+proxy\_protocol | bool | false | no | Whether to use the HAProxy PROXY protocol to transmit sender information
security.uid | int | 0 | no | What UID to drop privilege to
security.gid | int | 0 | no | What GID to drop privilege to
diff --git a/lxd/container.go b/lxd/container.go
index d748aa597..d75f1e6e1 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -237,6 +237,8 @@ func containerValidDeviceConfigKey(t, k string) bool {
return true
case "mode":
return true
+ case "proxy_protocol":
+ return true
case "security.gid":
return true
case "security.uid":
@@ -469,6 +471,10 @@ func containerValidDevices(db *db.Cluster, devices types.Devices, profile bool,
return fmt.Errorf("Proxy device entry is missing the required \"connect\" property.")
}
+ if shared.IsTrue(m["proxy_protocol"]) && !strings.HasPrefix(m["connect"], "tcp") {
+ return fmt.Errorf("The PROXY header can only be sent to tcp servers")
+ }
+
if (!strings.HasPrefix(m["listen"], "unix:") || strings.HasPrefix(m["listen"], "unix:@")) &&
(m["uid"] != "" || m["gid"] != "" || m["mode"] != "") {
return fmt.Errorf("Only proxy devices for non-abstract unix sockets can carry uid, gid, or mode properties")
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index d2636e43f..f44030a06 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -6873,7 +6873,9 @@ func (c *containerLXC) insertProxyDevice(devName string, m types.Device) error {
proxyValues.listenAddrUid,
proxyValues.listenAddrMode,
proxyValues.securityGid,
- proxyValues.securityUid)
+ proxyValues.securityUid,
+ proxyValues.proxyProtocol,
+ )
if err != nil {
return fmt.Errorf("Error occurred when starting proxy device: %s", err)
}
diff --git a/lxd/main_forkproxy.go b/lxd/main_forkproxy.go
index 4f6d94ca1..cc6f2a455 100644
--- a/lxd/main_forkproxy.go
+++ b/lxd/main_forkproxy.go
@@ -324,7 +324,7 @@ func rearmUDPFd(epFd C.int, connFd C.int) {
}
}
-func listenerInstance(epFd C.int, lAddr *proxyAddress, cAddr *proxyAddress, connFd C.int, lStruct *lStruct) error {
+func listenerInstance(epFd C.int, lAddr *proxyAddress, cAddr *proxyAddress, connFd C.int, lStruct *lStruct, proxy bool) error {
fmt.Printf("Starting %s <-> %s proxy\n", lAddr.connType, cAddr.connType)
if lAddr.connType == "udp" {
// This only handles udp <-> udp. The C constructor will have
@@ -379,10 +379,37 @@ func listenerInstance(epFd C.int, lAddr *proxyAddress, cAddr *proxyAddress, conn
return err
}
+ if proxy && cAddr.connType == "tcp" {
+ if lAddr.connType == "unix" {
+ dstConn.Write([]byte(fmt.Sprintf("PROXY UNKNOWN\r\n")))
+ } else {
+ cHost, cPort, err := net.SplitHostPort(srcConn.RemoteAddr().String())
+ if err != nil {
+ return err
+ }
+
+ dHost, dPort, err := net.SplitHostPort(srcConn.LocalAddr().String())
+ if err != nil {
+ return err
+ }
+
+ proto := srcConn.LocalAddr().Network()
+ proto = strings.ToUpper(proto)
+ if strings.Contains(cHost, ":") {
+ proto = fmt.Sprintf("%s6", proto)
+ } else {
+ proto = fmt.Sprintf("%s4", proto)
+ }
+
+ dstConn.Write([]byte(fmt.Sprintf("PROXY %s %s %s %s %s\r\n", proto, cHost, dHost, cPort, dPort)))
+ }
+ }
+
if cAddr.connType == "unix" && lAddr.connType == "unix" {
// Handle OOB if both src and dst are using unix sockets
go unixRelay(srcConn, dstConn)
} else {
+
go genericRelay(srcConn, dstConn, false)
}
@@ -403,7 +430,7 @@ func (c *cmdForkproxy) Run(cmd *cobra.Command, args []string) error {
}
// Sanity checks
- if len(args) != 11 {
+ if len(args) != 12 {
cmd.Help()
if len(args) == 0 {
@@ -647,7 +674,7 @@ func (c *cmdForkproxy) Run(cmd *cobra.Command, args []string) error {
continue
}
- err := listenerInstance(epFd, lAddr, cAddr, curFd, srcConn)
+ err := listenerInstance(epFd, lAddr, cAddr, curFd, srcConn, args[11] == "true")
if err != nil {
fmt.Printf("Failed to prepare new listener instance: %s", err)
}
diff --git a/lxd/proxy_device_utils.go b/lxd/proxy_device_utils.go
index 176feb757..48f4ca571 100644
--- a/lxd/proxy_device_utils.go
+++ b/lxd/proxy_device_utils.go
@@ -23,6 +23,7 @@ type proxyProcInfo struct {
listenAddrMode string
securityUid string
securityGid string
+ proxyProtocol string
}
func setupProxyProcInfo(c container, device map[string]string) (*proxyProcInfo, error) {
@@ -68,6 +69,7 @@ func setupProxyProcInfo(c container, device map[string]string) (*proxyProcInfo,
listenAddrMode: device["mode"],
securityGid: device["security.gid"],
securityUid: device["security.uid"],
+ proxyProtocol: device["proxy_protocol"],
}
return p, nil
diff --git a/shared/version/api.go b/shared/version/api.go
index 323e6cf5d..dca9279f1 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -115,6 +115,7 @@ var APIExtensions = []string{
"container_protection_delete",
"unix_priv_drop",
"pprof_http",
+ "proxy_protocol",
}
// APIExtensionsCount returns the number of available API extensions.
More information about the lxc-devel
mailing list