Skip to content
This repository has been archived by the owner on Apr 3, 2021. It is now read-only.

Commit

Permalink
add blockOutsideDns option
Browse files Browse the repository at this point in the history
  • Loading branch information
ghost committed Dec 3, 2019
1 parent 2ac9433 commit c030570
Show file tree
Hide file tree
Showing 5 changed files with 476 additions and 14 deletions.
38 changes: 24 additions & 14 deletions cmd/tun2socks/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import (
"io"
"os"
"os/signal"
"runtime"
"strings"
"syscall"
"time"

"github.com/eycorsican/go-tun2socks/common/dns/blocker"
"github.com/eycorsican/go-tun2socks/common/log"
_ "github.com/eycorsican/go-tun2socks/common/log/simple" // Register a simple logger.
"github.com/eycorsican/go-tun2socks/core"
Expand All @@ -31,20 +33,21 @@ func addPostFlagsInitFn(fn func()) {
}

type CmdArgs struct {
Version *bool
TunName *string
TunAddr *string
TunGw *string
TunMask *string
TunDns *string
TunPersist *bool
ProxyType *string
ProxyServer *string
ProxyHost *string
ProxyPort *uint16
UdpTimeout *time.Duration
LogLevel *string
DnsFallback *bool
Version *bool
TunName *string
TunAddr *string
TunGw *string
TunMask *string
TunDns *string
TunPersist *bool
BlockOutsideDns *bool
ProxyType *string
ProxyServer *string
ProxyHost *string
ProxyPort *uint16
UdpTimeout *time.Duration
LogLevel *string
DnsFallback *bool
}

type cmdFlag uint
Expand Down Expand Up @@ -91,6 +94,7 @@ func main() {
args.TunMask = flag.String("tunMask", "255.255.255.0", "TUN interface netmask, it should be a prefixlen (a number) for IPv6 address")
args.TunDns = flag.String("tunDns", "8.8.8.8,8.8.4.4", "DNS resolvers for TUN interface (only need on Windows)")
args.TunPersist = flag.Bool("tunPersist", false, "Persist TUN interface after the program exits or the last open file descriptor is closed (Linux only)")
args.BlockOutsideDns = flag.Bool("blockOutsideDns", false, "Prevent DNS leaks by blocking plaintext DNS queries going out through non-TUN interface (may require admin privileges) (Windows only) ")
args.ProxyType = flag.String("proxyType", "socks", "Proxy handler type")
args.LogLevel = flag.String("loglevel", "info", "Logging level. (debug, info, warn, error, none)")

Expand Down Expand Up @@ -131,6 +135,12 @@ func main() {
log.Fatalf("failed to open tun device: %v", err)
}

if runtime.GOOS == "windows" && *args.BlockOutsideDns {
if err := blocker.BlockOutsideDns(*args.TunName); err != nil {
log.Fatalf("failed to block outside DNS: %v", err)
}
}

// Setup TCP/IP stack.
lwipWriter := core.NewLWIPStack().(io.Writer)

Expand Down
11 changes: 11 additions & 0 deletions common/dns/blocker/blocker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// +build !windows

package blocker

import (
"errors"
)

func BlockOutsideDns(tunName string) error {
return errors.New("not implemented")
}
152 changes: 152 additions & 0 deletions common/dns/blocker/blocker_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// +build windows

package blocker

import (
"fmt"
"math"
"net"
"unsafe"

"golang.org/x/sys/windows"

"github.com/eycorsican/go-tun2socks/common/log"
)

func BlockOutsideDns(tunName string) error {
var engine uintptr
session := FWPM_SESSION0{
Flags: FWPM_SESSION_FLAG_DYNAMIC,
}
err := FwpmEngineOpen0(nil, RPC_C_AUTHN_DEFAULT, nil, &session, unsafe.Pointer(&engine))
if err != nil {
return fmt.Errorf("failed to open engine: %v", err)
}

// Add a sublayer.
key, err := windows.GenerateGUID()
if err != nil {
return fmt.Errorf("failed to generate GUID: %v", err)
}
displayData, err := CreateDisplayData("DnsBlocker", "Dns Blocker sublayer.")
if err != nil {
return fmt.Errorf("failed to create display data: %v", err)
}
sublayer := FWPM_SUBLAYER0{
SubLayerKey: key,
DisplayData: *displayData,
Weight: math.MaxUint16,
}
err = FwpmSubLayerAdd0(engine, &sublayer, 0)
if err != nil {
return fmt.Errorf("failed to add sublayer: %v", err)
}

var filterId uint64

// Block all IPv6 traffic.
blockV6FilterDisplayData, err := CreateDisplayData("DnsBlocker", "Block all IPv6 traffic.")
if err != nil {
return fmt.Errorf("failed to create block v6 filter filter display data: %v", err)
}
blockV6Filter := FWPM_FILTER0{
DisplayData: *blockV6FilterDisplayData,
SubLayerKey: key,
LayerKey: FWPM_LAYER_ALE_AUTH_CONNECT_V6,
Action: FWPM_ACTION0{
Type: FWP_ACTION_BLOCK,
},
Weight: FWP_VALUE0{
Type: FWP_UINT8,
Value: uintptr(13),
},
}
err = FwpmFilterAdd0(engine, &blockV6Filter, 0, &filterId)
if err != nil {
return fmt.Errorf("failed to add block v6 filter: %v", err)
}
log.Debugf("Added filter to block all IPv6 traffic")

// Allow all IPv4 traffic to the TAP adapter.
iface, err := net.InterfaceByName(tunName)
if err != nil {
return fmt.Errorf("fialed to get interface by name %v: %v", tunName, err)
}
tapWhitelistCondition := []FWPM_FILTER_CONDITION0{
{
FieldKey: FWPM_CONDITION_LOCAL_INTERFACE_INDEX,
MatchType: FWP_MATCH_EQUAL,
ConditionValue: FWP_CONDITION_VALUE0{
Type: FWP_UINT32,
Value: uintptr(uint32(iface.Index)),
},
},
}
tapWhitelistFilterDisplayData, err := CreateDisplayData("DnsBlocker", "Allow all traffic to the TAP device.")
if err != nil {
return fmt.Errorf("failed to create tap device whitelist filter display data: %v", err)
}
tapWhitelistFilter := FWPM_FILTER0{
FilterCondition: (*FWPM_FILTER_CONDITION0)(unsafe.Pointer(&tapWhitelistCondition[0])),
NumFilterConditions: 1,
DisplayData: *tapWhitelistFilterDisplayData,
SubLayerKey: key,
LayerKey: FWPM_LAYER_ALE_AUTH_CONNECT_V4,
Action: FWPM_ACTION0{
Type: FWP_ACTION_PERMIT,
},
Weight: FWP_VALUE0{
Type: FWP_UINT8,
Value: uintptr(11),
},
}
err = FwpmFilterAdd0(engine, &tapWhitelistFilter, 0, &filterId)
if err != nil {
return fmt.Errorf("failed to add tap device whitelist filter: %v", err)
}
log.Debugf("Added filter to allow all IPv4 traffic to %v", tunName)

// Block all UDP traffic targeting port 53.
blockAllUDP53Condition := []FWPM_FILTER_CONDITION0{
{
FieldKey: FWPM_CONDITION_IP_PROTOCOL,
MatchType: FWP_MATCH_EQUAL,
ConditionValue: FWP_CONDITION_VALUE0{
Type: FWP_UINT8,
Value: uintptr(uint8(IPPROTO_UDP)),
},
}, {
FieldKey: FWPM_CONDITION_IP_REMOTE_PORT,
MatchType: FWP_MATCH_EQUAL,
ConditionValue: FWP_CONDITION_VALUE0{
Type: FWP_UINT16,
Value: uintptr(uint16(53)),
},
},
}
blockAllUDP53FilterDisplayData, err := CreateDisplayData("DnsBlocker", "Block all UDP traffic targeting port 53")
if err != nil {
return fmt.Errorf("failed to create filter display data: %v", err)
}
blockAllUDP53Filter := FWPM_FILTER0{
FilterCondition: (*FWPM_FILTER_CONDITION0)(unsafe.Pointer(&blockAllUDP53Condition[0])),
NumFilterConditions: 2,
DisplayData: *blockAllUDP53FilterDisplayData,
SubLayerKey: key,
LayerKey: FWPM_LAYER_ALE_AUTH_CONNECT_V4,
Action: FWPM_ACTION0{
Type: FWP_ACTION_BLOCK,
},
Weight: FWP_VALUE0{
Type: FWP_UINT8,
Value: uintptr(10),
},
}
err = FwpmFilterAdd0(engine, &blockAllUDP53Filter, 0, &filterId)
if err != nil {
return fmt.Errorf("failed to add filter: %v", err)
}
log.Debugf("Added filter to block all IPv4 UDP traffic targeting port 53")

return nil
}
Loading

0 comments on commit c030570

Please sign in to comment.