Files
free-turn-proxy/mobile/protect.go

48 lines
1.2 KiB
Go

package mobile
import (
"errors"
"fmt"
"sync/atomic"
"syscall"
"github.com/samosvalishe/free-turn-proxy/internal/netctl"
)
// Protector реализуется хостом для исключения сокетов клиента из VPN-туннеля (VpnService.protect).
// Без этого TURN / VK API / DNS трафик заворачивается обратно в туннель.
type Protector interface {
Protect(fd int) bool
}
var ErrProtect = errors.New("mobile: socket protect failed") //nolint:gochecknoglobals // sentinel для errors.Is
var protector atomic.Pointer[Protector]
// SetProtect устанавливает обработчик защиты сокетов хоста (nil - no-op).
func SetProtect(p Protector) {
if p == nil {
protector.Store(nil)
netctl.SetControl(nil)
return
}
protector.Store(&p)
netctl.SetControl(func(_, _ string, c syscall.RawConn) error {
ok := false
if err := c.Control(func(fd uintptr) { ok = p.Protect(int(fd)) }); err != nil {
return fmt.Errorf("socket control: %w", err)
}
if !ok {
return ErrProtect
}
return nil
})
}
func protectFD(fd int) bool {
if p := protector.Load(); p != nil {
return (*p).Protect(fd)
}
return false
}