mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-23 09:01:28 +00:00
Add tun support
This commit is contained in:
parent
18e5b0963f
commit
603264017a
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
|
@ -186,12 +186,12 @@ jobs:
|
||||||
- name: Build Xray
|
- name: Build Xray
|
||||||
run: |
|
run: |
|
||||||
mkdir -p build_assets
|
mkdir -p build_assets
|
||||||
go build -v -o build_assets/xray -trimpath -ldflags "-s -w -buildid=" ./main
|
go build -v -o build_assets/xray -trimpath -ldflags "-s -w -buildid=" -tags with_gvisor ./main
|
||||||
|
|
||||||
- name: Build background Xray on Windows
|
- name: Build background Xray on Windows
|
||||||
if: matrix.goos == 'windows'
|
if: matrix.goos == 'windows'
|
||||||
run: |
|
run: |
|
||||||
go build -v -o build_assets/wxray.exe -trimpath -ldflags "-s -w -H windowsgui -buildid=" ./main
|
go build -v -o build_assets/wxray.exe -trimpath -ldflags "-s -w -H windowsgui -buildid=" -tags with_gvisor ./main
|
||||||
|
|
||||||
- name: Build Mips softfloat Xray
|
- name: Build Mips softfloat Xray
|
||||||
if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle'
|
if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle'
|
||||||
|
|
347
app/tun/config.pb.go
Normal file
347
app/tun/config.pb.go
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.28.1
|
||||||
|
// protoc v3.21.12
|
||||||
|
// source: app/tun/config.proto
|
||||||
|
|
||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
InterfaceName string `protobuf:"bytes,1,opt,name=interface_name,json=interfaceName,proto3" json:"interface_name,omitempty"`
|
||||||
|
Inet4Address []string `protobuf:"bytes,2,rep,name=inet4_address,json=inet4Address,proto3" json:"inet4_address,omitempty"`
|
||||||
|
Inet6Address []string `protobuf:"bytes,3,rep,name=inet6_address,json=inet6Address,proto3" json:"inet6_address,omitempty"`
|
||||||
|
Mtu uint32 `protobuf:"varint,4,opt,name=mtu,proto3" json:"mtu,omitempty"`
|
||||||
|
AutoRoute bool `protobuf:"varint,5,opt,name=auto_route,json=autoRoute,proto3" json:"auto_route,omitempty"`
|
||||||
|
StrictRoute bool `protobuf:"varint,6,opt,name=strict_route,json=strictRoute,proto3" json:"strict_route,omitempty"`
|
||||||
|
Inet4RouteAddress []string `protobuf:"bytes,7,rep,name=inet4_route_address,json=inet4RouteAddress,proto3" json:"inet4_route_address,omitempty"`
|
||||||
|
Inet6RouteAddress []string `protobuf:"bytes,8,rep,name=inet6_route_address,json=inet6RouteAddress,proto3" json:"inet6_route_address,omitempty"`
|
||||||
|
EndpointIndependentNat bool `protobuf:"varint,9,opt,name=endpoint_independent_nat,json=endpointIndependentNat,proto3" json:"endpoint_independent_nat,omitempty"`
|
||||||
|
UdpTimeout int64 `protobuf:"varint,10,opt,name=udp_timeout,json=udpTimeout,proto3" json:"udp_timeout,omitempty"`
|
||||||
|
Stack string `protobuf:"bytes,11,opt,name=stack,proto3" json:"stack,omitempty"`
|
||||||
|
IncludeUid []uint32 `protobuf:"varint,12,rep,packed,name=include_uid,json=includeUid,proto3" json:"include_uid,omitempty"`
|
||||||
|
IncludeUidRange []string `protobuf:"bytes,13,rep,name=include_uid_range,json=includeUidRange,proto3" json:"include_uid_range,omitempty"`
|
||||||
|
ExcludeUid []uint32 `protobuf:"varint,14,rep,packed,name=exclude_uid,json=excludeUid,proto3" json:"exclude_uid,omitempty"`
|
||||||
|
ExcludeUidRange []string `protobuf:"bytes,15,rep,name=exclude_uid_range,json=excludeUidRange,proto3" json:"exclude_uid_range,omitempty"`
|
||||||
|
IncludeAndroidUser []int32 `protobuf:"varint,16,rep,packed,name=include_android_user,json=includeAndroidUser,proto3" json:"include_android_user,omitempty"`
|
||||||
|
IncludePackage []string `protobuf:"bytes,17,rep,name=include_package,json=includePackage,proto3" json:"include_package,omitempty"`
|
||||||
|
ExcludePackage []string `protobuf:"bytes,18,rep,name=exclude_package,json=excludePackage,proto3" json:"exclude_package,omitempty"`
|
||||||
|
// for xray
|
||||||
|
AutoDetectInterface bool `protobuf:"varint,100,opt,name=auto_detect_interface,json=autoDetectInterface,proto3" json:"auto_detect_interface,omitempty"`
|
||||||
|
OverrideAndroidVpn bool `protobuf:"varint,101,opt,name=override_android_vpn,json=overrideAndroidVpn,proto3" json:"override_android_vpn,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) Reset() {
|
||||||
|
*x = Config{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_app_tun_config_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_tun_config_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Config) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_tun_config_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetInterfaceName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.InterfaceName
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetInet4Address() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Inet4Address
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetInet6Address() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Inet6Address
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetMtu() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Mtu
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetAutoRoute() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.AutoRoute
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetStrictRoute() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.StrictRoute
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetInet4RouteAddress() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Inet4RouteAddress
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetInet6RouteAddress() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Inet6RouteAddress
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetEndpointIndependentNat() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.EndpointIndependentNat
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetUdpTimeout() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.UdpTimeout
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetStack() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Stack
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetIncludeUid() []uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.IncludeUid
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetIncludeUidRange() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.IncludeUidRange
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetExcludeUid() []uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.ExcludeUid
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetExcludeUidRange() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.ExcludeUidRange
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetIncludeAndroidUser() []int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.IncludeAndroidUser
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetIncludePackage() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.IncludePackage
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetExcludePackage() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.ExcludePackage
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetAutoDetectInterface() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.AutoDetectInterface
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetOverrideAndroidVpn() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.OverrideAndroidVpn
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_app_tun_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_app_tun_config_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x14, 0x61, 0x70, 0x70, 0x2f, 0x74, 0x75, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
|
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||||
|
0x2e, 0x74, 0x75, 0x6e, 0x22, 0xa2, 0x06, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
||||||
|
0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
|
||||||
|
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61,
|
||||||
|
0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x65, 0x74, 0x34, 0x5f,
|
||||||
|
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x69,
|
||||||
|
0x6e, 0x65, 0x74, 0x34, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x69,
|
||||||
|
0x6e, 0x65, 0x74, 0x36, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x03,
|
||||||
|
0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x65, 0x74, 0x36, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
|
||||||
|
0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6d,
|
||||||
|
0x74, 0x75, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||||
|
0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x52, 0x6f, 0x75, 0x74,
|
||||||
|
0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x5f, 0x72, 0x6f, 0x75, 0x74,
|
||||||
|
0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x52,
|
||||||
|
0x6f, 0x75, 0x74, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x65, 0x74, 0x34, 0x5f, 0x72, 0x6f,
|
||||||
|
0x75, 0x74, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28,
|
||||||
|
0x09, 0x52, 0x11, 0x69, 0x6e, 0x65, 0x74, 0x34, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x64, 0x64,
|
||||||
|
0x72, 0x65, 0x73, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x65, 0x74, 0x36, 0x5f, 0x72, 0x6f,
|
||||||
|
0x75, 0x74, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28,
|
||||||
|
0x09, 0x52, 0x11, 0x69, 0x6e, 0x65, 0x74, 0x36, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x41, 0x64, 0x64,
|
||||||
|
0x72, 0x65, 0x73, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
|
0x5f, 0x69, 0x6e, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x74,
|
||||||
|
0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
|
0x49, 0x6e, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x74, 0x12, 0x1f,
|
||||||
|
0x0a, 0x0b, 0x75, 0x64, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x0a, 0x20,
|
||||||
|
0x01, 0x28, 0x03, 0x52, 0x0a, 0x75, 0x64, 0x70, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12,
|
||||||
|
0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||||
|
0x73, 0x74, 0x61, 0x63, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65,
|
||||||
|
0x5f, 0x75, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0a, 0x69, 0x6e, 0x63, 0x6c,
|
||||||
|
0x75, 0x64, 0x65, 0x55, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64,
|
||||||
|
0x65, 0x5f, 0x75, 0x69, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x0d, 0x20, 0x03, 0x28,
|
||||||
|
0x09, 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x55, 0x69, 0x64, 0x52, 0x61, 0x6e,
|
||||||
|
0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x75, 0x69,
|
||||||
|
0x64, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x0a, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65,
|
||||||
|
0x55, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x75,
|
||||||
|
0x69, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f,
|
||||||
|
0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x55, 0x69, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12,
|
||||||
|
0x30, 0x0a, 0x14, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
|
||||||
|
0x69, 0x64, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, 0x10, 0x20, 0x03, 0x28, 0x05, 0x52, 0x12, 0x69,
|
||||||
|
0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x55, 0x73, 0x65,
|
||||||
|
0x72, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x61, 0x63,
|
||||||
|
0x6b, 0x61, 0x67, 0x65, 0x18, 0x11, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c,
|
||||||
|
0x75, 0x64, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78,
|
||||||
|
0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x12, 0x20,
|
||||||
|
0x03, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x61, 0x63, 0x6b,
|
||||||
|
0x61, 0x67, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x74, 0x65,
|
||||||
|
0x63, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x64, 0x20, 0x01,
|
||||||
|
0x28, 0x08, 0x52, 0x13, 0x61, 0x75, 0x74, 0x6f, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x49, 0x6e,
|
||||||
|
0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6f, 0x76, 0x65, 0x72, 0x72,
|
||||||
|
0x69, 0x64, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x76, 0x70, 0x6e, 0x18,
|
||||||
|
0x65, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x41,
|
||||||
|
0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x56, 0x70, 0x6e, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d,
|
||||||
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x74, 0x75, 0x6e, 0x50, 0x01, 0x5a,
|
||||||
|
0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73,
|
||||||
|
0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x74,
|
||||||
|
0x75, 0x6e, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x54, 0x75,
|
||||||
|
0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_app_tun_config_proto_rawDescOnce sync.Once
|
||||||
|
file_app_tun_config_proto_rawDescData = file_app_tun_config_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_app_tun_config_proto_rawDescGZIP() []byte {
|
||||||
|
file_app_tun_config_proto_rawDescOnce.Do(func() {
|
||||||
|
file_app_tun_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_tun_config_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_app_tun_config_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_app_tun_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||||
|
var file_app_tun_config_proto_goTypes = []interface{}{
|
||||||
|
(*Config)(nil), // 0: xray.app.tun.Config
|
||||||
|
}
|
||||||
|
var file_app_tun_config_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_app_tun_config_proto_init() }
|
||||||
|
func file_app_tun_config_proto_init() {
|
||||||
|
if File_app_tun_config_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_app_tun_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Config); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_app_tun_config_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 1,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_app_tun_config_proto_goTypes,
|
||||||
|
DependencyIndexes: file_app_tun_config_proto_depIdxs,
|
||||||
|
MessageInfos: file_app_tun_config_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_app_tun_config_proto = out.File
|
||||||
|
file_app_tun_config_proto_rawDesc = nil
|
||||||
|
file_app_tun_config_proto_goTypes = nil
|
||||||
|
file_app_tun_config_proto_depIdxs = nil
|
||||||
|
}
|
32
app/tun/config.proto
Normal file
32
app/tun/config.proto
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package xray.app.tun;
|
||||||
|
option csharp_namespace = "Xray.App.Tun";
|
||||||
|
option go_package = "github.com/xtls/xray-core/app/tun";
|
||||||
|
option java_package = "com.xray.app.tun";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
message Config {
|
||||||
|
string interface_name = 1;
|
||||||
|
repeated string inet4_address = 2;
|
||||||
|
repeated string inet6_address = 3;
|
||||||
|
uint32 mtu = 4;
|
||||||
|
bool auto_route = 5;
|
||||||
|
bool strict_route = 6;
|
||||||
|
repeated string inet4_route_address = 7;
|
||||||
|
repeated string inet6_route_address = 8;
|
||||||
|
bool endpoint_independent_nat = 9;
|
||||||
|
int64 udp_timeout = 10;
|
||||||
|
string stack = 11;
|
||||||
|
repeated uint32 include_uid = 12;
|
||||||
|
repeated string include_uid_range = 13;
|
||||||
|
repeated uint32 exclude_uid = 14;
|
||||||
|
repeated string exclude_uid_range = 15;
|
||||||
|
repeated int32 include_android_user = 16;
|
||||||
|
repeated string include_package = 17;
|
||||||
|
repeated string exclude_package = 18;
|
||||||
|
|
||||||
|
// for xray
|
||||||
|
bool auto_detect_interface = 100;
|
||||||
|
bool override_android_vpn = 101;
|
||||||
|
}
|
9
app/tun/errors.generated.go
Normal file
9
app/tun/errors.generated.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package tun
|
||||||
|
|
||||||
|
import "github.com/xtls/xray-core/common/errors"
|
||||||
|
|
||||||
|
type errPathObjHolder struct{}
|
||||||
|
|
||||||
|
func newError(values ...interface{}) *errors.Error {
|
||||||
|
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
||||||
|
}
|
50
app/tun/interface_finder.go
Normal file
50
app/tun/interface_finder.go
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/control"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ control.InterfaceFinder = (*myInterfaceFinder)(nil)
|
||||||
|
|
||||||
|
type myInterfaceFinder struct {
|
||||||
|
ifs []net.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *myInterfaceFinder) update() error {
|
||||||
|
ifs, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.ifs = ifs
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *myInterfaceFinder) InterfaceIndexByName(name string) (interfaceIndex int, err error) {
|
||||||
|
for _, netInterface := range f.ifs {
|
||||||
|
if netInterface.Name == name {
|
||||||
|
return netInterface.Index, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
netInterface, err := net.InterfaceByName(name)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.update()
|
||||||
|
return netInterface.Index, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *myInterfaceFinder) InterfaceNameByIndex(index int) (interfaceName string, err error) {
|
||||||
|
for _, netInterface := range f.ifs {
|
||||||
|
if netInterface.Index == index {
|
||||||
|
return netInterface.Name, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
netInterface, err := net.InterfaceByIndex(index)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.update()
|
||||||
|
return netInterface.Name, nil
|
||||||
|
}
|
42
app/tun/packet_conn.go
Normal file
42
app/tun/packet_conn.go
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
sing_common "github.com/sagernet/sing/common"
|
||||||
|
sing_buf "github.com/sagernet/sing/common/buf"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/singbridge"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PacketConn struct {
|
||||||
|
N.PacketConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PacketConn) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||||
|
packet := buf.New()
|
||||||
|
packet.Extend(buf.Size)
|
||||||
|
sPacket := sing_buf.With(packet.Bytes())
|
||||||
|
destination, err := p.ReadPacket(sPacket)
|
||||||
|
if err != nil {
|
||||||
|
packet.Release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
packet.Clear()
|
||||||
|
packet.Resize(int32(sPacket.Start()), int32(sPacket.Start()+sPacket.Len()))
|
||||||
|
destinationX := singbridge.ToDestination(destination, net.Network_UDP)
|
||||||
|
packet.UDP = &destinationX
|
||||||
|
return buf.MultiBuffer{packet}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PacketConn) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||||
|
defer buf.ReleaseMulti(mb)
|
||||||
|
for _, buffer := range mb {
|
||||||
|
destination := sing_common.PtrValueOrDefault(buffer.UDP)
|
||||||
|
err := p.PacketConn.WritePacket(sing_buf.As(buffer.Bytes()), singbridge.ToSocksaddr(destination))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
296
app/tun/tun.go
Normal file
296
app/tun/tun.go
Normal file
|
@ -0,0 +1,296 @@
|
||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/netip"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-tun"
|
||||||
|
sing_common "github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/control"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/logger"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/sing/common/ranges"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/common/singbridge"
|
||||||
|
"github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/features/routing"
|
||||||
|
features_tun "github.com/xtls/xray-core/features/tun"
|
||||||
|
"github.com/xtls/xray-core/transport"
|
||||||
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
|
||||||
|
return New(ctx, cfg.(*Config))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
var TunInitializer features_tun.Interface = (*Tun)(nil)
|
||||||
|
|
||||||
|
type Tun struct {
|
||||||
|
ctx context.Context
|
||||||
|
dispatcher routing.Dispatcher
|
||||||
|
logger logger.ContextLogger
|
||||||
|
tunOptions tun.Options
|
||||||
|
stack string
|
||||||
|
endpointIndependentNat bool
|
||||||
|
udpTimeout int64
|
||||||
|
tunIf tun.Tun
|
||||||
|
tunStack tun.Stack
|
||||||
|
networkMonitor tun.NetworkUpdateMonitor
|
||||||
|
interfaceMonitor tun.DefaultInterfaceMonitor
|
||||||
|
packageManager tun.PackageManager
|
||||||
|
interfaceFinder *myInterfaceFinder
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ctx context.Context, config *Config) (*Tun, error) {
|
||||||
|
instance := core.MustFromContext(ctx)
|
||||||
|
tunInterface := &Tun{
|
||||||
|
ctx: ctx,
|
||||||
|
dispatcher: instance.GetFeature(routing.DispatcherType()).(routing.Dispatcher),
|
||||||
|
logger: singbridge.NewLogger(newError),
|
||||||
|
stack: config.Stack,
|
||||||
|
endpointIndependentNat: config.EndpointIndependentNat,
|
||||||
|
udpTimeout: int64(5 * time.Minute.Seconds()),
|
||||||
|
interfaceFinder: new(myInterfaceFinder),
|
||||||
|
}
|
||||||
|
networkUpdateMonitor, err := tun.NewNetworkUpdateMonitor(tunInterface)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defaultInterfaceMonitor, err := tun.NewDefaultInterfaceMonitor(networkUpdateMonitor, tun.DefaultInterfaceMonitorOptions{
|
||||||
|
OverrideAndroidVPN: config.OverrideAndroidVpn,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defaultInterfaceMonitor.RegisterCallback(tunInterface.notifyNetworkUpdate)
|
||||||
|
if config.AutoDetectInterface {
|
||||||
|
networkUpdateMonitor.RegisterCallback(tunInterface.interfaceFinder.update)
|
||||||
|
const useInterfaceName = runtime.GOOS == "linux" || runtime.GOOS == "android"
|
||||||
|
bindFunc := control.BindToInterfaceFunc(tunInterface.interfaceFinder, func(network string, address string) (interfaceName string, interfaceIndex int) {
|
||||||
|
remoteAddr := M.ParseSocksaddr(address).Addr
|
||||||
|
if useInterfaceName {
|
||||||
|
return defaultInterfaceMonitor.DefaultInterfaceName(remoteAddr), -1
|
||||||
|
} else {
|
||||||
|
return "", defaultInterfaceMonitor.DefaultInterfaceIndex(remoteAddr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
internet.UseAlternativeSystemDialer(nil)
|
||||||
|
internet.RegisterDialerController(bindFunc)
|
||||||
|
internet.RegisterListenerController(bindFunc)
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "android" {
|
||||||
|
packageManage, err := tun.NewPackageManager(tunInterface)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tunInterface.packageManager = packageManage
|
||||||
|
}
|
||||||
|
tunInterface.networkMonitor = networkUpdateMonitor
|
||||||
|
tunInterface.interfaceMonitor = defaultInterfaceMonitor
|
||||||
|
tunName := config.InterfaceName
|
||||||
|
if tunName == "" {
|
||||||
|
tunName = tun.CalculateInterfaceName("")
|
||||||
|
}
|
||||||
|
tunMTU := config.Mtu
|
||||||
|
if tunMTU == 0 {
|
||||||
|
tunMTU = 9000
|
||||||
|
}
|
||||||
|
includeUID := uidToRange(config.IncludeUid)
|
||||||
|
if len(config.IncludeUidRange) > 0 {
|
||||||
|
var err error
|
||||||
|
includeUID, err = parseRange(includeUID, config.IncludeUidRange)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "parse include_uid_range")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
excludeUID := uidToRange(config.ExcludeUid)
|
||||||
|
if len(config.ExcludeUidRange) > 0 {
|
||||||
|
var err error
|
||||||
|
excludeUID, err = parseRange(excludeUID, config.ExcludeUidRange)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "parse exclude_uid_range")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if config.UdpTimeout != 0 {
|
||||||
|
tunInterface.udpTimeout = config.UdpTimeout
|
||||||
|
}
|
||||||
|
tunInterface.tunOptions = tun.Options{
|
||||||
|
Name: tunName,
|
||||||
|
Inet4Address: sing_common.Map(config.Inet4Address, netip.MustParsePrefix),
|
||||||
|
Inet6Address: sing_common.Map(config.Inet6Address, netip.MustParsePrefix),
|
||||||
|
MTU: tunMTU,
|
||||||
|
AutoRoute: config.AutoRoute,
|
||||||
|
StrictRoute: config.StrictRoute,
|
||||||
|
Inet4RouteAddress: sing_common.Map(config.Inet4RouteAddress, netip.MustParsePrefix),
|
||||||
|
Inet6RouteAddress: sing_common.Map(config.Inet6RouteAddress, netip.MustParsePrefix),
|
||||||
|
IncludeUID: includeUID,
|
||||||
|
ExcludeUID: excludeUID,
|
||||||
|
IncludeAndroidUser: sing_common.Map(config.IncludeAndroidUser, func(it int32) int {
|
||||||
|
return int(it)
|
||||||
|
}),
|
||||||
|
IncludePackage: config.IncludePackage,
|
||||||
|
ExcludePackage: config.ExcludePackage,
|
||||||
|
InterfaceMonitor: defaultInterfaceMonitor,
|
||||||
|
TableIndex: 2022,
|
||||||
|
}
|
||||||
|
return tunInterface, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tun) Type() interface{} {
|
||||||
|
return features_tun.InterfaceType()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tun) Start() error {
|
||||||
|
err := t.interfaceMonitor.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = t.networkMonitor.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "android" {
|
||||||
|
err = t.packageManager.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.tunOptions.BuildAndroidRules(t.packageManager, t)
|
||||||
|
}
|
||||||
|
tunIf, err := tun.New(t.tunOptions)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "configure tun interface")
|
||||||
|
}
|
||||||
|
t.tunIf = tunIf
|
||||||
|
t.tunStack, err = tun.NewStack(t.stack, tun.StackOptions{
|
||||||
|
Context: t.ctx,
|
||||||
|
Tun: tunIf,
|
||||||
|
MTU: t.tunOptions.MTU,
|
||||||
|
Name: t.tunOptions.Name,
|
||||||
|
Inet4Address: t.tunOptions.Inet4Address,
|
||||||
|
Inet6Address: t.tunOptions.Inet6Address,
|
||||||
|
EndpointIndependentNat: t.endpointIndependentNat,
|
||||||
|
UDPTimeout: t.udpTimeout,
|
||||||
|
Handler: t,
|
||||||
|
Logger: t.logger,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = t.tunStack.Start()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.logger.Info("tun started at ", t.tunOptions.Name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tun) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
||||||
|
sid := session.NewID()
|
||||||
|
ctx = session.ContextWithID(ctx, sid)
|
||||||
|
t.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
|
||||||
|
t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
|
||||||
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
|
Source: net.DestinationFromAddr(metadata.Source.TCPAddr()),
|
||||||
|
Conn: conn,
|
||||||
|
})
|
||||||
|
wConn := singbridge.NewConn(conn)
|
||||||
|
_ = t.dispatcher.DispatchLink(ctx, singbridge.ToDestination(metadata.Destination, net.Network_TCP), &transport.Link{
|
||||||
|
Reader: wConn,
|
||||||
|
Writer: wConn,
|
||||||
|
})
|
||||||
|
conn.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tun) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||||
|
sid := session.NewID()
|
||||||
|
ctx = session.ContextWithID(ctx, sid)
|
||||||
|
t.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source)
|
||||||
|
t.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
|
||||||
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
|
Source: net.DestinationFromAddr(metadata.Source.UDPAddr()),
|
||||||
|
})
|
||||||
|
pc := &PacketConn{conn}
|
||||||
|
_ = t.dispatcher.DispatchLink(ctx, singbridge.ToDestination(metadata.Destination, net.Network_UDP), &transport.Link{
|
||||||
|
Reader: pc,
|
||||||
|
Writer: pc,
|
||||||
|
})
|
||||||
|
conn.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tun) Close() error {
|
||||||
|
return sing_common.Close(
|
||||||
|
t.packageManager,
|
||||||
|
t.interfaceMonitor,
|
||||||
|
t.networkMonitor,
|
||||||
|
t.tunStack,
|
||||||
|
t.tunIf,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tun) OnPackagesUpdated(packages int, sharedUsers int) {
|
||||||
|
t.logger.Info("updated packages list: ", packages, " packages, ", sharedUsers, " shared users")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tun) NewError(ctx context.Context, err error) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tun) notifyNetworkUpdate(int) error {
|
||||||
|
if runtime.GOOS == "android" {
|
||||||
|
var vpnStatus string
|
||||||
|
if t.interfaceMonitor.AndroidVPNEnabled() {
|
||||||
|
vpnStatus = "enabled"
|
||||||
|
} else {
|
||||||
|
vpnStatus = "disabled"
|
||||||
|
}
|
||||||
|
t.logger.Info("updated default interface ", t.interfaceMonitor.DefaultInterfaceName(netip.IPv4Unspecified()), ", index ", t.interfaceMonitor.DefaultInterfaceIndex(netip.IPv4Unspecified()), ", vpn ", vpnStatus)
|
||||||
|
} else {
|
||||||
|
t.logger.Info("updated default interface ", t.interfaceMonitor.DefaultInterfaceName(netip.IPv4Unspecified()), ", index ", t.interfaceMonitor.DefaultInterfaceIndex(netip.IPv4Unspecified()))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func uidToRange(uidList []uint32) []ranges.Range[uint32] {
|
||||||
|
return sing_common.Map(uidList, func(uid uint32) ranges.Range[uint32] {
|
||||||
|
return ranges.NewSingle(uint32(uid))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseRange(uidRanges []ranges.Range[uint32], rangeList []string) ([]ranges.Range[uint32], error) {
|
||||||
|
for _, uidRange := range rangeList {
|
||||||
|
if !strings.Contains(uidRange, ":") {
|
||||||
|
return nil, E.New("missing ':' in range: ", uidRange)
|
||||||
|
}
|
||||||
|
subIndex := strings.Index(uidRange, ":")
|
||||||
|
if subIndex == 0 {
|
||||||
|
return nil, E.New("missing range start: ", uidRange)
|
||||||
|
} else if subIndex == len(uidRange)-1 {
|
||||||
|
return nil, E.New("missing range end: ", uidRange)
|
||||||
|
}
|
||||||
|
var start, end uint64
|
||||||
|
var err error
|
||||||
|
start, err = strconv.ParseUint(uidRange[:subIndex], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "parse range start")
|
||||||
|
}
|
||||||
|
end, err = strconv.ParseUint(uidRange[subIndex+1:], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "parse range end")
|
||||||
|
}
|
||||||
|
uidRanges = append(uidRanges, ranges.New(uint32(start), uint32(end)))
|
||||||
|
}
|
||||||
|
return uidRanges, nil
|
||||||
|
}
|
11
features/tun/tun.go
Normal file
11
features/tun/tun.go
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package tun
|
||||||
|
|
||||||
|
import "github.com/xtls/xray-core/features"
|
||||||
|
|
||||||
|
type Interface interface {
|
||||||
|
features.Feature
|
||||||
|
}
|
||||||
|
|
||||||
|
func InterfaceType() interface{} {
|
||||||
|
return (*Interface)(nil)
|
||||||
|
}
|
5
go.mod
5
go.mod
|
@ -37,6 +37,7 @@ require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
||||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
github.com/gaukas/godicttls v0.0.3 // indirect
|
github.com/gaukas/godicttls v0.0.3 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||||
github.com/google/btree v1.1.2 // indirect
|
github.com/google/btree v1.1.2 // indirect
|
||||||
|
@ -48,6 +49,10 @@ require (
|
||||||
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
|
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
|
||||||
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
|
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||||
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
|
||||||
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
||||||
|
github.com/sagernet/sing-tun v0.1.4 // indirect
|
||||||
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
||||||
golang.org/x/mod v0.10.0 // indirect
|
golang.org/x/mod v0.10.0 // indirect
|
||||||
|
|
14
go.sum
14
go.sum
|
@ -33,6 +33,8 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI
|
||||||
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
|
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
|
||||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||||
|
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||||
github.com/gaukas/godicttls v0.0.3 h1:YNDIf0d9adcxOijiLrEzpfZGAkNwLRzPaG6OjU7EITk=
|
github.com/gaukas/godicttls v0.0.3 h1:YNDIf0d9adcxOijiLrEzpfZGAkNwLRzPaG6OjU7EITk=
|
||||||
github.com/gaukas/godicttls v0.0.3/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
|
github.com/gaukas/godicttls v0.0.3/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
@ -143,12 +145,19 @@ github.com/refraction-networking/utls v1.3.2/go.mod h1:fmoaOww2bxzzEpIKOebIsnBvj
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA=
|
||||||
|
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
|
||||||
|
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.2.3 h1:V50MvZ4c3Iij2lYFWPlzL1PyipwSzjGeN9x+Ox89vpk=
|
github.com/sagernet/sing v0.2.3 h1:V50MvZ4c3Iij2lYFWPlzL1PyipwSzjGeN9x+Ox89vpk=
|
||||||
github.com/sagernet/sing v0.2.3/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
github.com/sagernet/sing v0.2.3/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
||||||
github.com/sagernet/sing v0.2.4 h1:gC8BR5sglbJZX23RtMyFa8EETP9YEUADhfbEzU1yVbo=
|
github.com/sagernet/sing v0.2.4 h1:gC8BR5sglbJZX23RtMyFa8EETP9YEUADhfbEzU1yVbo=
|
||||||
github.com/sagernet/sing v0.2.4/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
github.com/sagernet/sing v0.2.4/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.1 h1:FvdLQOqpvxHBJUcUe4fvgiYP2XLLwH5i1DtXQviVEPw=
|
github.com/sagernet/sing-shadowsocks v0.2.1 h1:FvdLQOqpvxHBJUcUe4fvgiYP2XLLwH5i1DtXQviVEPw=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.1/go.mod h1:T/OgurSjsAe+Ug3+6PprXjmgHFmJidjOvQcjXGTKb3I=
|
github.com/sagernet/sing-shadowsocks v0.2.1/go.mod h1:T/OgurSjsAe+Ug3+6PprXjmgHFmJidjOvQcjXGTKb3I=
|
||||||
|
github.com/sagernet/sing-tun v0.1.4 h1:Fa6kgvuM2fPbPu3R97S8L8NgaD5lJq3wQorNuTb5oqo=
|
||||||
|
github.com/sagernet/sing-tun v0.1.4/go.mod h1:7BrtP7NMp9FK5oVsZWg92b7yFrD+sM2+udapFurReyw=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
||||||
|
@ -192,6 +201,8 @@ github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
||||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||||
|
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=
|
||||||
github.com/xtls/reality v0.0.0-20230331223127-176a94313eda h1:psRJD2RrZbnI0OWyHvXfgYCPqlRM5q5SPDcjDoDBWhE=
|
github.com/xtls/reality v0.0.0-20230331223127-176a94313eda h1:psRJD2RrZbnI0OWyHvXfgYCPqlRM5q5SPDcjDoDBWhE=
|
||||||
github.com/xtls/reality v0.0.0-20230331223127-176a94313eda/go.mod h1:rkuAY1S9F8eI8gDiPDYvACE8e2uwkyg8qoOTuwWov7Y=
|
github.com/xtls/reality v0.0.0-20230331223127-176a94313eda/go.mod h1:rkuAY1S9F8eI8gDiPDYvACE8e2uwkyg8qoOTuwWov7Y=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
@ -251,12 +262,15 @@ golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
|
113
infra/conf/tun.go
Normal file
113
infra/conf/tun.go
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
package conf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/xtls/xray-core/app/tun"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TunConfig struct {
|
||||||
|
InterfaceName string `json:"interface_name,omitempty"`
|
||||||
|
MTU uint32 `json:"mtu,omitempty"`
|
||||||
|
Inet4Address Listable[ListenPrefix] `json:"inet4_address,omitempty"`
|
||||||
|
Inet6Address Listable[ListenPrefix] `json:"inet6_address,omitempty"`
|
||||||
|
AutoRoute bool `json:"auto_route,omitempty"`
|
||||||
|
StrictRoute bool `json:"strict_route,omitempty"`
|
||||||
|
Inet4RouteAddress Listable[ListenPrefix] `json:"inet4_route_address,omitempty"`
|
||||||
|
Inet6RouteAddress Listable[ListenPrefix] `json:"inet6_route_address,omitempty"`
|
||||||
|
IncludeUID Listable[uint32] `json:"include_uid,omitempty"`
|
||||||
|
IncludeUIDRange Listable[string] `json:"include_uid_range,omitempty"`
|
||||||
|
ExcludeUID Listable[uint32] `json:"exclude_uid,omitempty"`
|
||||||
|
ExcludeUIDRange Listable[string] `json:"exclude_uid_range,omitempty"`
|
||||||
|
IncludeAndroidUser Listable[int] `json:"include_android_user,omitempty"`
|
||||||
|
IncludePackage Listable[string] `json:"include_package,omitempty"`
|
||||||
|
ExcludePackage Listable[string] `json:"exclude_package,omitempty"`
|
||||||
|
EndpointIndependentNat bool `json:"endpoint_independent_nat,omitempty"`
|
||||||
|
UDPTimeout int64 `json:"udp_timeout,omitempty"`
|
||||||
|
Stack string `json:"stack,omitempty"`
|
||||||
|
|
||||||
|
AutoDetectInterface bool `json:"auto_detect_interface,omitempty"`
|
||||||
|
OverrideAndroidVPN bool `json:"override_android_vpn,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *TunConfig) Build() (*tun.Config, error) {
|
||||||
|
var config tun.Config
|
||||||
|
config.InterfaceName = f.InterfaceName
|
||||||
|
config.Mtu = f.MTU
|
||||||
|
config.Inet4Address = common.Map(common.Map(f.Inet4Address, ListenPrefix.Build), netip.Prefix.String)
|
||||||
|
config.Inet6Address = common.Map(common.Map(f.Inet6Address, ListenPrefix.Build), netip.Prefix.String)
|
||||||
|
config.AutoRoute = f.AutoRoute
|
||||||
|
config.StrictRoute = f.StrictRoute
|
||||||
|
config.Inet4RouteAddress = common.Map(common.Map(f.Inet4RouteAddress, ListenPrefix.Build), netip.Prefix.String)
|
||||||
|
config.Inet6RouteAddress = common.Map(common.Map(f.Inet6RouteAddress, ListenPrefix.Build), netip.Prefix.String)
|
||||||
|
config.IncludeUid = f.IncludeUID
|
||||||
|
config.IncludeUidRange = f.IncludeUIDRange
|
||||||
|
config.ExcludeUid = f.ExcludeUID
|
||||||
|
config.ExcludeUidRange = f.ExcludeUIDRange
|
||||||
|
config.IncludeAndroidUser = common.Map(f.IncludeAndroidUser, func(it int) int32 {
|
||||||
|
return int32(it)
|
||||||
|
})
|
||||||
|
config.IncludePackage = f.IncludePackage
|
||||||
|
config.ExcludePackage = f.ExcludePackage
|
||||||
|
config.EndpointIndependentNat = f.EndpointIndependentNat
|
||||||
|
config.UdpTimeout = f.UDPTimeout
|
||||||
|
config.Stack = f.Stack
|
||||||
|
// for xray
|
||||||
|
config.AutoDetectInterface = f.AutoDetectInterface
|
||||||
|
config.OverrideAndroidVpn = f.OverrideAndroidVPN
|
||||||
|
return &config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Listable[T comparable] []T
|
||||||
|
|
||||||
|
func (l Listable[T]) MarshalJSON() ([]byte, error) {
|
||||||
|
arrayList := []T(l)
|
||||||
|
if len(arrayList) == 1 {
|
||||||
|
return json.Marshal(arrayList[0])
|
||||||
|
}
|
||||||
|
return json.Marshal(arrayList)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Listable[T]) UnmarshalJSON(content []byte) error {
|
||||||
|
err := json.Unmarshal(content, (*[]T)(l))
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var singleItem T
|
||||||
|
err = json.Unmarshal(content, &singleItem)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*l = []T{singleItem}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListenPrefix netip.Prefix
|
||||||
|
|
||||||
|
func (p ListenPrefix) MarshalJSON() ([]byte, error) {
|
||||||
|
prefix := netip.Prefix(p)
|
||||||
|
if !prefix.IsValid() {
|
||||||
|
return json.Marshal(nil)
|
||||||
|
}
|
||||||
|
return json.Marshal(prefix.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ListenPrefix) UnmarshalJSON(bytes []byte) error {
|
||||||
|
var value string
|
||||||
|
err := json.Unmarshal(bytes, &value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
prefix, err := netip.ParsePrefix(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*p = ListenPrefix(prefix)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ListenPrefix) Build() netip.Prefix {
|
||||||
|
return netip.Prefix(p)
|
||||||
|
}
|
|
@ -410,6 +410,7 @@ type Config struct {
|
||||||
Reverse *ReverseConfig `json:"reverse"`
|
Reverse *ReverseConfig `json:"reverse"`
|
||||||
FakeDNS *FakeDNSConfig `json:"fakeDns"`
|
FakeDNS *FakeDNSConfig `json:"fakeDns"`
|
||||||
Observatory *ObservatoryConfig `json:"observatory"`
|
Observatory *ObservatoryConfig `json:"observatory"`
|
||||||
|
Tun *TunConfig `json:"tun"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) findInboundTag(tag string) int {
|
func (c *Config) findInboundTag(tag string) int {
|
||||||
|
@ -474,6 +475,10 @@ func (c *Config) Override(o *Config, fn string) {
|
||||||
c.Observatory = o.Observatory
|
c.Observatory = o.Observatory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.Tun != nil {
|
||||||
|
c.Tun = o.Tun
|
||||||
|
}
|
||||||
|
|
||||||
// deprecated attrs... keep them for now
|
// deprecated attrs... keep them for now
|
||||||
if o.InboundConfig != nil {
|
if o.InboundConfig != nil {
|
||||||
c.InboundConfig = o.InboundConfig
|
c.InboundConfig = o.InboundConfig
|
||||||
|
@ -637,6 +642,14 @@ func (c *Config) Build() (*core.Config, error) {
|
||||||
config.App = append(config.App, serial.ToTypedMessage(r))
|
config.App = append(config.App, serial.ToTypedMessage(r))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.Tun != nil {
|
||||||
|
r, err := c.Tun.Build()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config.App = append(config.App, serial.ToTypedMessage(r))
|
||||||
|
}
|
||||||
|
|
||||||
var inbounds []InboundDetourConfig
|
var inbounds []InboundDetourConfig
|
||||||
|
|
||||||
if c.InboundConfig != nil {
|
if c.InboundConfig != nil {
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
|
|
||||||
// Developer preview services
|
// Developer preview services
|
||||||
_ "github.com/xtls/xray-core/app/observatory/command"
|
_ "github.com/xtls/xray-core/app/observatory/command"
|
||||||
|
_ "github.com/xtls/xray-core/app/tun"
|
||||||
|
|
||||||
// Other optional features.
|
// Other optional features.
|
||||||
_ "github.com/xtls/xray-core/app/dns"
|
_ "github.com/xtls/xray-core/app/dns"
|
||||||
|
|
Loading…
Reference in a new issue