diff --git a/gui/components/Preferences.qml b/gui/components/Preferences.qml
index 02c4b2995dd435ba991276ce43c440de771bdf0d..106af7af6f00cd30add38933dcd1bf12fa3e1a5c 100644
--- a/gui/components/Preferences.qml
+++ b/gui/components/Preferences.qml
@@ -1,16 +1,17 @@
-import QtQuick 2.9
+import QtQuick 2.15
 import QtQuick.Controls 2.2
 import QtQuick.Layouts 1.14
 import QtQuick.Controls.Material 2.1
 
 import "../themes/themes.js" as Theme
 
+// TODO
+// [ ] disable UDP if provider doesn't support it
+// [ ] disable UDP if the platform doesn't support it
+
 ThemedPage {
     title: qsTr("Preferences")
 
-    // TODO - convert "boxed" themedpage with white background into
-    // a QML template.
-
     Rectangle {
         anchors.horizontalCenter: parent.horizontalCenter
         width: root.appWidth * 0.80
@@ -27,9 +28,6 @@ ThemedPage {
         ColumnLayout {
             id: prefCol
             width: root.appWidth * 0.80
-            // FIXME checkboxes in Material style force lineHeights too big.
-            // need to override the style
-            // See: https://bugreports.qt.io/browse/QTBUG-95385
 
             Rectangle {
                 id: turnOffWarning
@@ -38,7 +36,6 @@ ThemedPage {
                 width: parent.width
                 color: "white"
 
-
                 Label {
                     color: "red"
                     text: qsTr("Turn off the VPN to make changes")
@@ -49,7 +46,6 @@ ThemedPage {
                 Layout.rightMargin: 10
             }
 
-
             Label {
                 id: circumLabel
                 text: qsTr("Censorship circumvention")
@@ -72,25 +68,30 @@ ThemedPage {
 
             MaterialCheckBox {
                 id: useBridgesCheckBox
+                enabled: areBridgesAvailable()
                 checked: false
                 text: qsTr("Use obfs4 bridges")
-	        // TODO refactor - this sets wrapMode on checkbox
-		contentItem: Label {
-			text: useBridgesCheckBox.text
-			font: useBridgesCheckBox.font
-			horizontalAlignment: Text.AlignLeft
-			verticalAlignment: Text.AlignVCenter
-			leftPadding: useBridgesCheckBox.indicator.width + useBridgesCheckBox.spacing
-			wrapMode: Label.Wrap
-		}
+                // TODO refactor - this sets wrapMode on checkbox
+                contentItem: Label {
+                    text: useBridgesCheckBox.text
+                    font: useBridgesCheckBox.font
+                    horizontalAlignment: Text.AlignLeft
+                    verticalAlignment: Text.AlignVCenter
+                    leftPadding: useBridgesCheckBox.indicator.width + useBridgesCheckBox.spacing
+                    wrapMode: Label.Wrap
+                }
                 Layout.leftMargin: 10
                 Layout.rightMargin: 10
-		onClicked: {
+                HoverHandler {
+                    cursorShape: Qt.PointingHandCursor
+                }
+                onClicked: {
                     // TODO there's a corner case that needs to be dealt with in the backend,
                     // if an user has a manual location selected and switches to bridges:
-                    // we need to fallback to "auto" selection if such location does not 
+                    // we need to fallback to "auto" selection if such location does not
                     // offer bridges
                     useBridges(checked)
+                    useUDP.enabled = !checked
                 }
             }
 
@@ -100,6 +101,9 @@ ThemedPage {
                 text: qsTr("Use Snowflake (experimental)")
                 enabled: false
                 checked: false
+                HoverHandler {
+                    cursorShape: Qt.PointingHandCursor
+                }
                 Layout.leftMargin: 10
                 Layout.rightMargin: 10
             }
@@ -129,8 +133,12 @@ ThemedPage {
                 checked: false
                 Layout.leftMargin: 10
                 Layout.rightMargin: 10
+                HoverHandler {
+                    cursorShape: Qt.PointingHandCursor
+                }
                 onClicked: {
                     doUseUDP(checked)
+                    useBridgesCheckBox.enabled = areBridgesAvailable()
                 }
             }
         }
@@ -187,6 +195,12 @@ ThemedPage {
         ]
     }
 
+    function areBridgesAvailable() {
+        // FIXME check if provider offers it
+        let providerSupport = true
+        return providerSupport && !useUDP.checked
+    }
+
     function useBridges(value) {
         if (value == true) {
             console.debug("use obfs4")
@@ -215,5 +229,8 @@ ThemedPage {
         if (ctx && ctx.transport == "obfs4") {
             useBridgesCheckBox.checked = true
         }
+        if (ctx && ctx.udp == "true") {
+            useUDP.checked = true
+        }
     }
 }
diff --git a/helpers/bitmask-root b/helpers/bitmask-root
index 929e0f9805a6b8d084546af8eb1baa43e40fca12..ed0fe8e44ca693bc36c783b68dc87f978b563685 100644
--- a/helpers/bitmask-root
+++ b/helpers/bitmask-root
@@ -89,12 +89,15 @@ def is_ipv6_disabled():
 def tostr(s):
     return s.decode('utf-8')
 
-VERSION = "14"
+VERSION = "15"
 SCRIPT = "bitmask-root"
 NAMESERVER_TCP = "10.41.0.1"
 NAMESERVER_UDP = "10.42.0.1"
-# for the time being, we're hardcoding tcp on connection params.
-NAMESERVER = NAMESERVER_TCP
+
+if os.getenv("UDP") == "1":
+    NAMESERVER = NAMESERVER_UDP
+else:
+    NAMESERVER = NAMESERVER_TCP
 BITMASK_CHAIN = "bitmask"
 BITMASK_CHAIN_NAT_OUT = "bitmask"
 BITMASK_CHAIN_NAT_POST = "bitmask_postrouting"
diff --git a/pkg/backend/api.go b/pkg/backend/api.go
index 51fa37719157e7ad7d7004db1811ae44d7f0770a..dc7cbbfac80178e52ed94021293ec7991b267dca 100644
--- a/pkg/backend/api.go
+++ b/pkg/backend/api.go
@@ -95,6 +95,7 @@ func SetTransport(label string) {
 func SetUDP(udp bool) {
 	log.Println("DEBUG setting UDP")
 	ctx.cfg.SetUseUDP(udp)
+	ctx.bm.UseUDP(udp)
 	go trigger(OnStatusChanged)
 }
 
diff --git a/pkg/bitmask/bitmask.go b/pkg/bitmask/bitmask.go
index 1d7217cd374df0c30af61da249d3198b1dd778aa..5597efba7b1e9a022e9cc30ebbafadf2d99c7c63 100644
--- a/pkg/bitmask/bitmask.go
+++ b/pkg/bitmask/bitmask.go
@@ -34,6 +34,7 @@ type Bitmask interface {
 	UseAutomaticGateway()
 	GetTransport() string
 	SetTransport(string) error
+	UseUDP(bool) error
 	GetCurrentGateway() string
 	GetCurrentLocation() string
 	GetCurrentCountry() string
diff --git a/pkg/vpn/launcher_linux.go b/pkg/vpn/launcher_linux.go
index 52c87f71b040126e16d544d9686ab8f87ffb2704..57bbe78be81c4dd76755fa00b859e5af7326d00c 100644
--- a/pkg/vpn/launcher_linux.go
+++ b/pkg/vpn/launcher_linux.go
@@ -215,7 +215,8 @@ func runBitmaskRoot(arg ...string) error {
 	}
 	arg = append([]string{bitmaskRoot}, arg...)
 
-	out, err := exec.Command("pkexec", arg...).Output()
+	cmd := exec.Command("pkexec", arg...)
+	out, err := cmd.Output()
 	if err != nil && arg[2] != "isup" {
 		log.Println("Error while running bitmask-root:")
 		log.Println("args: ", arg)
diff --git a/pkg/vpn/main.go b/pkg/vpn/main.go
index 0671877ce069dabce4f1a82b16167438ce9ffa68..0b1d316ed6ba608c9c9eab9980bf4c6d279bb43b 100644
--- a/pkg/vpn/main.go
+++ b/pkg/vpn/main.go
@@ -39,6 +39,7 @@ type Bitmask struct {
 	shapes           *shapeshifter.ShapeShifter
 	certPemPath      string
 	openvpnArgs      []string
+	udp              bool
 	failed           bool
 }
 
@@ -54,7 +55,7 @@ func Init() (*Bitmask, error) {
 	if err != nil {
 		return nil, err
 	}
-	b := Bitmask{tempdir, bonafide.Gateway{}, bonafide.Gateway{}, statusCh, nil, bf, launch, "", nil, "", []string{}, false}
+	b := Bitmask{tempdir, bonafide.Gateway{}, bonafide.Gateway{}, statusCh, nil, bf, launch, "", nil, "", []string{}, false, false}
 
 	b.launch.firewallStop()
 	/*
@@ -107,3 +108,8 @@ func (b *Bitmask) NeedsCredentials() bool {
 func (b *Bitmask) DoLogin(username, password string) (bool, error) {
 	return b.bonafide.DoLogin(username, password)
 }
+
+func (b *Bitmask) UseUDP(udp bool) error {
+	b.udp = udp
+	return nil
+}
diff --git a/pkg/vpn/openvpn.go b/pkg/vpn/openvpn.go
index e2695a32f31eaa2185b4077d045e55076e395713..673dc2c2ff5bd6cf0997d4035b0a2900212c92c1 100644
--- a/pkg/vpn/openvpn.go
+++ b/pkg/vpn/openvpn.go
@@ -145,6 +145,7 @@ func (b *Bitmask) startOpenVPN() error {
 		}
 
 		proxyArgs := strings.Split(proxy, ":")
+		// TODO pass UDP flag
 		arg = append(arg, "--remote", proxyArgs[0], proxyArgs[1], "tcp4")
 		arg = append(arg, "--route", gw.IPAddress, "255.255.255.255", "net_gateway")
 	} else {
@@ -162,9 +163,11 @@ func (b *Bitmask) startOpenVPN() error {
 		for _, gw := range gateways {
 			for _, port := range gw.Ports {
 				if port != "53" {
-					if os.Getenv("UDP") == "1" {
+					if b.udp {
+						os.Setenv("UDP", "1")
 						arg = append(arg, "--remote", gw.IPAddress, port, "udp4")
 					} else {
+						os.Setenv("UDP", "0")
 						arg = append(arg, "--remote", gw.IPAddress, port, "tcp4")
 					}
 				}