Dev: new option to mark all tincd socket of a tincd process

Olivier Tirat olivier.tirat at byo-networks.com
Mon Oct 10 20:55:00 CEST 2016


you will find hereafter my patch that has not been done really smartly.

I'm not sure i have understood all i did (probably not).

But once done i still got packet with no mark. And i'm not able to have 
2 tincd process working concurently with the same port but different 
addresses. Did i miss something?

You will find hereafter some outputs of ps, netstat and iptables logs.

  ps -ef | grep tincd
root     14131     1  0 16:41 ?        00:00:00 tincd -n tnid-00000002 
-m 4096 --logfile=/var/log/tinc/tnid-00000002.log
root     14898     1  0 19:28 ?        00:00:00 tincd -n tnid-00000001 
-m 8192 --logfile=/var/log/tinc/tnid-00000001.log

netstat -anp | grep 655
tcp        0      0 192.168.42.111:655 0.0.0.0:*               
LISTEN      14898/tincd
tcp        0      0 192.168.42.110:655 0.0.0.0:*               
LISTEN      14131/tincd
tcp        0      0 192.168.42.110:39626 192.168.42.172:655      
ESTABLISHED 14131/tincd
tcp        0      0 192.168.42.110:54492 192.168.42.175:655      
ESTABLISHED 14898/tincd
udp        0      0 192.168.42.111:655 
0.0.0.0:*                           14898/tincd
udp        0      0 192.168.42.110:655 
0.0.0.0:*                           14131/tincd

the expected trace for the 4th tcp connexion is:

tcp        0      0 192.168.42.111:54492 192.168.42.175:655      
ESTABLISHED 14898/tincd because it is linked to 14898 tincd process 
marked with 8192 mark

  cat /var/log/iptables.log | grep TCP | grep 54492

Oct 10 20:44:39 localhost kernel: output dport: IN= OUT=eth0 
SRC=192.168.42.110 DST=192.168.42.175 LEN=54 TOS=0x10 PREC=0x00 TTL=64 
ID=48981 DF PROTO=TCP SPT=54492 DPT=655 WINDOW=310 RES=0x00 ACK PSH URGP=0
Oct 10 20:44:39 localhost kernel: output dport: IN= OUT=eth0 
SRC=192.168.42.110 DST=192.168.42.175 LEN=52 TOS=0x10 PREC=0x00 TTL=64 
ID=48982 DF PROTO=TCP SPT=54492 DPT=655 WINDOW=310 RES=0x00 ACK URGP=0
Oct 10 20:44:40 localhost kernel: output dport: IN= OUT=eth0 
SRC=192.168.42.110 DST=192.168.42.175 LEN=52 TOS=0x10 PREC=0x00 TTL=64 
ID=48983 DF PROTO=TCP SPT=54492 DPT=655 WINDOW=310 RES=0x00 ACK URGP=0
Oct 10 20:44:40 localhost kernel: output dport: IN= OUT=eth0 
SRC=192.168.42.110 DST=192.168.42.175 LEN=54 TOS=0x10 PREC=0x00 TTL=64 
ID=48984 DF PROTO=TCP SPT=54492 DPT=655 WINDOW=310 RES=0x00 ACK PSH URGP=0
Oct 10 20:45:10 localhost kernel: output dport: IN= OUT=eth0 
SRC=192.168.42.110 DST=192.168.42.175 LEN=52 TOS=0x10 PREC=0x00 TTL=64 
ID=48985 DF PROTO=TCP SPT=54492 DPT=655 WINDOW=310 RES=0x00 ACK URGP=0
Oct 10 20:45:39 localhost kernel: output dport: IN= OUT=eth0 
SRC=192.168.42.110 DST=192.168.42.175 LEN=54 TOS=0x10 PREC=0x00 TTL=64 
ID=48986 DF PROTO=TCP SPT=54492 DPT=655 WINDOW=310 RES=0x00 ACK PSH URGP=0
Oct 10 20:45:39 localhost kernel: output dport: IN= OUT=eth0 
SRC=192.168.42.110 DST=192.168.42.175 LEN=52 TOS=0x10 PREC=0x00 TTL=64 
ID=48987 DF PROTO=TCP SPT=54492 DPT=655 WINDOW=310 RES=0x00 ACK URGP=0
Oct 10 20:45:40 localhost kernel: output dport: IN= OUT=eth0 
SRC=192.168.42.110 DST=192.168.42.175 LEN=52 TOS=0x10 PREC=0x00 TTL=64 
ID=48988 DF PROTO=TCP SPT=54492 DPT=655 WINDOW=310 RES=0x00 ACK URGP=0
Oct 10 20:45:40 localhost kernel: output dport: IN= OUT=eth0 
SRC=192.168.42.110 DST=192.168.42.175 LEN=54 TOS=0x10 PREC=0x00 TTL=64 
ID=48989 DF PROTO=TCP SPT=54492 DPT=655 WINDOW=310 RES=0x00 ACK PSH URGP=0

Packet are not marked why?

All outgoing packet marked with m=8192 are using 192.168.42.111 as 
source address as shown there

  cat /var/log/iptables.log | grep 192.168.42.111
Oct 10 20:44:32 localhost kernel: tincd: IN= OUT=eth0 SRC=192.168.42.175 
DST=192.168.42.111 LEN=516 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=UDP 
SPT=655 DPT=655 LEN=496 MARK=0x2000
Oct 10 20:44:32 localhost kernel: tincd: IN= OUT=eth0 SRC=192.168.42.175 
DST=192.168.42.111 LEN=516 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=UDP 
SPT=655 DPT=655 LEN=496 MARK=0x2000
Oct 10 20:44:32 localhost kernel: tincd: IN= OUT=eth0 SRC=192.168.42.175 
DST=192.168.42.111 LEN=220 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=UDP 
SPT=655 DPT=655 LEN=200 MARK=0x2000
Oct 10 20:44:32 localhost kernel: tincd: IN= OUT=eth0 SRC=192.168.42.175 
DST=192.168.42.111 LEN=220 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=UDP 
SPT=655 DPT=655 LEN=200 MARK=0x2000
Oct 10 20:44:32 localhost kernel: tincd: IN= OUT=eth0 SRC=192.168.42.111 
DST=192.168.42.175 LEN=524 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=UDP 
SPT=655 DPT=655 LEN=504 MARK=0x2000
Oct 10 20:44:32 localhost kernel: tincd: IN= OUT=eth0 SRC=192.168.42.111 
DST=192.168.42.175 LEN=524 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=UDP 
SPT=655 DPT=655 LEN=504 MARK=0x2000
Oct 10 20:44:32 localhost kernel: tincd: IN= OUT=eth0 SRC=192.168.42.111 
DST=192.168.42.175 LEN=411 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=UDP 
SPT=655 DPT=655 LEN=391 MARK=0x2000
Oct 10 20:44:32 localhost kernel: tincd: IN= OUT=eth0 SRC=192.168.42.111 
DST=192.168.42.175 LEN=411 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=UDP 
SPT=655 DPT=655 LEN=391 MARK=0x2000
Oct 10 20:44:32 localhost kernel: tincd: IN= OUT=eth0 SRC=192.168.42.111 
DST=192.168.42.175 LEN=517 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=UDP 
SPT=655 DPT=655 LEN=497 MARK=0x2000


Thank you guys for you help!!!!


Olivier


tinc-1.0.28

diff -ur tinc-1.0.28-orig/src/conf.h tinc-1.0.28/src/conf.h
--- tinc-1.0.28-orig/src/conf.h    2014-08-27 10:40:51.000000000 +0200
+++ tinc-1.0.28/src/conf.h    2016-10-10 18:36:21.401842379 +0200
@@ -39,6 +39,7 @@
  extern int pingtimeout;
  extern int maxtimeout;
  extern int mintimeout;
+extern int mark;
  extern bool bypass_security;
  extern char *confbase;
  extern char *netname;
Seulement dans tinc-1.0.28/src: Makefile
diff -ur tinc-1.0.28-orig/src/net_socket.c tinc-1.0.28/src/net_socket.c
--- tinc-1.0.28-orig/src/net_socket.c    2016-04-09 15:16:47.000000000 +0200
+++ tinc-1.0.28/src/net_socket.c    2016-10-10 18:41:01.081238670 +0200
@@ -69,25 +69,40 @@
          logger(LOG_ERR, "ioctlsocket for %s: %s", c->hostname, 
sockstrerror(sockerrno));
      }
  #endif
-
+
+    int one = 1;
+    int val = mark;
+
  #if defined(SOL_TCP) && defined(TCP_NODELAY)
      option = 1;
      setsockopt(c->socket, SOL_TCP, TCP_NODELAY, (void *)&option, 
sizeof(option));
+    if ( mark != 0 ){
+              setsockopt(c->socket, SOL_TCP, SO_MARK, (void *)&val, 
sizeof(one));
+       }
+
  #endif

  #if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
      option = IPTOS_LOWDELAY;
      setsockopt(c->socket, SOL_IP, IP_TOS, (void *)&option, 
sizeof(option));
+    if ( mark != 0 ){
+              setsockopt(c->socket, SOL_IP, SO_MARK, (void *)&val, 
sizeof(one));
+       }
  #endif

  #if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) && 
defined(IPTOS_LOWDELAY)
      option = IPTOS_LOWDELAY;
      setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, 
sizeof(option));
+    if ( mark != 0 ){
+              setsockopt(c->socket, IPPROTO_IPV6, SO_MARK, (void 
*)&val, sizeof(one));
+       }
  #endif
  }

  static bool bind_to_interface(int sd) {
      char *iface;
+    int val = mark;
+        int one = 1;

  #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
      struct ifreq ifr;
@@ -108,6 +123,12 @@
          logger(LOG_ERR, "Can't bind to interface %s: %s", 
ifr.ifr_ifrn.ifrn_name, strerror(errno));
          return false;
      }
+    else{
+        if ( mark != 0 ){
+                  setsockopt(sd, SOL_SOCKET, SO_MARK, (void *)&val, 
sizeof(one));
+           }
+    }
+

  #else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */
      logger(LOG_WARNING, "%s not supported on this platform", 
"BindToInterface");
@@ -121,13 +142,16 @@
      char *addrstr;
      int option;
      char *iface;
+    int val = mark;
+    int one = 1;

      nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
-
+
      if(nfd < 0) {
          ifdebug(STATUS) logger(LOG_ERR, "Creating metasocket failed: 
%s", sockstrerror(sockerrno));
          return -1;
      }
+

  #ifdef FD_CLOEXEC
      fcntl(nfd, F_SETFD, FD_CLOEXEC);
@@ -137,6 +161,11 @@

      option = 1;
      setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, 
sizeof(option));
+    if ( mark != 0 ){
+        setsockopt(nfd, SOL_SOCKET, SO_MARK, (void *)&val, sizeof(one));
+       }
+
+

  #if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
      if(sa->sa.sa_family == AF_INET6)
@@ -184,6 +213,7 @@
      int nfd;
      char *addrstr;
      int option;
+    int one = 1;

      nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);

@@ -221,6 +251,9 @@
      option = 1;
      setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, 
sizeof(option));
      setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, 
sizeof(option));
+
+    option = mark;
+       setsockopt(nfd, SOL_SOCKET, SO_MARK, (void *)&option, sizeof(one));

      if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void 
*)&udp_rcvbuf, sizeof(udp_rcvbuf)))
          logger(LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", 
udp_rcvbuf, strerror(errno));
diff -ur tinc-1.0.28-orig/src/tincd.c tinc-1.0.28/src/tincd.c
--- tinc-1.0.28-orig/src/tincd.c    2016-04-09 15:41:35.000000000 +0200
+++ tinc-1.0.28/src/tincd.c    2016-10-10 18:36:21.402842391 +0200
@@ -82,6 +82,9 @@
  /* If nonzero, generate public/private keypair for this host/net. */
  int generate_keys = 0;

+/* If nonzero, generate public/private keypair for this host/net. */
+int mark = 0;
+
  /* If nonzero, use null ciphers and skip all key exchanges. */
  bool bypass_security = false;

@@ -120,6 +123,7 @@
      {"logfile", optional_argument, NULL, 4},
      {"pidfile", required_argument, NULL, 5},
      {"option", required_argument, NULL, 'o'},
+    {"mark", required_argument, NULL, 'm'},
      {NULL, 0, NULL, 0}
  };

@@ -147,6 +151,7 @@
                  "  -o, --option=[HOST.]KEY=VALUE  Set global/host 
configuration value.\n"
                  "  -R, --chroot                   chroot to NET dir at 
startup.\n"
                  "  -U, --user=USER                setuid to given USER 
at startup.\n"
+                "  -m, --mark=MARK                mark to address 
several output ip.\n"
                  "      --help                     Display this help 
and exit.\n"
                  "      --version                  Output version 
information and exit.\n\n");
          printf("Report bugs to tinc at tinc-vpn.org.\n");
@@ -161,7 +166,7 @@

      cmdline_conf = list_alloc((list_action_t)free_config);

-    while((r = getopt_long(argc, argv, "c:DLd::k::n:o:K::RU:", 
long_options, &option_index)) != EOF) {
+    while((r = getopt_long(argc, argv, "c:DLd::k::n:o:K::RU:m:", 
long_options, &option_index)) != EOF) {
          switch (r) {
              case 0:                /* long option */
                  break;
@@ -197,6 +202,16 @@
                      debug_level++;
                  break;

+             case 'm':                               /* increase debug 
level */
+                                if(!optarg && optind < argc && 
*argv[optind] != '-')
+                                        optarg = argv[optind++];
+                                if(optarg)
+                                        mark = atoi(optarg);
+                                else
+                                        mark = 0;
+                                break;
+
+
              case 'k':                /* kill old tincds */
  #ifndef HAVE_MINGW
                  if(!optarg && optind < argc && *argv[optind] != '-')



Le 06/10/2016 à 14:11, Guus Sliepen a écrit :
> On Wed, Oct 05, 2016 at 07:27:54PM +0200, Olivier Tirat wrote:
>
>> I'd like to mark all sockets established by a tincd process with a mark
>> passed as an argument in the command line.
> [...]
>> Do you think its something interesting?
>> Do you think its a hard work to do?
>> If not i could probably try to do it and propose a patch for that if you
>> think it is interesting.
> I think it is relatively easy to do. There are two places in
> src/net_socket.c where you would have to call setsockopt() with the
> SO_MARK option: configure_tcp() and setup_vpn_in_socket(). The first one
> is run for all incoming and outgoing TCP sockets, the second one sets up
> the UDP sockets.
>
> Try it out and see if it really allows you to do the mark-based routing
> you want. If it works, you can submit a patch or pull request.
>
>
>
> _______________________________________________
> tinc mailing list
> tinc at tinc-vpn.org
> https://www.tinc-vpn.org/cgi-bin/mailman/listinfo/tinc



---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast.
https://www.avast.com/antivirus
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.tinc-vpn.org/pipermail/tinc/attachments/20161010/c6bf5f25/attachment-0001.html>
-------------- next part --------------
diff -ur tinc-1.0.28-orig/src/conf.h tinc-1.0.28/src/conf.h
--- tinc-1.0.28-orig/src/conf.h	2014-08-27 10:40:51.000000000 +0200
+++ tinc-1.0.28/src/conf.h	2016-10-10 18:36:21.401842379 +0200
@@ -39,6 +39,7 @@
 extern int pingtimeout;
 extern int maxtimeout;
 extern int mintimeout;
+extern int mark;
 extern bool bypass_security;
 extern char *confbase;
 extern char *netname;
Seulement dans tinc-1.0.28/src: Makefile
diff -ur tinc-1.0.28-orig/src/net_socket.c tinc-1.0.28/src/net_socket.c
--- tinc-1.0.28-orig/src/net_socket.c	2016-04-09 15:16:47.000000000 +0200
+++ tinc-1.0.28/src/net_socket.c	2016-10-10 18:41:01.081238670 +0200
@@ -69,25 +69,40 @@
 		logger(LOG_ERR, "ioctlsocket for %s: %s", c->hostname, sockstrerror(sockerrno));
 	}
 #endif
-
+   
+	int one = 1;
+	int val = mark;
+	
 #if defined(SOL_TCP) && defined(TCP_NODELAY)
 	option = 1;
 	setsockopt(c->socket, SOL_TCP, TCP_NODELAY, (void *)&option, sizeof(option));
+	if ( mark != 0 ){
+      		setsockopt(c->socket, SOL_TCP, SO_MARK, (void *)&val, sizeof(one));
+   	}
+	   	
 #endif
 
 #if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY)
 	option = IPTOS_LOWDELAY;
 	setsockopt(c->socket, SOL_IP, IP_TOS, (void *)&option, sizeof(option));
+	if ( mark != 0 ){
+      		setsockopt(c->socket, SOL_IP, SO_MARK, (void *)&val, sizeof(one));
+   	}
 #endif
 
 #if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS) && defined(IPTOS_LOWDELAY)
 	option = IPTOS_LOWDELAY;
 	setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, sizeof(option));
+	if ( mark != 0 ){
+      		setsockopt(c->socket, IPPROTO_IPV6, SO_MARK, (void *)&val, sizeof(one));
+   	}
 #endif
 }
 
 static bool bind_to_interface(int sd) {
 	char *iface;
+	int val = mark;
+        int one = 1;
 
 #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
 	struct ifreq ifr;
@@ -108,6 +123,12 @@
 		logger(LOG_ERR, "Can't bind to interface %s: %s", ifr.ifr_ifrn.ifrn_name, strerror(errno));
 		return false;
 	}
+	else{
+		if ( mark != 0 ){
+      			setsockopt(sd, SOL_SOCKET, SO_MARK, (void *)&val, sizeof(one));
+   		}
+	}
+
 
 #else /* if !defined(SOL_SOCKET) || !defined(SO_BINDTODEVICE) */
 	logger(LOG_WARNING, "%s not supported on this platform", "BindToInterface");
@@ -121,13 +142,16 @@
 	char *addrstr;
 	int option;
 	char *iface;
+	int val = mark;
+	int one = 1;
 
 	nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
-
+     
 	if(nfd < 0) {
 		ifdebug(STATUS) logger(LOG_ERR, "Creating metasocket failed: %s", sockstrerror(sockerrno));
 		return -1;
 	}
+	
 
 #ifdef FD_CLOEXEC
 	fcntl(nfd, F_SETFD, FD_CLOEXEC);
@@ -137,6 +161,11 @@
 
 	option = 1;
 	setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
+	if ( mark != 0 ){
+		setsockopt(nfd, SOL_SOCKET, SO_MARK, (void *)&val, sizeof(one));
+   	}
+
+	
 
 #if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
 	if(sa->sa.sa_family == AF_INET6)
@@ -184,6 +213,7 @@
 	int nfd;
 	char *addrstr;
 	int option;
+	int one = 1;
 
 	nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
 
@@ -221,6 +251,9 @@
 	option = 1;
 	setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));
 	setsockopt(nfd, SOL_SOCKET, SO_BROADCAST, (void *)&option, sizeof(option));
+	
+	option = mark;
+   	setsockopt(nfd, SOL_SOCKET, SO_MARK, (void *)&option, sizeof(one));
 
 	if(udp_rcvbuf && setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (void *)&udp_rcvbuf, sizeof(udp_rcvbuf)))
 		logger(LOG_WARNING, "Can't set UDP SO_RCVBUF to %i: %s", udp_rcvbuf, strerror(errno));
diff -ur tinc-1.0.28-orig/src/tincd.c tinc-1.0.28/src/tincd.c
--- tinc-1.0.28-orig/src/tincd.c	2016-04-09 15:41:35.000000000 +0200
+++ tinc-1.0.28/src/tincd.c	2016-10-10 18:36:21.402842391 +0200
@@ -82,6 +82,9 @@
 /* If nonzero, generate public/private keypair for this host/net. */
 int generate_keys = 0;
 
+/* If nonzero, generate public/private keypair for this host/net. */
+int mark = 0;
+
 /* If nonzero, use null ciphers and skip all key exchanges. */
 bool bypass_security = false;
 
@@ -120,6 +123,7 @@
 	{"logfile", optional_argument, NULL, 4},
 	{"pidfile", required_argument, NULL, 5},
 	{"option", required_argument, NULL, 'o'},
+	{"mark", required_argument, NULL, 'm'},
 	{NULL, 0, NULL, 0}
 };
 
@@ -147,6 +151,7 @@
 				"  -o, --option=[HOST.]KEY=VALUE  Set global/host configuration value.\n"
 				"  -R, --chroot                   chroot to NET dir at startup.\n"
 				"  -U, --user=USER                setuid to given USER at startup.\n"
+				"  -m, --mark=MARK                mark to address several output ip.\n"
 				"      --help                     Display this help and exit.\n"
 				"      --version                  Output version information and exit.\n\n");
 		printf("Report bugs to tinc at tinc-vpn.org.\n");
@@ -161,7 +166,7 @@
 
 	cmdline_conf = list_alloc((list_action_t)free_config);
 
-	while((r = getopt_long(argc, argv, "c:DLd::k::n:o:K::RU:", long_options, &option_index)) != EOF) {
+	while((r = getopt_long(argc, argv, "c:DLd::k::n:o:K::RU:m:", long_options, &option_index)) != EOF) {
 		switch (r) {
 			case 0:				/* long option */
 				break;
@@ -197,6 +202,16 @@
 					debug_level++;
 				break;
 
+			 case 'm':                               /* increase debug level */
+                                if(!optarg && optind < argc && *argv[optind] != '-')
+                                        optarg = argv[optind++];
+                                if(optarg)
+                                        mark = atoi(optarg);
+                                else
+                                        mark = 0;
+                                break;
+
+
 			case 'k':				/* kill old tincds */
 #ifndef HAVE_MINGW
 				if(!optarg && optind < argc && *argv[optind] != '-')


More information about the tinc mailing list