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 de2717ef8307700a552efdef8bfa84747bcad46e..575f412a2e9ae398db1e02ae480026ec3ddf0135 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 ed9709a651ec358f2f9863632cb49fc6987fe3be..fa0f2fd00dcf23b76cbe8f0eefb63302c816ac6e 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 c9bda8e57759f8d21c17f2ff9a8c6d55c66491a2..7a4d8b803122e98f93102b335d28e8215e0c3cf2 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 90cbdbb46188dec322a32c57dba7d174e57ae99f..d69eabdacab702624afbedcf8c4e21944f9eb746 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 17675aec40ace0b3f8d775875c54321961206e55..455f66c68d78ee55ddded5e5d9f1b59b3a9aedba 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 cd6a5c2f32e2ceb957de55bd692ec0b14134a764..2da6253ee3a3dc6c8d62dd669629ce1fbcc90c8d 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 5ba71613fd4f0cc4529ebddd6f2db0b2b1d938d8..79762e3acdca5b87c0c26f84b0da12bb90700d11 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},