mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-04-02 19:37:40 +03:00
Fix windows route
This commit is contained in:
parent
6bad0c2380
commit
a93592a9b5
9 changed files with 662 additions and 26 deletions
6
go.mod
6
go.mod
|
@ -7,9 +7,9 @@ require (
|
|||
github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e
|
||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
|
||||
github.com/sagernet/sing v0.0.0-20220925112014-b12b8b7fd220
|
||||
golang.org/x/net v0.0.0-20220923203811-8be639271d50
|
||||
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8
|
||||
github.com/sagernet/sing v0.0.0-20220929000216-9a83e35b7186
|
||||
golang.org/x/net v0.0.0-20220927171203-f486391704dc
|
||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec
|
||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c
|
||||
)
|
||||
|
||||
|
|
12
go.sum
12
go.sum
|
@ -9,17 +9,17 @@ github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h
|
|||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||
github.com/sagernet/sing v0.0.0-20220925112014-b12b8b7fd220 h1:fQk/BHOeHw5murjeNTdmkXmDy9cMlbubRINRH7GDuu4=
|
||||
github.com/sagernet/sing v0.0.0-20220925112014-b12b8b7fd220/go.mod h1:5/u6RMDMoGIkSNtrZb41kJvyIFg3Ysn69P3WiAu8m0c=
|
||||
github.com/sagernet/sing v0.0.0-20220929000216-9a83e35b7186 h1:ZDlgH6dTozS3ODaYq1GxCj+H8NvYESaex90iX72gadw=
|
||||
github.com/sagernet/sing v0.0.0-20220929000216-9a83e35b7186/go.mod h1:zvgDYKI+vCAW9RyfyrKTgleI+DOa8lzHMPC7VZo3OL4=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
golang.org/x/net v0.0.0-20220923203811-8be639271d50 h1:vKyz8L3zkd+xrMeIaBsQ/MNVPVFSffdaU3ZyYlBGFnI=
|
||||
golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20220927171203-f486391704dc h1:FxpXZdoBqT8RjqTy6i1E8nXHhW21wK7ptQ/EPIGxzPQ=
|
||||
golang.org/x/net v0.0.0-20220927171203-f486391704dc/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 h1:h+EGohizhe9XlX18rfpa8k8RAc5XyaeamM+0VHRd4lc=
|
||||
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
|
||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c h1:m5lcgWnL3OElQNVyp3qcncItJ2c0sQlSGjYK2+nJTA4=
|
||||
|
|
158
internal/winsys/constants.go
Normal file
158
internal/winsys/constants.go
Normal file
|
@ -0,0 +1,158 @@
|
|||
//go:build windows
|
||||
|
||||
package winsys
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
AF_INET = 2
|
||||
AF_INET6 = 23
|
||||
)
|
||||
|
||||
const (
|
||||
MAX_MODULE_NAME32 = 255
|
||||
MAX_PATH = 260
|
||||
)
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot
|
||||
const (
|
||||
TH32CS_SNAPHEAPLIST = 0x00000001
|
||||
TH32CS_SNAPPROCESS = 0x00000002
|
||||
TH32CS_SNAPTHREAD = 0x00000004
|
||||
TH32CS_SNAPMODULE = 0x00000008
|
||||
TH32CS_SNAPMODULE32 = 0x00000010
|
||||
TH32CS_INHERIT = 0x80000000
|
||||
TH32CS_SNAPALL = TH32CS_SNAPHEAPLIST | TH32CS_SNAPMODULE | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD
|
||||
)
|
||||
|
||||
const (
|
||||
MAX_ADAPTER_NAME = 128
|
||||
MAX_INTERFACE_NAME_LEN = 256
|
||||
MAXLEN_PHYSADDR = 8
|
||||
MAXLEN_IFDESCR = 256
|
||||
)
|
||||
|
||||
const (
|
||||
ERROR_INSUFFICIENT_BUFFER = 122
|
||||
)
|
||||
|
||||
const (
|
||||
RPC_C_AUTHN_DEFAULT uint32 = 0xFFFFFFFF
|
||||
FWPM_SESSION_FLAG_DYNAMIC uint32 = 0x00000001
|
||||
)
|
||||
|
||||
const (
|
||||
FWP_MATCH_EQUAL uint32 = 0
|
||||
FWP_MATCH_GREATER = (FWP_MATCH_EQUAL + 1)
|
||||
FWP_MATCH_LESS = (FWP_MATCH_GREATER + 1)
|
||||
FWP_MATCH_GREATER_OR_EQUAL = (FWP_MATCH_LESS + 1)
|
||||
FWP_MATCH_LESS_OR_EQUAL = (FWP_MATCH_GREATER_OR_EQUAL + 1)
|
||||
FWP_MATCH_RANGE = (FWP_MATCH_LESS_OR_EQUAL + 1)
|
||||
FWP_MATCH_FLAGS_ALL_SET = (FWP_MATCH_RANGE + 1)
|
||||
FWP_MATCH_FLAGS_ANY_SET = (FWP_MATCH_FLAGS_ALL_SET + 1)
|
||||
FWP_MATCH_FLAGS_NONE_SET = (FWP_MATCH_FLAGS_ANY_SET + 1)
|
||||
FWP_MATCH_EQUAL_CASE_INSENSITIVE = (FWP_MATCH_FLAGS_NONE_SET + 1)
|
||||
FWP_MATCH_NOT_EQUAL = (FWP_MATCH_EQUAL_CASE_INSENSITIVE + 1)
|
||||
FWP_MATCH_PREFIX = (FWP_MATCH_NOT_EQUAL + 1)
|
||||
FWP_MATCH_NOT_PREFIX = (FWP_MATCH_PREFIX + 1)
|
||||
FWP_MATCH_TYPE_MAX = (FWP_MATCH_NOT_PREFIX + 1)
|
||||
)
|
||||
|
||||
const (
|
||||
FWP_EMPTY uint32 = 0
|
||||
FWP_UINT8 = (FWP_EMPTY + 1)
|
||||
FWP_UINT16 = (FWP_UINT8 + 1)
|
||||
FWP_UINT32 = (FWP_UINT16 + 1)
|
||||
FWP_UINT64 = (FWP_UINT32 + 1)
|
||||
FWP_INT8 = (FWP_UINT64 + 1)
|
||||
FWP_INT16 = (FWP_INT8 + 1)
|
||||
FWP_INT32 = (FWP_INT16 + 1)
|
||||
FWP_INT64 = (FWP_INT32 + 1)
|
||||
FWP_FLOAT = (FWP_INT64 + 1)
|
||||
FWP_DOUBLE = (FWP_FLOAT + 1)
|
||||
FWP_BYTE_ARRAY16_TYPE = (FWP_DOUBLE + 1)
|
||||
FWP_BYTE_BLOB_TYPE = (FWP_BYTE_ARRAY16_TYPE + 1)
|
||||
FWP_SID = (FWP_BYTE_BLOB_TYPE + 1)
|
||||
FWP_SECURITY_DESCRIPTOR_TYPE = (FWP_SID + 1)
|
||||
FWP_TOKEN_INFORMATION_TYPE = (FWP_SECURITY_DESCRIPTOR_TYPE + 1)
|
||||
FWP_TOKEN_ACCESS_INFORMATION_TYPE = (FWP_TOKEN_INFORMATION_TYPE + 1)
|
||||
FWP_UNICODE_STRING_TYPE = (FWP_TOKEN_ACCESS_INFORMATION_TYPE + 1)
|
||||
FWP_BYTE_ARRAY6_TYPE = (FWP_UNICODE_STRING_TYPE + 1)
|
||||
FWP_BITMAP_INDEX_TYPE = (FWP_BYTE_ARRAY6_TYPE + 1)
|
||||
FWP_BITMAP_ARRAY64_TYPE = (FWP_BITMAP_INDEX_TYPE + 1)
|
||||
FWP_SINGLE_DATA_TYPE_MAX = 0xff
|
||||
FWP_V4_ADDR_MASK = (FWP_SINGLE_DATA_TYPE_MAX + 1)
|
||||
FWP_V6_ADDR_MASK = (FWP_V4_ADDR_MASK + 1)
|
||||
FWP_RANGE_TYPE = (FWP_V6_ADDR_MASK + 1)
|
||||
FWP_DATA_TYPE_MAX = (FWP_RANGE_TYPE + 1)
|
||||
)
|
||||
|
||||
var FWPM_CONDITION_IP_PROTOCOL = windows.GUID{
|
||||
Data1: 0x3971ef2b,
|
||||
Data2: 0x623e,
|
||||
Data3: 0x4f9a,
|
||||
Data4: [8]byte{0x8c, 0xb1, 0x6e, 0x79, 0xb8, 0x06, 0xb9, 0xa7},
|
||||
}
|
||||
|
||||
var FWPM_CONDITION_IP_REMOTE_PORT = windows.GUID{
|
||||
Data1: 0xc35a604d,
|
||||
Data2: 0xd22b,
|
||||
Data3: 0x4e1a,
|
||||
Data4: [8]byte{0x91, 0xb4, 0x68, 0xf6, 0x74, 0xee, 0x67, 0x4b},
|
||||
}
|
||||
|
||||
var FWPM_LAYER_ALE_AUTH_CONNECT_V4 = windows.GUID{
|
||||
Data1: 0xc38d57d1,
|
||||
Data2: 0x05a7,
|
||||
Data3: 0x4c33,
|
||||
Data4: [8]byte{0x90, 0x4f, 0x7f, 0xbc, 0xee, 0xe6, 0x0e, 0x82},
|
||||
}
|
||||
|
||||
var FWPM_CONDITION_LOCAL_INTERFACE_INDEX = windows.GUID{
|
||||
Data1: 0x667fd755,
|
||||
Data2: 0xd695,
|
||||
Data3: 0x434a,
|
||||
Data4: [8]byte{0x8a, 0xf5, 0xd3, 0x83, 0x5a, 0x12, 0x59, 0xbc},
|
||||
}
|
||||
|
||||
var FWPM_LAYER_ALE_AUTH_CONNECT_V6 = windows.GUID{
|
||||
Data1: 0x4a72393b,
|
||||
Data2: 0x319f,
|
||||
Data3: 0x44bc,
|
||||
Data4: [8]byte{0x84, 0xc3, 0xba, 0x54, 0xdc, 0xb3, 0xb6, 0xb4},
|
||||
}
|
||||
|
||||
var FWPM_CONDITION_ALE_APP_ID = windows.GUID{
|
||||
Data1: 0xd78e1e87,
|
||||
Data2: 0x8644,
|
||||
Data3: 0x4ea5,
|
||||
Data4: [8]byte{0x94, 0x37, 0xd8, 0x09, 0xec, 0xef, 0xc9, 0x71},
|
||||
}
|
||||
|
||||
const (
|
||||
IPPROTO_UDP uint32 = 17
|
||||
)
|
||||
|
||||
const (
|
||||
FWP_ACTION_FLAG_TERMINATING uint32 = 0x00001000
|
||||
FWP_ACTION_BLOCK uint32 = (0x00000001 | FWP_ACTION_FLAG_TERMINATING)
|
||||
FWP_ACTION_PERMIT uint32 = (0x00000002 | FWP_ACTION_FLAG_TERMINATING)
|
||||
)
|
||||
|
||||
const (
|
||||
FWPM_FILTER_FLAG_NONE = 0x00000000
|
||||
FWPM_FILTER_FLAG_PERSISTENT = 0x00000001
|
||||
FWPM_FILTER_FLAG_BOOTTIME = 0x00000002
|
||||
FWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT = 0x00000004
|
||||
FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT = 0x00000008
|
||||
FWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED = 0x00000010
|
||||
FWPM_FILTER_FLAG_DISABLED = 0x00000020
|
||||
FWPM_FILTER_FLAG_INDEXED = 0x00000040
|
||||
FWPM_FILTER_FLAG_HAS_SECURITY_REALM_PROVIDER_CONTEXT = 0x00000080
|
||||
FWPM_FILTER_FLAG_SYSTEMOS_ONLY = 0x00000100
|
||||
FWPM_FILTER_FLAG_GAMEOS_ONLY = 0x00000200
|
||||
FWPM_FILTER_FLAG_SILENT_MODE = 0x00000400
|
||||
FWPM_FILTER_FLAG_IPSEC_NO_ACQUIRE_INITIATE = 0x00000800
|
||||
)
|
46
internal/winsys/helper.go
Normal file
46
internal/winsys/helper.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
//go:build windows
|
||||
|
||||
package winsys
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
"github.com/sagernet/sing/common"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func CreateDisplayData(name, description string) FWPM_DISPLAY_DATA0 {
|
||||
namePtr, err := windows.UTF16PtrFromString(name)
|
||||
common.Must(err)
|
||||
|
||||
descriptionPtr, err := windows.UTF16PtrFromString(description)
|
||||
common.Must(err)
|
||||
|
||||
return FWPM_DISPLAY_DATA0{
|
||||
Name: namePtr,
|
||||
Description: descriptionPtr,
|
||||
}
|
||||
}
|
||||
|
||||
func GetCurrentProcessAppID() (*FWP_BYTE_BLOB, error) {
|
||||
currentFile, err := os.Executable()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
curFilePtr, err := windows.UTF16PtrFromString(currentFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
windows.GetCurrentProcessId()
|
||||
|
||||
var appID *FWP_BYTE_BLOB
|
||||
err = FwpmGetAppIdFromFileName0(curFilePtr, unsafe.Pointer(&appID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return appID, nil
|
||||
}
|
5
internal/winsys/mksyscall.go
Normal file
5
internal/winsys/mksyscall.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
//go:build windows
|
||||
|
||||
package winsys
|
||||
|
||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall_windows.go
|
19
internal/winsys/syscall_windows.go
Normal file
19
internal/winsys/syscall_windows.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package winsys
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmengineopen0
|
||||
//sys FwpmEngineOpen0(serverName *uint16, authnService uint32, authIdentity *uintptr, session *FWPM_SESSION0, engineHandle unsafe.Pointer) (err error) [failretval!=0] = fwpuclnt.FwpmEngineOpen0
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/fwpmu/nf-fwpmu-fwpmengineclose0
|
||||
//sys FwpmEngineClose0(engineHandle uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmEngineClose0
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmsublayeradd0
|
||||
//sys FwpmSubLayerAdd0(engineHandle uintptr, subLayer *FWPM_SUBLAYER0, sd uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmSubLayerAdd0
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmfilteradd0
|
||||
//sys FwpmFilterAdd0(engineHandle uintptr, filter *FWPM_FILTER0, sd uintptr, id *uint64) (err error) [failretval!=0] = fwpuclnt.FwpmFilterAdd0
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmgetappidfromfilename0
|
||||
//sys FwpmGetAppIdFromFileName0(fileName *uint16, appID unsafe.Pointer) (err error) [failretval!=0] = fwpuclnt.FwpmGetAppIdFromFileName0
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmfreememory0
|
||||
//sys FwpmFreeMemory0(p unsafe.Pointer) = fwpuclnt.FwpmFreeMemory0
|
99
internal/winsys/types_windows.go
Normal file
99
internal/winsys/types_windows.go
Normal file
|
@ -0,0 +1,99 @@
|
|||
package winsys
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
type (
|
||||
BOOL int32
|
||||
HANDLE uintptr
|
||||
DWORD uint32
|
||||
PDWORD uintptr
|
||||
ULONG uint32
|
||||
ULONG_PTR uintptr
|
||||
HMODULE HANDLE
|
||||
)
|
||||
|
||||
type MIB_IPFORWARDROW struct {
|
||||
ForwardDest uint32
|
||||
ForwardMask uint32
|
||||
ForwardPolicy uint32
|
||||
ForwardNextHop uint32
|
||||
ForwardIfIndex uint32
|
||||
ForwardType uint32
|
||||
ForwardProto uint32
|
||||
ForwardAge uint32
|
||||
ForwardNextHopAS uint32
|
||||
ForwardMetric1 uint32
|
||||
ForwardMetric2 uint32
|
||||
ForwardMetric3 uint32
|
||||
ForwardMetric4 uint32
|
||||
ForwardMetric5 uint32
|
||||
}
|
||||
|
||||
type FWPM_DISPLAY_DATA0 struct {
|
||||
Name *uint16
|
||||
Description *uint16
|
||||
}
|
||||
|
||||
type FWPM_SESSION0 struct {
|
||||
SessionKey windows.GUID
|
||||
DisplayData FWPM_DISPLAY_DATA0
|
||||
Flags uint32
|
||||
TxnWaitTimeoutInMSec uint32
|
||||
ProcessId uint32
|
||||
Sid *windows.SID
|
||||
Username *uint16
|
||||
KernelMode int32
|
||||
}
|
||||
|
||||
type FWP_BYTE_BLOB struct {
|
||||
size uint32
|
||||
data *uint8
|
||||
}
|
||||
|
||||
type FWPM_SUBLAYER0 struct {
|
||||
SubLayerKey windows.GUID // Windows type: GUID
|
||||
DisplayData FWPM_DISPLAY_DATA0
|
||||
Flags uint32
|
||||
ProviderKey *windows.GUID // Windows type: *GUID
|
||||
ProviderData FWP_BYTE_BLOB
|
||||
Weight uint16
|
||||
}
|
||||
|
||||
type FWP_VALUE0 struct {
|
||||
Type uint32
|
||||
Value uintptr
|
||||
}
|
||||
|
||||
type FWP_CONDITION_VALUE0 FWP_VALUE0
|
||||
|
||||
type FWPM_FILTER_CONDITION0 struct {
|
||||
FieldKey windows.GUID // Windows type: GUID
|
||||
MatchType uint32
|
||||
ConditionValue FWP_CONDITION_VALUE0
|
||||
}
|
||||
|
||||
type FWPM_ACTION0 struct {
|
||||
Type uint32
|
||||
Value windows.GUID
|
||||
}
|
||||
|
||||
type FWPM_FILTER0 struct {
|
||||
FilterKey windows.GUID
|
||||
DisplayData FWPM_DISPLAY_DATA0
|
||||
Flags uint32
|
||||
ProviderKey *windows.GUID
|
||||
ProviderData FWP_BYTE_BLOB
|
||||
LayerKey windows.GUID
|
||||
SubLayerKey windows.GUID
|
||||
Weight FWP_VALUE0
|
||||
NumFilterConditions uint32
|
||||
FilterCondition *FWPM_FILTER_CONDITION0
|
||||
Action FWPM_ACTION0
|
||||
Offset1 [4]byte
|
||||
Context windows.GUID
|
||||
Reserved *windows.GUID
|
||||
FilterId uint64
|
||||
EffectiveWeight FWP_VALUE0
|
||||
}
|
94
internal/winsys/zsyscall_windows.go
Normal file
94
internal/winsys/zsyscall_windows.go
Normal file
|
@ -0,0 +1,94 @@
|
|||
// Code generated by 'go generate'; DO NOT EDIT.
|
||||
|
||||
package winsys
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
// Do the interface allocations only once for common
|
||||
// Errno values.
|
||||
const (
|
||||
errnoERROR_IO_PENDING = 997
|
||||
)
|
||||
|
||||
var (
|
||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||
errERROR_EINVAL error = syscall.EINVAL
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
// allocations at runtime.
|
||||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return errERROR_EINVAL
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
// TODO: add more here, after collecting data on the common
|
||||
// error values see on Windows. (perhaps when running
|
||||
// all.bat?)
|
||||
return e
|
||||
}
|
||||
|
||||
var (
|
||||
modfwpuclnt = windows.NewLazySystemDLL("fwpuclnt.dll")
|
||||
|
||||
procFwpmEngineClose0 = modfwpuclnt.NewProc("FwpmEngineClose0")
|
||||
procFwpmEngineOpen0 = modfwpuclnt.NewProc("FwpmEngineOpen0")
|
||||
procFwpmFilterAdd0 = modfwpuclnt.NewProc("FwpmFilterAdd0")
|
||||
procFwpmFreeMemory0 = modfwpuclnt.NewProc("FwpmFreeMemory0")
|
||||
procFwpmGetAppIdFromFileName0 = modfwpuclnt.NewProc("FwpmGetAppIdFromFileName0")
|
||||
procFwpmSubLayerAdd0 = modfwpuclnt.NewProc("FwpmSubLayerAdd0")
|
||||
)
|
||||
|
||||
func FwpmEngineClose0(engineHandle uintptr) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procFwpmEngineClose0.Addr(), 1, uintptr(engineHandle), 0, 0)
|
||||
if r1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func FwpmEngineOpen0(serverName *uint16, authnService uint32, authIdentity *uintptr, session *FWPM_SESSION0, engineHandle unsafe.Pointer) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procFwpmEngineOpen0.Addr(), 5, uintptr(unsafe.Pointer(serverName)), uintptr(authnService), uintptr(unsafe.Pointer(authIdentity)), uintptr(unsafe.Pointer(session)), uintptr(engineHandle), 0)
|
||||
if r1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func FwpmFilterAdd0(engineHandle uintptr, filter *FWPM_FILTER0, sd uintptr, id *uint64) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procFwpmFilterAdd0.Addr(), 4, uintptr(engineHandle), uintptr(unsafe.Pointer(filter)), uintptr(sd), uintptr(unsafe.Pointer(id)), 0, 0)
|
||||
if r1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func FwpmFreeMemory0(p unsafe.Pointer) {
|
||||
syscall.Syscall(procFwpmFreeMemory0.Addr(), 1, uintptr(p), 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func FwpmGetAppIdFromFileName0(fileName *uint16, appID unsafe.Pointer) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procFwpmGetAppIdFromFileName0.Addr(), 2, uintptr(unsafe.Pointer(fileName)), uintptr(appID), 0)
|
||||
if r1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func FwpmSubLayerAdd0(engineHandle uintptr, subLayer *FWPM_SUBLAYER0, sd uintptr) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procFwpmSubLayerAdd0.Addr(), 3, uintptr(engineHandle), uintptr(unsafe.Pointer(subLayer)), uintptr(sd))
|
||||
if r1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
249
tun_windows.go
249
tun_windows.go
|
@ -4,6 +4,8 @@ import (
|
|||
"crypto/md5"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"sync"
|
||||
|
@ -12,8 +14,10 @@ import (
|
|||
"unsafe"
|
||||
|
||||
"github.com/sagernet/sing-tun/internal/winipcfg"
|
||||
"github.com/sagernet/sing-tun/internal/winsys"
|
||||
"github.com/sagernet/sing-tun/internal/wintun"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/windnsapi"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
@ -21,14 +25,15 @@ import (
|
|||
var TunnelType = "sing-tun"
|
||||
|
||||
type NativeTun struct {
|
||||
adapter *wintun.Adapter
|
||||
options Options
|
||||
session wintun.Session
|
||||
readWait windows.Handle
|
||||
rate rateJuggler
|
||||
running sync.WaitGroup
|
||||
closeOnce sync.Once
|
||||
close int32
|
||||
adapter *wintun.Adapter
|
||||
options Options
|
||||
session wintun.Session
|
||||
readWait windows.Handle
|
||||
rate rateJuggler
|
||||
running sync.WaitGroup
|
||||
closeOnce sync.Once
|
||||
close int32
|
||||
fwpmSession uintptr
|
||||
}
|
||||
|
||||
func Open(options Options) (WinTun, error) {
|
||||
|
@ -78,16 +83,41 @@ func (t *NativeTun) configure() error {
|
|||
}
|
||||
}
|
||||
if t.options.AutoRoute {
|
||||
if len(t.options.Inet4Address) > 0 {
|
||||
err := luid.AddRoute(netip.PrefixFrom(netip.IPv4Unspecified(), 0), netip.IPv4Unspecified(), 0)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set ipv4 route")
|
||||
if t.options.StrictRoute {
|
||||
if len(t.options.Inet4Address) > 0 {
|
||||
for _, prefix := range []netip.Prefix{
|
||||
netip.MustParsePrefix("0.0.0.0/1"),
|
||||
netip.MustParsePrefix("128.0.0.0/1"),
|
||||
} {
|
||||
err := luid.AddRoute(prefix, netip.IPv4Unspecified(), 0)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set ipv4 route")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(t.options.Inet6Address) > 0 {
|
||||
err := luid.AddRoute(netip.PrefixFrom(netip.IPv6Unspecified(), 0), netip.IPv6Unspecified(), 0)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set ipv6 route")
|
||||
if len(t.options.Inet6Address) > 0 {
|
||||
for _, prefix := range []netip.Prefix{
|
||||
netip.MustParsePrefix("::/1"),
|
||||
netip.MustParsePrefix("8000::/1"),
|
||||
} {
|
||||
err := luid.AddRoute(prefix, netip.IPv6Unspecified(), 0)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set ipv6 route")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(t.options.Inet4Address) > 0 {
|
||||
err := luid.AddRoute(netip.PrefixFrom(netip.IPv4Unspecified(), 0), netip.IPv4Unspecified(), 0)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set ipv4 route")
|
||||
}
|
||||
}
|
||||
if len(t.options.Inet6Address) > 0 {
|
||||
err := luid.AddRoute(netip.PrefixFrom(netip.IPv6Unspecified(), 0), netip.IPv6Unspecified(), 0)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set ipv6 route")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +161,187 @@ func (t *NativeTun) configure() error {
|
|||
}
|
||||
}
|
||||
|
||||
if t.options.AutoRoute {
|
||||
var engine uintptr
|
||||
session := &winsys.FWPM_SESSION0{Flags: winsys.FWPM_SESSION_FLAG_DYNAMIC}
|
||||
err := winsys.FwpmEngineOpen0(nil, winsys.RPC_C_AUTHN_DEFAULT, nil, session, unsafe.Pointer(&engine))
|
||||
if err != nil {
|
||||
return os.NewSyscallError("FwpmEngineOpen0", err)
|
||||
}
|
||||
t.fwpmSession = engine
|
||||
|
||||
subLayerKey, err := windows.GenerateGUID()
|
||||
if err != nil {
|
||||
return os.NewSyscallError("CoCreateGuid", err)
|
||||
}
|
||||
|
||||
subLayer := winsys.FWPM_SUBLAYER0{}
|
||||
subLayer.SubLayerKey = subLayerKey
|
||||
subLayer.DisplayData = winsys.CreateDisplayData("sing-box", "auto-route rules")
|
||||
subLayer.Weight = math.MaxUint16
|
||||
err = winsys.FwpmSubLayerAdd0(engine, &subLayer, 0)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("FwpmSubLayerAdd0", err)
|
||||
}
|
||||
|
||||
processAppID, err := winsys.GetCurrentProcessAppID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer winsys.FwpmFreeMemory0(unsafe.Pointer(&processAppID))
|
||||
|
||||
var filterId uint64
|
||||
permitCondition := make([]winsys.FWPM_FILTER_CONDITION0, 1)
|
||||
permitCondition[0].FieldKey = winsys.FWPM_CONDITION_ALE_APP_ID
|
||||
permitCondition[0].MatchType = winsys.FWP_MATCH_EQUAL
|
||||
permitCondition[0].ConditionValue.Type = winsys.FWP_BYTE_BLOB_TYPE
|
||||
permitCondition[0].ConditionValue.Value = uintptr(unsafe.Pointer(processAppID))
|
||||
|
||||
permitFilter4 := winsys.FWPM_FILTER0{}
|
||||
permitFilter4.FilterCondition = &permitCondition[0]
|
||||
permitFilter4.NumFilterConditions = 1
|
||||
permitFilter4.DisplayData = winsys.CreateDisplayData("sing-box", "protect ipv4")
|
||||
permitFilter4.SubLayerKey = subLayerKey
|
||||
permitFilter4.LayerKey = winsys.FWPM_LAYER_ALE_AUTH_CONNECT_V4
|
||||
permitFilter4.Action.Type = winsys.FWP_ACTION_PERMIT
|
||||
permitFilter4.Weight.Type = winsys.FWP_UINT8
|
||||
permitFilter4.Weight.Value = uintptr(12)
|
||||
permitFilter4.Flags = winsys.FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT
|
||||
err = winsys.FwpmFilterAdd0(engine, &permitFilter4, 0, &filterId)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("FwpmFilterAdd0", err)
|
||||
}
|
||||
|
||||
permitFilter6 := winsys.FWPM_FILTER0{}
|
||||
permitFilter6.FilterCondition = &permitCondition[0]
|
||||
permitFilter6.NumFilterConditions = 1
|
||||
permitFilter6.DisplayData = winsys.CreateDisplayData("sing-box", "protect ipv6")
|
||||
permitFilter6.SubLayerKey = subLayerKey
|
||||
permitFilter6.LayerKey = winsys.FWPM_LAYER_ALE_AUTH_CONNECT_V6
|
||||
permitFilter6.Action.Type = winsys.FWP_ACTION_PERMIT
|
||||
permitFilter6.Weight.Type = winsys.FWP_UINT8
|
||||
permitFilter6.Weight.Value = uintptr(12)
|
||||
permitFilter6.Flags = winsys.FWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT
|
||||
err = winsys.FwpmFilterAdd0(engine, &permitFilter6, 0, &filterId)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("FwpmFilterAdd0", err)
|
||||
}
|
||||
|
||||
if len(t.options.Inet4Address) == 0 {
|
||||
blockFilter := winsys.FWPM_FILTER0{}
|
||||
blockFilter.DisplayData = winsys.CreateDisplayData("sing-box", "block ipv4")
|
||||
blockFilter.SubLayerKey = subLayerKey
|
||||
blockFilter.LayerKey = winsys.FWPM_LAYER_ALE_AUTH_CONNECT_V4
|
||||
blockFilter.Action.Type = winsys.FWP_ACTION_BLOCK
|
||||
blockFilter.Weight.Type = winsys.FWP_UINT8
|
||||
blockFilter.Weight.Value = uintptr(13)
|
||||
err = winsys.FwpmFilterAdd0(engine, &blockFilter, 0, &filterId)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("FwpmFilterAdd0", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(t.options.Inet6Address) == 0 {
|
||||
blockFilter := winsys.FWPM_FILTER0{}
|
||||
blockFilter.DisplayData = winsys.CreateDisplayData("sing-box", "block ipv6")
|
||||
blockFilter.SubLayerKey = subLayerKey
|
||||
blockFilter.LayerKey = winsys.FWPM_LAYER_ALE_AUTH_CONNECT_V6
|
||||
blockFilter.Action.Type = winsys.FWP_ACTION_BLOCK
|
||||
blockFilter.Weight.Type = winsys.FWP_UINT8
|
||||
blockFilter.Weight.Value = uintptr(13)
|
||||
err = winsys.FwpmFilterAdd0(engine, &blockFilter, 0, &filterId)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("FwpmFilterAdd0", err)
|
||||
}
|
||||
}
|
||||
|
||||
netInterface, err := net.InterfaceByName(t.options.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tunCondition := make([]winsys.FWPM_FILTER_CONDITION0, 1)
|
||||
tunCondition[0].FieldKey = winsys.FWPM_CONDITION_LOCAL_INTERFACE_INDEX
|
||||
tunCondition[0].MatchType = winsys.FWP_MATCH_EQUAL
|
||||
tunCondition[0].ConditionValue.Type = winsys.FWP_UINT32
|
||||
tunCondition[0].ConditionValue.Value = uintptr(uint32(netInterface.Index))
|
||||
|
||||
if len(t.options.Inet4Address) > 0 {
|
||||
tunFilter4 := winsys.FWPM_FILTER0{}
|
||||
tunFilter4.FilterCondition = &tunCondition[0]
|
||||
tunFilter4.NumFilterConditions = 1
|
||||
tunFilter4.DisplayData = winsys.CreateDisplayData("sing-box", "allow ipv4")
|
||||
tunFilter4.SubLayerKey = subLayerKey
|
||||
tunFilter4.LayerKey = winsys.FWPM_LAYER_ALE_AUTH_CONNECT_V4
|
||||
tunFilter4.Action.Type = winsys.FWP_ACTION_PERMIT
|
||||
tunFilter4.Weight.Type = winsys.FWP_UINT8
|
||||
tunFilter4.Weight.Value = uintptr(11)
|
||||
err = winsys.FwpmFilterAdd0(engine, &tunFilter4, 0, &filterId)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("FwpmFilterAdd0", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(t.options.Inet6Address) > 0 {
|
||||
tunFilter6 := winsys.FWPM_FILTER0{}
|
||||
tunFilter6.FilterCondition = &tunCondition[0]
|
||||
tunFilter6.NumFilterConditions = 1
|
||||
tunFilter6.DisplayData = winsys.CreateDisplayData("sing-box", "allow ipv6")
|
||||
tunFilter6.SubLayerKey = subLayerKey
|
||||
tunFilter6.LayerKey = winsys.FWPM_LAYER_ALE_AUTH_CONNECT_V6
|
||||
tunFilter6.Action.Type = winsys.FWP_ACTION_PERMIT
|
||||
tunFilter6.Weight.Type = winsys.FWP_UINT8
|
||||
tunFilter6.Weight.Value = uintptr(11)
|
||||
err = winsys.FwpmFilterAdd0(engine, &tunFilter6, 0, &filterId)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("FwpmFilterAdd0", err)
|
||||
}
|
||||
}
|
||||
|
||||
blockDNSCondition := make([]winsys.FWPM_FILTER_CONDITION0, 2)
|
||||
blockDNSCondition[0].FieldKey = winsys.FWPM_CONDITION_IP_PROTOCOL
|
||||
blockDNSCondition[0].MatchType = winsys.FWP_MATCH_EQUAL
|
||||
blockDNSCondition[0].ConditionValue.Type = winsys.FWP_UINT8
|
||||
blockDNSCondition[0].ConditionValue.Value = uintptr(uint8(winsys.IPPROTO_UDP))
|
||||
blockDNSCondition[1].FieldKey = winsys.FWPM_CONDITION_IP_REMOTE_PORT
|
||||
blockDNSCondition[1].MatchType = winsys.FWP_MATCH_EQUAL
|
||||
blockDNSCondition[1].ConditionValue.Type = winsys.FWP_UINT16
|
||||
blockDNSCondition[1].ConditionValue.Value = uintptr(uint16(53))
|
||||
|
||||
blockDNSFilter4 := winsys.FWPM_FILTER0{}
|
||||
blockDNSFilter4.FilterCondition = &blockDNSCondition[0]
|
||||
blockDNSFilter4.NumFilterConditions = 2
|
||||
blockDNSFilter4.DisplayData = winsys.CreateDisplayData("sing-box", "block ipv4 dns")
|
||||
blockDNSFilter4.SubLayerKey = subLayerKey
|
||||
blockDNSFilter4.LayerKey = winsys.FWPM_LAYER_ALE_AUTH_CONNECT_V4
|
||||
blockDNSFilter4.Action.Type = winsys.FWP_ACTION_BLOCK
|
||||
blockDNSFilter4.Weight.Type = winsys.FWP_UINT8
|
||||
blockDNSFilter4.Weight.Value = uintptr(10)
|
||||
err = winsys.FwpmFilterAdd0(engine, &blockDNSFilter4, 0, &filterId)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("FwpmFilterAdd0", err)
|
||||
}
|
||||
|
||||
blockDNSFilter6 := winsys.FWPM_FILTER0{}
|
||||
blockDNSFilter6.FilterCondition = &blockDNSCondition[0]
|
||||
blockDNSFilter6.NumFilterConditions = 2
|
||||
blockDNSFilter6.DisplayData = winsys.CreateDisplayData("sing-box", "block ipv6 dns")
|
||||
blockDNSFilter6.SubLayerKey = subLayerKey
|
||||
blockDNSFilter6.LayerKey = winsys.FWPM_LAYER_ALE_AUTH_CONNECT_V6
|
||||
blockDNSFilter6.Action.Type = winsys.FWP_ACTION_BLOCK
|
||||
blockDNSFilter6.Weight.Type = winsys.FWP_UINT8
|
||||
blockDNSFilter6.Weight.Value = uintptr(10)
|
||||
err = winsys.FwpmFilterAdd0(engine, &blockDNSFilter6, 0, &filterId)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("FwpmFilterAdd0", err)
|
||||
}
|
||||
|
||||
err = windnsapi.FlushResolverCache()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -269,6 +480,10 @@ func (t *NativeTun) Close() error {
|
|||
t.running.Wait()
|
||||
t.session.End()
|
||||
t.adapter.Close()
|
||||
if t.fwpmSession != 0 {
|
||||
winsys.FwpmEngineClose0(t.fwpmSession)
|
||||
}
|
||||
windnsapi.FlushResolverCache()
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue