Fix windows firewall for system stack

This commit is contained in:
世界 2023-05-03 23:03:51 +08:00
parent 209ec123ca
commit 6999634511
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
4 changed files with 88 additions and 25 deletions

View file

@ -15,19 +15,20 @@ type Stack interface {
} }
type StackOptions struct { type StackOptions struct {
Context context.Context Context context.Context
Tun Tun Tun Tun
Name string Name string
MTU uint32 MTU uint32
Inet4Address []netip.Prefix Inet4Address []netip.Prefix
Inet6Address []netip.Prefix Inet6Address []netip.Prefix
EndpointIndependentNat bool EndpointIndependentNat bool
UDPTimeout int64 UDPTimeout int64
Router Router Router Router
Handler Handler Handler Handler
Logger logger.Logger Logger logger.Logger
ForwarderBindInterface bool ForwarderBindInterface bool
InterfaceFinder control.InterfaceFinder InterfaceFinder control.InterfaceFinder
ExperimentalFixWindowsFirewall bool
} }
func NewStack( func NewStack(

View file

@ -42,6 +42,7 @@ type System struct {
routeMapping *RouteMapping routeMapping *RouteMapping
bindInterface bool bindInterface bool
interfaceFinder control.InterfaceFinder interfaceFinder control.InterfaceFinder
fixWindowsFirewall bool
} }
type Session struct { type Session struct {
@ -53,18 +54,19 @@ type Session struct {
func NewSystem(options StackOptions) (Stack, error) { func NewSystem(options StackOptions) (Stack, error) {
stack := &System{ stack := &System{
ctx: options.Context, ctx: options.Context,
tun: options.Tun, tun: options.Tun,
tunName: options.Name, tunName: options.Name,
mtu: options.MTU, mtu: options.MTU,
udpTimeout: options.UDPTimeout, udpTimeout: options.UDPTimeout,
router: options.Router, router: options.Router,
handler: options.Handler, handler: options.Handler,
logger: options.Logger, logger: options.Logger,
inet4Prefixes: options.Inet4Address, inet4Prefixes: options.Inet4Address,
inet6Prefixes: options.Inet6Address, inet6Prefixes: options.Inet6Address,
bindInterface: options.ForwarderBindInterface, bindInterface: options.ForwarderBindInterface,
interfaceFinder: options.InterfaceFinder, interfaceFinder: options.InterfaceFinder,
fixWindowsFirewall: options.ExperimentalFixWindowsFirewall,
} }
if stack.router != nil { if stack.router != nil {
stack.routeMapping = NewRouteMapping(options.UDPTimeout) stack.routeMapping = NewRouteMapping(options.UDPTimeout)
@ -97,6 +99,12 @@ func (s *System) Close() error {
} }
func (s *System) Start() error { func (s *System) Start() error {
if s.fixWindowsFirewall {
err := fixWindowsFirewall()
if err != nil {
return E.Cause(err, "fix windows firewall for system stack")
}
}
var listener net.ListenConfig var listener net.ListenConfig
if s.bindInterface { if s.bindInterface {
listener.Control = control.Append(listener.Control, func(network, address string, conn syscall.RawConn) error { listener.Control = control.Append(listener.Control, func(network, address string, conn syscall.RawConn) error {

7
system_nonwindows.go Normal file
View file

@ -0,0 +1,7 @@
//go:build !windows
package tun
func fixWindowsFirewall() error {
return nil
}

47
system_windows.go Normal file
View file

@ -0,0 +1,47 @@
package tun
import (
"os"
"os/exec"
"path/filepath"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
"github.com/sagernet/sing/common/shell"
)
func fixWindowsFirewall() error {
const shellStringSplit = "\""
isPWSH := true
powershell, err := exec.LookPath("pwsh.exe")
if err != nil {
powershell, err = exec.LookPath("powershell.exe")
isPWSH = false
}
if err != nil {
return nil
}
ruleName := "sing-tun rule for " + os.Args[0]
commandPrefix := []string{"-NoProfile", "-NonInteractive"}
if isPWSH {
commandPrefix = append(commandPrefix, "-Command")
}
err = shell.Exec(powershell, append(commandPrefix,
F.ToString("Get-NetFirewallRule -Name ", shellStringSplit, ruleName, shellStringSplit))...).Run()
if err == nil {
return nil
}
fileName := filepath.Base(os.Args[0])
output, err := shell.Exec(powershell, append(commandPrefix,
F.ToString("New-NetFirewallRule",
" -Name ", shellStringSplit, ruleName, shellStringSplit,
" -DisplayName ", shellStringSplit, "sing-tun (", fileName, ")", shellStringSplit,
" -Program ", shellStringSplit, os.Args[0], shellStringSplit,
" -Direction Inbound",
" -Protocol TCP",
" -Action Allow"))...).Read()
if err != nil {
return E.Extend(err, output)
}
return nil
}