safing-portmaster/service/splittun/module.go
Alexandr Stelnykovych ee8cde31f6 feat: Add Split Tunnel feature (Windows PoC)
Implement initial proof-of-concept for split tunnel functionality on Windows,
allowing applications to route traffic through a designated network interface
while bypassing default system routing.

Features:
- Split tunnel module with TCP/UDP proxy infrastructure
- Firewall integration with split tunnel verdict handling
- SplitTunneling context attached to connections
- Configuration options: enable toggle, interface selection, and policy rules
- UI display of split tunnel connection details in connection info panel
- Subsystem configuration for user-level access

Windows-specific implementation:
- Uses proxy-based interface routing on Windows
- Automatic or manual interface detection and binding
- Support for IPv4 and IPv6 traffic

Note: Linux implementation is under development. SPN takes precedence over
split tunnel when both are enabled, ensuring SPN connections bypass this feature.
2026-04-24 18:04:01 +03:00

68 lines
1.2 KiB
Go

package splittun
import (
"errors"
"sync/atomic"
"github.com/safing/portmaster/service/mgr"
)
const SplitTunPort = 719
type SplitTunModule struct {
mgr *mgr.Manager
instance instance
}
var (
module *SplitTunModule
shimLoaded atomic.Bool
ready atomic.Bool // ready indicates whether the module is fully initialized and ready to handle requests.
)
func IsReady() bool {
return ready.Load()
}
func New(instance instance) (*SplitTunModule, error) {
if !shimLoaded.CompareAndSwap(false, true) {
return nil, errors.New("only one instance allowed")
}
m := mgr.New("SplitTunModule")
module = &SplitTunModule{
mgr: m,
instance: instance,
}
if err := prep(); err != nil {
return nil, err
}
return module, nil
}
func prep() error {
return nil
}
func (s *SplitTunModule) Manager() *mgr.Manager {
return s.mgr
}
func (s *SplitTunModule) Start() error {
err := startProxies(s.mgr)
if err != nil {
return err
}
ready.Store(true)
return nil
}
func (s *SplitTunModule) Stop() error {
ready.Store(false)
return stopProxies()
}
// INSTANCE
type instance interface{}