diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-06-17 22:54:59 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-06-18 11:39:38 +0200 |
commit | 96e5d80a3e8c2b874b321bc5918971f8ea63d2c6 (patch) | |
tree | 71ca822435f2f0941b9969a9583cd1d07320f6a3 | |
parent | global: go fmt for 1.17 build tags (diff) | |
download | wireguard-windows-96e5d80a3e8c2b874b321bc5918971f8ea63d2c6.tar.xz wireguard-windows-96e5d80a3e8c2b874b321bc5918971f8ea63d2c6.zip |
tunnel: support turning off automatic routing table
This supports the familiar "Table = off" syntax as on Linux, and then
interprets other valid values as simply "on".
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r-- | conf/config.go | 1 | ||||
-rw-r--r-- | conf/parser.go | 17 | ||||
-rw-r--r-- | conf/writer.go | 3 | ||||
-rw-r--r-- | tunnel/addressconfig.go | 10 | ||||
-rw-r--r-- | ui/confview.go | 8 | ||||
-rw-r--r-- | ui/editdialog.go | 2 | ||||
-rw-r--r-- | ui/syntax/highlighter.go | 10 | ||||
-rw-r--r-- | ui/syntax/syntaxedit.go | 14 |
8 files changed, 57 insertions, 8 deletions
diff --git a/conf/config.go b/conf/config.go index 0a6c6abf..a6266851 100644 --- a/conf/config.go +++ b/conf/config.go @@ -53,6 +53,7 @@ type Interface struct { PostUp string PreDown string PostDown string + TableOff bool } type Peer struct { diff --git a/conf/parser.go b/conf/parser.go index bd08ee6c..9c1295bf 100644 --- a/conf/parser.go +++ b/conf/parser.go @@ -137,6 +137,16 @@ func parsePersistentKeepalive(s string) (uint16, error) { return uint16(m), nil } +func parseTableOff(s string) (bool, error) { + if s == "off" { + return true, nil + } else if s == "auto" || s == "main" { + return false, nil + } + _, err := strconv.ParseUint(s, 10, 32) + return false, err +} + func parseKeyBase64(s string) (*Key, error) { k, err := base64.StdEncoding.DecodeString(s) if err != nil { @@ -292,6 +302,12 @@ func FromWgQuick(s string, name string) (*Config, error) { conf.Interface.PreDown = val case "postdown": conf.Interface.PostDown = val + case "table": + tableOff, err := parseTableOff(val) + if err != nil { + return nil, err + } + conf.Interface.TableOff = tableOff default: return nil, &ParseError{l18n.Sprintf("Invalid key for [Interface] section"), key} } @@ -382,6 +398,7 @@ func FromUAPI(reader io.Reader, existingConfig *Config) (*Config, error) { PostUp: existingConfig.Interface.PostUp, PreDown: existingConfig.Interface.PreDown, PostDown: existingConfig.Interface.PostDown, + TableOff: existingConfig.Interface.TableOff, }, } var peer *Peer diff --git a/conf/writer.go b/conf/writer.go index c786ec10..ddf54aa5 100644 --- a/conf/writer.go +++ b/conf/writer.go @@ -53,6 +53,9 @@ func (conf *Config) ToWgQuick() string { if len(conf.Interface.PostDown) > 0 { output.WriteString(fmt.Sprintf("PostDown = %s\n", conf.Interface.PostDown)) } + if conf.Interface.TableOff { + output.WriteString("Table = off\n") + } for _, peer := range conf.Peers { output.WriteString("\n[Peer]\n") diff --git a/tunnel/addressconfig.go b/tunnel/addressconfig.go index 44bfd8ae..0dec95d0 100644 --- a/tunnel/addressconfig.go +++ b/tunnel/addressconfig.go @@ -138,9 +138,11 @@ func configureInterface(family winipcfg.AddressFamily, conf *conf.Config, tun *t deduplicatedRoutes = append(deduplicatedRoutes, &routes[i]) } - err = luid.SetRoutesForFamily(family, deduplicatedRoutes) - if err != nil { - return err + if !conf.Interface.TableOff { + err = luid.SetRoutesForFamily(family, deduplicatedRoutes) + if err != nil { + return err + } } ipif, err := luid.IPInterface(family) @@ -174,7 +176,7 @@ func configureInterface(family winipcfg.AddressFamily, conf *conf.Config, tun *t func enableFirewall(conf *conf.Config, tun *tun.NativeTun) error { doNotRestrict := true - if len(conf.Peers) == 1 { + if len(conf.Peers) == 1 && !conf.Interface.TableOff { nextallowedip: for _, allowedip := range conf.Peers[0].AllowedIPs { if allowedip.Cidr == 0 { diff --git a/ui/confview.go b/ui/confview.go index cc3bcad9..3d16f38f 100644 --- a/ui/confview.go +++ b/ui/confview.go @@ -51,6 +51,7 @@ type interfaceView struct { addresses *labelTextLine dns *labelTextLine scripts *labelTextLine + table *labelTextLine toggleActive *toggleActiveLine lines []widgetsLine } @@ -307,6 +308,7 @@ func newInterfaceView(parent walk.Container) (*interfaceView, error) { {l18n.Sprintf("Addresses:"), &iv.addresses}, {l18n.Sprintf("DNS servers:"), &iv.dns}, {l18n.Sprintf("Scripts:"), &iv.scripts}, + {l18n.Sprintf("Table:"), &iv.table}, } if iv.lines, err = createLabelTextLines(items, parent, &disposables); err != nil { return nil, err @@ -427,6 +429,12 @@ func (iv *interfaceView) apply(c *conf.Interface) { } else { iv.scripts.hide() } + + if c.TableOff { + iv.table.show(l18n.Sprintf("off")) + } else { + iv.table.hide() + } } func (pv *peerView) widgetsLines() []widgetsLine { diff --git a/ui/editdialog.go b/ui/editdialog.go index 71b71150..3b1521ff 100644 --- a/ui/editdialog.go +++ b/ui/editdialog.go @@ -129,7 +129,7 @@ func newEditDialog(owner walk.Form, tunnel *manager.Tunnel) (*EditDialog, error) return nil, err } dlg.blockUntunneledTrafficCB.SetText(l18n.Sprintf("&Block untunneled traffic (kill-switch)")) - dlg.blockUntunneledTrafficCB.SetToolTipText(l18n.Sprintf("When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.")) + dlg.blockUntunneledTrafficCB.SetToolTipText(l18n.Sprintf("When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, and the interface does not have table off, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.")) dlg.blockUntunneledTrafficCB.SetVisible(false) dlg.blockUntunneledTrafficCB.CheckedChanged().Attach(dlg.onBlockUntunneledTrafficCBCheckedChanged) diff --git a/ui/syntax/highlighter.go b/ui/syntax/highlighter.go index d49cab32..a531854b 100644 --- a/ui/syntax/highlighter.go +++ b/ui/syntax/highlighter.go @@ -26,6 +26,7 @@ const ( highlightKeepalive highlightComment highlightDelimiter + highlightTable highlightCmd highlightError ) @@ -256,6 +257,10 @@ func (s stringSpan) isValidMTU() bool { return s.isValidUint(false, 576, 65535) } +func (s stringSpan) isValidTable() bool { + return s.isSame("off") || s.isSame("auto") || s.isSame("main") || s.isValidUint(false, 0, (1<<32)-1) +} + func (s stringSpan) isValidPersistentKeepAlive() bool { if s.isSame("off") { return true @@ -360,6 +365,7 @@ const ( fieldAddress fieldDNS fieldMTU + fieldTable fieldPreUp fieldPostUp fieldPreDown @@ -395,6 +401,8 @@ func (s stringSpan) field() field { return fieldDNS case s.isCaselessSame("MTU"): return fieldMTU + case s.isCaselessSame("Table"): + return fieldTable case s.isCaselessSame("PublicKey"): return fieldPublicKey case s.isCaselessSame("PresharedKey"): @@ -508,6 +516,8 @@ func (hsa *highlightSpanArray) highlightValue(parent stringSpan, s stringSpan, s hsa.append(parent.s, s, validateHighlight(s.isValidKey(), highlightPresharedKey)) case fieldMTU: hsa.append(parent.s, s, validateHighlight(s.isValidMTU(), highlightMTU)) + case fieldTable: + hsa.append(parent.s, s, validateHighlight(s.isValidTable(), highlightTable)) case fieldPreUp, fieldPostUp, fieldPreDown, fieldPostDown: hsa.append(parent.s, s, validateHighlight(s.isValidPrePostUpDown(), highlightCmd)) case fieldListenPort: diff --git a/ui/syntax/syntaxedit.go b/ui/syntax/syntaxedit.go index 26cd533f..42f6e7b7 100644 --- a/ui/syntax/syntaxedit.go +++ b/ui/syntax/syntaxedit.go @@ -100,6 +100,7 @@ var stylemap = map[highlight]spanStyle{ highlightHost: spanStyle{color: win.RGB(0x0E, 0x0E, 0xFF)}, highlightPort: spanStyle{color: win.RGB(0x81, 0x5F, 0x03)}, highlightMTU: spanStyle{color: win.RGB(0x1C, 0x00, 0xCF)}, + highlightTable: spanStyle{color: win.RGB(0x1C, 0x00, 0xCF)}, highlightKeepalive: spanStyle{color: win.RGB(0x1C, 0x00, 0xCF)}, highlightComment: spanStyle{color: win.RGB(0x53, 0x65, 0x79), effects: win.CFE_ITALIC}, highlightDelimiter: spanStyle{color: win.RGB(0x00, 0x00, 0x00)}, @@ -110,6 +111,8 @@ var stylemap = map[highlight]spanStyle{ func (se *SyntaxEdit) evaluateUntunneledBlocking(cfg string, spans []highlightSpan) { state := InevaluableBlockingUntunneledTraffic var onAllowedIPs, + onTable, + tableOff, seenPeer, seen00v6, seen00v4, @@ -132,10 +135,13 @@ func (se *SyntaxEdit) evaluateUntunneledBlocking(cfg string, spans []highlightSp } else { goto done } - break case highlightField: onAllowedIPs = strings.EqualFold(cfg[span.s:span.s+span.len], "AllowedIPs") - break + onTable = strings.EqualFold(cfg[span.s:span.s+span.len], "Table") + case highlightTable: + if onTable { + tableOff = cfg[span.s:span.s+span.len] == "off" + } case highlightIP: if !onAllowedIPs || !seenPeer { break @@ -166,9 +172,11 @@ func (se *SyntaxEdit) evaluateUntunneledBlocking(cfg string, spans []highlightSp seen80001v6 = true } } - break } } + if tableOff { + return + } if seen00v4 || seen00v6 { state = BlockingUntunneledTraffic |