Hi!

I have situation where i should pass different type of requests over different routes (so they will go thru transparent proxy). I found option for mark for client connections, but didn't found for backend connections. Interface option won't work here, since i need to put specific gateway and to be able change in on fly (add additional routes for example or firewall rules), so i did following patch(attached).
Please let me know if it is ok.

Configuration example:

Networking:
ip rule add fwmark 0x11 table 111
ip rule add fwmark 0x12 table 112
ip rule add fwmark 0x13 table 113
ip rule add fwmark 0x14 table 114
ip route add table 111 default via 10.0.253.129
ip route add table 112 default via 10.0.253.133
ip route add table 113 default via 10.0.253.137
ip route add table 114 default via 10.0.253.141

Part of haproxy config:

backend transparent-cache1
        option transparent
        option tcp-smart-connect
        source 10.0.253.26 usesrc clientip set-mark 0x11

backend transparent-cache2
        option transparent
        option tcp-smart-connect
        source 10.0.253.26 usesrc clientip set-mark 0x12

backend transparent-cache3
        option transparent
        option tcp-smart-connect
        source 10.0.253.26 usesrc clientip set-mark 0x13

backend transparent-cache4
        option transparent
        option tcp-smart-connect
        source 10.0.253.26 usesrc clientip set-mark 0x14

frontend http-in
        bind    :80 transparent
        option tcp-smart-accept
        default_backend transparent-cache1

        acl all src 0.0.0.0/0

        acl url_video hdr_dom(host) -i youtube.com googlevideo.com
        acl url_xxx hdr_dom(host) -i test.com test2.com test3.com
acl url_downloads path_sub .exe .zip .flv .dmg .gz .tar .bin .pdf .mp3 .msi .npk .iso .rar .cab .sft .ipsw .ipa .bz2 .ver .f4v .mp4 .wmv .mov .avi .wav .wma .psf .deb .swf

        use_backend transparent-cache2 if url_video
        use_backend transparent-cache3 if url_xxx
        use_backend transparent-cache4 if url_downloads
        use_backend transparent-cache1 if all
diff -Naur haproxy-1.5-dev21/include/types/connection.h haproxy-1.5-dev21-new/include/types/connection.h
--- haproxy-1.5-dev21/include/types/connection.h	2013-12-17 01:45:49.000000000 +0200
+++ haproxy-1.5-dev21-new/include/types/connection.h	2013-12-21 01:46:42.894200958 +0200
@@ -221,6 +221,7 @@
 
 struct conn_src {
 	unsigned int opts;                   /* CO_SRC_* */
+	int mark;                            /* outgoing connection mark or zero */
 	int iface_len;                       /* bind interface name length */
 	char *iface_name;                    /* bind interface name or NULL */
 	struct port_range *sport_range;      /* optional per-server TCP source ports */
diff -Naur haproxy-1.5-dev21/src/cfgparse.c haproxy-1.5-dev21-new/src/cfgparse.c
--- haproxy-1.5-dev21/src/cfgparse.c	2013-12-17 01:45:49.000000000 +0200
+++ haproxy-1.5-dev21-new/src/cfgparse.c	2013-12-21 01:52:12.820215506 +0200
@@ -5335,6 +5335,7 @@
 		free(curproxy->conn_src.iface_name);
 		curproxy->conn_src.iface_name = NULL;
 		curproxy->conn_src.iface_len = 0;
+		curproxy->conn_src.mark = 0;
 
 		sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
 		if (!sk) {
@@ -5489,6 +5490,33 @@
 				cur_arg += 2;
 				continue;
 			}
+			if (!strcmp(args[cur_arg], "set-mark")) { /* assign mark */
+#ifdef SO_MARK
+				char *err;
+				if (*(args[cur_arg + 1]) == 0) {
+					Alert("parsing [%s:%d] : '%s' : expects an integer argument.\n",
+					      file, linenum, args[0]);
+					err_code |= ERR_ALERT | ERR_FATAL;
+					goto out;
+				}
+				curproxy->conn_src.mark  = (int) strtol(args[cur_arg + 1], &err, 0);
+				if (err && *err != '\0') {
+					Alert("parsing [%s:%d]: invalid character starting at '%s' in 'set-mark %s' (integer/hex value expected).\n",
+						file, linenum, err, args[0]);
+					err_code |= ERR_ALERT | ERR_FATAL;
+					goto out;
+				}
+				global.last_checks |= LSTCHK_NETADM;
+#else
+				Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
+				      file, linenum, args[0], args[cur_arg]);
+				err_code |= ERR_ALERT | ERR_FATAL;
+				goto out;
+#endif
+				cur_arg += 2;
+				continue;
+			}
+
 			Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
 			      file, linenum, args[0], "interface", "usesrc");
 			err_code |= ERR_ALERT | ERR_FATAL;
diff -Naur haproxy-1.5-dev21/src/proto_tcp.c haproxy-1.5-dev21-new/src/proto_tcp.c
--- haproxy-1.5-dev21/src/proto_tcp.c	2013-12-17 01:45:49.000000000 +0200
+++ haproxy-1.5-dev21-new/src/proto_tcp.c	2013-12-21 01:16:48.210121822 +0200
@@ -363,6 +363,11 @@
 			setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, src->iface_name, src->iface_len + 1);
 #endif
 
+#ifdef SO_MARK
+		if (src->mark)
+			setsockopt(fd, SOL_SOCKET, SO_MARK, &src->mark, sizeof(src->mark));
+#endif
+		
 		if (src->sport_range) {
 			int attempts = 10; /* should be more than enough to find a spare port */
 			struct sockaddr_storage sa;

Reply via email to