Add the ability to set a firewall mark on sockets.
authorGuus Sliepen <guus@tinc-vpn.org>
Mon, 2 Apr 2018 14:33:14 +0000 (16:33 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Mon, 2 Apr 2018 14:33:14 +0000 (16:33 +0200)
The FWMark option is added, when set it will use setsockopt(SOL_SOCKET, SO_MARK)
to set the given value as the mark on all sockets created by tinc.

Thanks to Olivier Tirat for submitting a similar patch in the past.

bash_completion.d/tinc
doc/tinc.conf.5.in
doc/tinc.texi
src/net.h
src/net_setup.c
src/net_socket.c
src/tincctl.c

index de2717e..575f412 100644 (file)
@@ -4,7 +4,7 @@ _tinc() {
        cur="${COMP_WORDS[COMP_CWORD]}"
        prev="${COMP_WORDS[COMP_CWORD-1]}"
        opts="-c -d -D -K -n -o -L -R -U --config --no-detach --debug --net --option --mlock --logfile --pidfile --chroot --user --help --version"
-       confvars="Address AddressFamily BindToAddress BindToInterface Broadcast BroadcastSubnet Cipher ClampMSS Compression ConnectTo DecrementTTL Device DeviceStandby DeviceType Digest DirectOnly Ed25519PrivateKeyFile Ed25519PublicKey Ed25519PublicKeyFile ExperimentalProtocol Forwarding GraphDumpFile Hostnames IffOneQueue IndirectData Interface InvitationExpire KeyExpire ListenAddress LocalDiscovery MACExpire MACLength MaxOutputBufferSize MaxTimeout Mode MTUInfoInterval Name PMTU PMTUDiscovery PingInterval PingTimeout Port PriorityInheritance PrivateKeyFile ProcessPriority Proxy PublicKeyFile ReplayWindow StrictSubnets Subnet TCPOnly TunnelServer UDPDiscovery UDPDiscoveryKeepaliveInterval UDPDiscoveryInterval UDPDiscoveryTimeout UDPInfoInterval UDPRcvBuf UDPSndBuf UPnP UPnPDiscoverWait UPnPRefreshPeriod VDEGroup VDEPort Weight"
+       confvars="Address AddressFamily BindToAddress BindToInterface Broadcast BroadcastSubnet Cipher ClampMSS Compression ConnectTo DecrementTTL Device DeviceStandby DeviceType Digest DirectOnly Ed25519PrivateKeyFile Ed25519PublicKey Ed25519PublicKeyFile ExperimentalProtocol Forwarding FWMark GraphDumpFile Hostnames IffOneQueue IndirectData Interface InvitationExpire KeyExpire ListenAddress LocalDiscovery MACExpire MACLength MaxOutputBufferSize MaxTimeout Mode MTUInfoInterval Name PMTU PMTUDiscovery PingInterval PingTimeout Port PriorityInheritance PrivateKeyFile ProcessPriority Proxy PublicKeyFile ReplayWindow StrictSubnets Subnet TCPOnly TunnelServer UDPDiscovery UDPDiscoveryKeepaliveInterval UDPDiscoveryInterval UDPDiscoveryTimeout UDPInfoInterval UDPRcvBuf UDPSndBuf UPnP UPnPDiscoverWait UPnPRefreshPeriod VDEGroup VDEPort Weight"
        commands="add connect debug del disconnect dump edit export export-all generate-ed25519-keys generate-keys generate-rsa-keys get help import info init invite join list log network pcap pid purge reload restart retry set sign start stop top verify version"
 
        case ${prev} in
index ed9709a..fa0f2fd 100644 (file)
@@ -312,6 +312,10 @@ This is less efficient, but allows the kernel to apply its routing and firewall
 and can also help debugging.
 Incoming packets using the SPTPS protocol are dropped, since they are end-to-end encrypted.
 .El
+.It Va FWMark Li = Ar value Po 0 Pc Bq experimental
+When set to a non-zero value, all TCP and UDP sockets created by tinc will use the given value as the firewall mark.
+This can be used for mark-based routing or for packet filtering.
+This option is currently only supported on Linux.
 .It Va Hostnames Li = yes | no Pq no
 This option selects whether IP addresses (both real and on the VPN) should
 be resolved. Since DNS lookups are blocking, it might affect tinc's
index c9bda8e..7a4d8b8 100644 (file)
@@ -1055,6 +1055,12 @@ and can also help debugging.
 Incoming packets using the SPTPS protocol are dropped, since they are end-to-end encrypted.
 @end table
 
+@cindex FWMark
+@item FWMark = <@var{value}> (0) [experimental]
+When set to a non-zero value, all TCP and UDP sockets created by tinc will use the given value as the firewall mark.
+This can be used for mark-based routing or for packet filtering.
+This option is currently only supported on Linux.
+
 @cindex Hostnames
 @item Hostnames = <yes|no> (no)
 This option selects whether IP addresses (both real and on the VPN)
index 90cbdbb..d69eabd 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -148,6 +148,7 @@ extern int keylifetime;
 extern int udp_rcvbuf;
 extern int udp_sndbuf;
 extern int max_connection_burst;
+extern int fwmark;
 extern bool do_prune;
 extern char *myport;
 extern bool device_standby;
index 17675ae..455f66c 100644 (file)
@@ -949,6 +949,16 @@ static bool setup_myself(void) {
                }
        }
 
+       get_config_int(lookup_config(config_tree, "FWMark"), &fwmark);
+#ifndef SO_MARK
+
+       if(fwmark) {
+               logger(DEBUG_ALWAYS, LOG_ERR, "FWMark not supported on this platform!");
+               return false;
+       }
+
+#endif
+
        int replaywin_int;
 
        if(get_config_int(lookup_config(config_tree, "ReplayWindow"), &replaywin_int)) {
index cd6a5c2..2da6253 100644 (file)
@@ -42,6 +42,7 @@ int seconds_till_retry = 5;
 int udp_rcvbuf = 1024 * 1024;
 int udp_sndbuf = 1024 * 1024;
 int max_connection_burst = 100;
+int fwmark;
 
 listen_socket_t listen_socket[MAXSOCKETS];
 int listen_sockets;
@@ -85,6 +86,14 @@ static void configure_tcp(connection_t *c) {
        option = IPTOS_LOWDELAY;
        setsockopt(c->socket, IPPROTO_IPV6, IPV6_TCLASS, (void *)&option, sizeof(option));
 #endif
+
+#if defined(SO_MARK)
+
+       if(fwmark) {
+               setsockopt(c->socket, SOL_SOCKET, SO_MARK, (void *)&fwmark, sizeof(fwmark));
+       }
+
+#endif
 }
 
 static bool bind_to_interface(int sd) {
@@ -184,6 +193,14 @@ int setup_listen_socket(const sockaddr_t *sa) {
 
 #else
 #warning IPV6_V6ONLY not defined
+#endif
+
+#if defined(SO_MARK)
+
+       if(fwmark) {
+               setsockopt(nfd, SOL_SOCKET, SO_MARK, (void *)&fwmark, sizeof(fwmark));
+       }
+
 #endif
 
        if(get_config_string
@@ -316,6 +333,14 @@ int setup_vpn_in_socket(const sockaddr_t *sa) {
                setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
        }
 
+#endif
+
+#if defined(SO_MARK)
+
+       if(fwmark) {
+               setsockopt(nfd, SOL_SOCKET, SO_MARK, (void *)&fwmark, sizeof(fwmark));
+       }
+
 #endif
 
        if(!bind_to_interface(nfd)) {
index 5ba7161..79762e3 100644 (file)
@@ -1695,6 +1695,7 @@ const var_t variables[] = {
        {"Ed25519PrivateKeyFile", VAR_SERVER},
        {"ExperimentalProtocol", VAR_SERVER},
        {"Forwarding", VAR_SERVER},
+       {"FWMark", VAR_SERVER},
        {"GraphDumpFile", VAR_SERVER | VAR_OBSOLETE},
        {"Hostnames", VAR_SERVER},
        {"IffOneQueue", VAR_SERVER},