mirror of
https://github.com/bolucat/Archive.git
synced 2026-04-22 16:07:49 +08:00
Update On Thu Dec 19 19:34:34 CET 2024
This commit is contained in:
@@ -856,3 +856,4 @@ Update On Sun Dec 15 19:34:29 CET 2024
|
||||
Update On Mon Dec 16 19:36:05 CET 2024
|
||||
Update On Tue Dec 17 19:39:30 CET 2024
|
||||
Update On Wed Dec 18 19:36:24 CET 2024
|
||||
Update On Thu Dec 19 19:34:25 CET 2024
|
||||
|
||||
@@ -40,8 +40,8 @@ subprojects {
|
||||
minSdk = 21
|
||||
targetSdk = 31
|
||||
|
||||
versionName = "2.11.2"
|
||||
versionCode = 211002
|
||||
versionName = "2.11.3"
|
||||
versionCode = 211003
|
||||
|
||||
resValue("string", "release_name", "v$versionName")
|
||||
resValue("integer", "release_code", "$versionCode")
|
||||
|
||||
@@ -8,12 +8,13 @@ import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
mieruclient "github.com/enfein/mieru/v3/apis/client"
|
||||
mierumodel "github.com/enfein/mieru/v3/apis/model"
|
||||
mierupb "github.com/enfein/mieru/v3/pkg/appctl/appctlpb"
|
||||
"github.com/metacubex/mihomo/component/dialer"
|
||||
"github.com/metacubex/mihomo/component/proxydialer"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
|
||||
mieruclient "github.com/enfein/mieru/v3/apis/client"
|
||||
mierumodel "github.com/enfein/mieru/v3/apis/model"
|
||||
mierupb "github.com/enfein/mieru/v3/pkg/appctl/appctlpb"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
@@ -26,13 +27,14 @@ type Mieru struct {
|
||||
|
||||
type MieruOption struct {
|
||||
BasicOption
|
||||
Name string `proxy:"name"`
|
||||
Server string `proxy:"server"`
|
||||
Port int `proxy:"port,omitempty"`
|
||||
PortRange string `proxy:"port-range,omitempty"`
|
||||
Transport string `proxy:"transport"`
|
||||
UserName string `proxy:"username"`
|
||||
Password string `proxy:"password"`
|
||||
Name string `proxy:"name"`
|
||||
Server string `proxy:"server"`
|
||||
Port int `proxy:"port,omitempty"`
|
||||
PortRange string `proxy:"port-range,omitempty"`
|
||||
Transport string `proxy:"transport"`
|
||||
UserName string `proxy:"username"`
|
||||
Password string `proxy:"password"`
|
||||
Multiplexing string `proxy:"multiplexing,omitempty"`
|
||||
}
|
||||
|
||||
// DialContext implements C.ProxyAdapter
|
||||
@@ -205,7 +207,7 @@ func buildMieruClientConfig(option MieruOption) (*mieruclient.ClientConfig, erro
|
||||
}
|
||||
}
|
||||
}
|
||||
return &mieruclient.ClientConfig{
|
||||
config := &mieruclient.ClientConfig{
|
||||
Profile: &mierupb.ClientProfile{
|
||||
ProfileName: proto.String(option.Name),
|
||||
User: &mierupb.User{
|
||||
@@ -214,7 +216,13 @@ func buildMieruClientConfig(option MieruOption) (*mieruclient.ClientConfig, erro
|
||||
},
|
||||
Servers: []*mierupb.ServerEndpoint{server},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
if multiplexing, ok := mierupb.MultiplexingLevel_value[option.Multiplexing]; ok {
|
||||
config.Profile.Multiplexing = &mierupb.MultiplexingConfig{
|
||||
Level: mierupb.MultiplexingLevel(multiplexing).Enum(),
|
||||
}
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func validateMieruOption(option MieruOption) error {
|
||||
@@ -258,6 +266,11 @@ func validateMieruOption(option MieruOption) error {
|
||||
if option.Password == "" {
|
||||
return fmt.Errorf("password is empty")
|
||||
}
|
||||
if option.Multiplexing != "" {
|
||||
if _, ok := mierupb.MultiplexingLevel_value[option.Multiplexing]; !ok {
|
||||
return fmt.Errorf("invalid multiplexing level: %s", option.Multiplexing)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,27 @@ func (d *Decoder) Decode(src map[string]any, dst any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// isNil returns true if the input is nil or a typed nil pointer.
|
||||
func isNil(input any) bool {
|
||||
if input == nil {
|
||||
return true
|
||||
}
|
||||
val := reflect.ValueOf(input)
|
||||
return val.Kind() == reflect.Pointer && val.IsNil()
|
||||
}
|
||||
|
||||
func (d *Decoder) decode(name string, data any, val reflect.Value) error {
|
||||
if isNil(data) {
|
||||
// If the data is nil, then we don't set anything
|
||||
// Maybe we should set to zero value?
|
||||
return nil
|
||||
}
|
||||
if !reflect.ValueOf(data).IsValid() {
|
||||
// If the input value is invalid, then we just set the value
|
||||
// to be the zero value.
|
||||
val.Set(reflect.Zero(val.Type()))
|
||||
return nil
|
||||
}
|
||||
for {
|
||||
kind := val.Kind()
|
||||
if kind == reflect.Pointer && val.IsNil() {
|
||||
|
||||
@@ -267,3 +267,21 @@ func TestStructure_TextUnmarshaller(t *testing.T) {
|
||||
err = decoder.Decode(rawMap, s)
|
||||
assert.NotNilf(t, err, "should throw error: %#v", s)
|
||||
}
|
||||
|
||||
func TestStructure_Null(t *testing.T) {
|
||||
rawMap := map[string]any{
|
||||
"opt": map[string]any{
|
||||
"bar": nil,
|
||||
},
|
||||
}
|
||||
|
||||
s := struct {
|
||||
Opt struct {
|
||||
Bar string `test:"bar,optional"`
|
||||
} `test:"opt,optional"`
|
||||
}{}
|
||||
|
||||
err := decoder.Decode(rawMap, &s)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, s.Opt.Bar, "")
|
||||
}
|
||||
|
||||
@@ -145,8 +145,12 @@ func (sd *Dispatcher) Enable() bool {
|
||||
}
|
||||
|
||||
func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (string, error) {
|
||||
//defer func(start time.Time) {
|
||||
// log.Debugln("[Sniffer] [%s] Sniffing took %s", metadata.DstIP, time.Since(start))
|
||||
//}(time.Now())
|
||||
|
||||
for s := range sd.sniffers {
|
||||
if s.SupportNetwork() == C.TCP {
|
||||
if s.SupportNetwork() == C.TCP && s.SupportPort(metadata.DstPort) {
|
||||
_ = conn.SetReadDeadline(time.Now().Add(1 * time.Second))
|
||||
_, err := conn.Peek(1)
|
||||
_ = conn.SetReadDeadline(time.Time{})
|
||||
@@ -154,7 +158,7 @@ func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (s
|
||||
_, ok := err.(*net.OpError)
|
||||
if ok {
|
||||
sd.cacheSniffFailed(metadata)
|
||||
log.Errorln("[Sniffer] [%s] may not have any sent data, Consider adding skip", metadata.DstIP.String())
|
||||
log.Errorln("[Sniffer] [%s] [%s] may not have any sent data, Consider adding skip", metadata.DstIP, s.Protocol())
|
||||
_ = conn.Close()
|
||||
}
|
||||
|
||||
@@ -164,22 +168,36 @@ func (sd *Dispatcher) sniffDomain(conn *N.BufferedConn, metadata *C.Metadata) (s
|
||||
bufferedLen := conn.Buffered()
|
||||
bytes, err := conn.Peek(bufferedLen)
|
||||
if err != nil {
|
||||
log.Debugln("[Sniffer] the data length not enough")
|
||||
log.Debugln("[Sniffer] [%s] [%s] the data length not enough, error: %v", metadata.DstIP, s.Protocol(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
host, err := s.SniffData(bytes)
|
||||
var e *errNeedAtLeastData
|
||||
if errors.As(err, &e) {
|
||||
//log.Debugln("[Sniffer] [%s] [%s] %v, got length: %d", metadata.DstIP, s.Protocol(), e, len(bytes))
|
||||
_ = conn.SetReadDeadline(time.Now().Add(1 * time.Second))
|
||||
bytes, err = conn.Peek(e.length)
|
||||
_ = conn.SetReadDeadline(time.Time{})
|
||||
//log.Debugln("[Sniffer] [%s] [%s] try again, got length: %d", metadata.DstIP, s.Protocol(), len(bytes))
|
||||
if err != nil {
|
||||
log.Debugln("[Sniffer] [%s] [%s] the data length not enough, error: %v", metadata.DstIP, s.Protocol(), err)
|
||||
continue
|
||||
}
|
||||
host, err = s.SniffData(bytes)
|
||||
}
|
||||
if err != nil {
|
||||
//log.Debugln("[Sniffer] [%s] Sniff data failed %s", s.Protocol(), metadata.DstIP)
|
||||
//log.Debugln("[Sniffer] [%s] [%s] Sniff data failed, error: %v", metadata.DstIP, s.Protocol(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = netip.ParseAddr(host)
|
||||
if err == nil {
|
||||
//log.Debugln("[Sniffer] [%s] Sniff data failed %s", s.Protocol(), metadata.DstIP)
|
||||
//log.Debugln("[Sniffer] [%s] [%s] Sniff data failed, got host [%s]", metadata.DstIP, s.Protocol(), host)
|
||||
continue
|
||||
}
|
||||
|
||||
//log.Debugln("[Sniffer] [%s] [%s] Sniffed [%s]", metadata.DstIP, s.Protocol(), host)
|
||||
return host, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package sniffer
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
@@ -15,6 +16,19 @@ var (
|
||||
errNotClientHello = errors.New("not client hello")
|
||||
)
|
||||
|
||||
type errNeedAtLeastData struct {
|
||||
length int
|
||||
err error
|
||||
}
|
||||
|
||||
func (e *errNeedAtLeastData) Error() string {
|
||||
return fmt.Sprintf("%v, need at least length: %d", e.err, e.length)
|
||||
}
|
||||
|
||||
func (e *errNeedAtLeastData) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
var _ sniffer.Sniffer = (*TLSSniffer)(nil)
|
||||
|
||||
type TLSSniffer struct {
|
||||
@@ -160,7 +174,10 @@ func SniffTLS(b []byte) (*string, error) {
|
||||
}
|
||||
headerLen := int(binary.BigEndian.Uint16(b[3:5]))
|
||||
if 5+headerLen > len(b) {
|
||||
return nil, ErrNoClue
|
||||
return nil, &errNeedAtLeastData{
|
||||
length: 5 + headerLen,
|
||||
err: ErrNoClue,
|
||||
}
|
||||
}
|
||||
|
||||
domain, err := ReadClientHello(b[5 : 5+headerLen])
|
||||
|
||||
@@ -13,6 +13,7 @@ const (
|
||||
File VehicleType = iota
|
||||
HTTP
|
||||
Compatible
|
||||
Inline
|
||||
)
|
||||
|
||||
// VehicleType defined
|
||||
@@ -26,6 +27,8 @@ func (v VehicleType) String() string {
|
||||
return "HTTP"
|
||||
case Compatible:
|
||||
return "Compatible"
|
||||
case Inline:
|
||||
return "Inline"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
@@ -855,6 +855,8 @@ proxies: # socks5
|
||||
transport: TCP # 只支持 TCP
|
||||
username: user
|
||||
password: password
|
||||
# 可以使用的值包括 MULTIPLEXING_OFF, MULTIPLEXING_LOW, MULTIPLEXING_MIDDLE, MULTIPLEXING_HIGH。其中 MULTIPLEXING_OFF 会关闭多路复用功能。默认值为 MULTIPLEXING_LOW。
|
||||
# multiplexing: MULTIPLEXING_LOW
|
||||
|
||||
# dns 出站会将请求劫持到内部 dns 模块,所有请求均在内部处理
|
||||
- name: "dns-out"
|
||||
@@ -1012,6 +1014,14 @@ rule-providers:
|
||||
format: mrs
|
||||
behavior: domain
|
||||
path: /path/to/save/file.mrs
|
||||
rule4:
|
||||
type: inline
|
||||
behavior: domain # classical / ipcidr
|
||||
payload:
|
||||
- '.blogger.com'
|
||||
- '*.*.microsoft.com'
|
||||
- 'books.itunes.apple.com'
|
||||
|
||||
rules:
|
||||
- RULE-SET,rule1,REJECT
|
||||
- IP-ASN,1,PROXY
|
||||
|
||||
@@ -7,14 +7,14 @@ require (
|
||||
github.com/bahlo/generic-list-go v0.2.0
|
||||
github.com/coreos/go-iptables v0.8.0
|
||||
github.com/dlclark/regexp2 v1.11.4
|
||||
github.com/enfein/mieru/v3 v3.8.3
|
||||
github.com/enfein/mieru/v3 v3.8.4
|
||||
github.com/go-chi/chi/v5 v5.1.0
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/gobwas/ws v1.4.0
|
||||
github.com/gofrs/uuid/v5 v5.3.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475
|
||||
github.com/klauspost/compress v1.17.9
|
||||
github.com/klauspost/cpuid/v2 v2.2.8
|
||||
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef
|
||||
github.com/klauspost/compress v1.17.9 // lastest version compatible with golang1.20
|
||||
github.com/klauspost/cpuid/v2 v2.2.9
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
|
||||
github.com/mdlayher/netlink v1.7.2
|
||||
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab
|
||||
@@ -35,28 +35,28 @@ require (
|
||||
github.com/miekg/dns v1.1.62
|
||||
github.com/mroth/weightedrand/v2 v2.1.0
|
||||
github.com/openacid/low v0.1.21
|
||||
github.com/oschwald/maxminddb-golang v1.12.0
|
||||
github.com/oschwald/maxminddb-golang v1.12.0 // lastest version compatible with golang1.20
|
||||
github.com/puzpuzpuz/xsync/v3 v3.4.0
|
||||
github.com/sagernet/cors v1.2.1
|
||||
github.com/sagernet/fswatch v0.1.1
|
||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a
|
||||
github.com/sagernet/sing v0.5.1
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6
|
||||
github.com/sagernet/sing-shadowtls v0.1.4
|
||||
github.com/sagernet/sing-mux v0.2.1
|
||||
github.com/sagernet/sing-shadowtls v0.1.5
|
||||
github.com/samber/lo v1.47.0
|
||||
github.com/shirou/gopsutil/v3 v3.24.5
|
||||
github.com/shirou/gopsutil/v4 v4.24.11
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/vmihailenco/msgpack/v5 v5.4.1
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8
|
||||
gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7
|
||||
go.uber.org/automaxprocs v1.6.0
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
golang.org/x/crypto v0.29.0
|
||||
golang.org/x/crypto v0.31.0
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // lastest version compatible with golang1.20
|
||||
golang.org/x/net v0.31.0
|
||||
golang.org/x/sys v0.27.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
golang.org/x/net v0.32.0
|
||||
golang.org/x/sys v0.28.0
|
||||
google.golang.org/protobuf v1.34.2 // lastest version compatible with golang1.20
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
lukechampine.com/blake3 v1.3.0
|
||||
)
|
||||
@@ -69,6 +69,7 @@ require (
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/ebitengine/purego v0.8.1 // indirect
|
||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 // indirect
|
||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
|
||||
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
|
||||
@@ -82,7 +83,7 @@ require (
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||
github.com/josharian/native v1.1.0 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
@@ -98,7 +99,6 @@ require (
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect
|
||||
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect
|
||||
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e // indirect
|
||||
@@ -111,12 +111,10 @@ require (
|
||||
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/sync v0.9.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect
|
||||
google.golang.org/grpc v1.64.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20241121030428-33b6ebc52000
|
||||
|
||||
@@ -27,8 +27,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
|
||||
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/enfein/mieru/v3 v3.8.3 h1:s4K0hMFDg6LHltokR8/nBTVCq15XnnxPsvc1LrHwpoo=
|
||||
github.com/enfein/mieru/v3 v3.8.3/go.mod h1:YtU00qjAEt54mCBQu4WZPCey6cBdB1BUtXjvrHLEUNQ=
|
||||
github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE=
|
||||
github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/enfein/mieru/v3 v3.8.4 h1:PmBQykuEcl8yKcQ647pg8Qbjl433CRYgUbW6VLBgGn4=
|
||||
github.com/enfein/mieru/v3 v3.8.4/go.mod h1:YtU00qjAEt54mCBQu4WZPCey6cBdB1BUtXjvrHLEUNQ=
|
||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 h1:/5RkVc9Rc81XmMyVqawCiDyrBHZbLAZgTTCqou4mwj8=
|
||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I=
|
||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g=
|
||||
@@ -61,7 +63,7 @@ github.com/gobwas/ws v1.4.0/go.mod h1:G3gNqMNtPppf5XUz7O4shetPpcZ1VJ7zt18dlUeakr
|
||||
github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk=
|
||||
github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
@@ -70,19 +72,19 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475 h1:hxST5pwMBEOWmxpkX20w9oZG+hXdhKmAIPQ3NGGAxas=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef h1:NzQKDfd5ZOPnuZYf9MnRee8x2qecsVqzsnaLjEZiBko=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
@@ -168,19 +170,16 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
|
||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 h1:5bCAkvDDzSMITiHFjolBwpdqYsvycdTu71FsMEFXQ14=
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||
github.com/sagernet/sing-mux v0.2.1 h1:N/3MHymfnFZRd29tE3TaXwPUVVgKvxhtOkiCMLp9HVo=
|
||||
github.com/sagernet/sing-mux v0.2.1/go.mod h1:dm3BWL6NvES9pbib7llpylrq7Gq+LjlzG+0RacdxcyE=
|
||||
github.com/sagernet/sing-shadowtls v0.1.5 h1:uXxmq/HXh8DIiBGLzpMjCbWnzIAFs+lIxiTOjdgG5qo=
|
||||
github.com/sagernet/sing-shadowtls v0.1.5/go.mod h1:tvrDPTGLrSM46Wnf7mSr+L8NHvgvF8M4YnJF790rZX4=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
||||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
github.com/shirou/gopsutil/v4 v4.24.11 h1:WaU9xqGFKvFfsUv94SXcUPD7rCkU0vr/asVdQOBZNj8=
|
||||
github.com/shirou/gopsutil/v4 v4.24.11/go.mod h1:s4D/wg+ag4rG0WO7AiTj2BeYCRhym0vM7DHbZRxnIT8=
|
||||
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b h1:rXHg9GrUEtWZhEkrykicdND3VPjlVbYiLdX9J7gimS8=
|
||||
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b/go.mod h1:X7qrxNQViEaAN9LNZOPl9PfvQtp3V3c7LTo0dvGi0fM=
|
||||
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c h1:DjKMC30y6yjG3IxDaeAj3PCoRr+IsO+bzyT+Se2m2Hk=
|
||||
@@ -199,8 +198,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
@@ -232,8 +232,8 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
@@ -242,11 +242,11 @@ golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
|
||||
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -258,17 +258,16 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
@@ -276,10 +275,6 @@ golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 h1:9Xyg6I9IWQZhRVfCWjKK+l6kI0jHcPesVlMnT//aHNo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
||||
google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
|
||||
google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -20,7 +20,7 @@ func init() {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
FullTimestamp: true,
|
||||
TimestampFormat: "2006-01-02T15:04:05.999999999Z07:00",
|
||||
TimestampFormat: "2006-01-02T15:04:05.000000000Z07:00",
|
||||
EnvironmentOverrideColors: true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
@@ -99,6 +100,13 @@ func main() {
|
||||
log.Fatalln("Initial configuration error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
} else if configFile == "-" {
|
||||
var err error
|
||||
configBytes, err = io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
log.Fatalln("Initial configuration error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if configFile != "" {
|
||||
if !filepath.IsAbs(configFile) {
|
||||
|
||||
@@ -3,6 +3,8 @@ package common
|
||||
import (
|
||||
"errors"
|
||||
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
@@ -38,3 +40,5 @@ func ParseParams(params []string) (isSrc bool, noResolve bool) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ParseRuleFunc func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (C.Rule, error)
|
||||
|
||||
@@ -23,9 +23,7 @@ type Logic struct {
|
||||
payloadOnce sync.Once
|
||||
}
|
||||
|
||||
type ParseRuleFunc func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (C.Rule, error)
|
||||
|
||||
func NewSubRule(payload, adapter string, subRules map[string][]C.Rule, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewSubRule(payload, adapter string, subRules map[string][]C.Rule, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.SubRules, subRules: subRules}
|
||||
err := logic.parsePayload(fmt.Sprintf("(%s)", payload), parseRule)
|
||||
if err != nil {
|
||||
@@ -38,7 +36,7 @@ func NewSubRule(payload, adapter string, subRules map[string][]C.Rule, parseRule
|
||||
return logic, nil
|
||||
}
|
||||
|
||||
func NewNOT(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewNOT(payload string, adapter string, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.NOT}
|
||||
err := logic.parsePayload(payload, parseRule)
|
||||
if err != nil {
|
||||
@@ -51,7 +49,7 @@ func NewNOT(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, er
|
||||
return logic, nil
|
||||
}
|
||||
|
||||
func NewOR(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewOR(payload string, adapter string, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.OR}
|
||||
err := logic.parsePayload(payload, parseRule)
|
||||
if err != nil {
|
||||
@@ -60,7 +58,7 @@ func NewOR(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, err
|
||||
return logic, nil
|
||||
}
|
||||
|
||||
func NewAND(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewAND(payload string, adapter string, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.AND}
|
||||
err := logic.parsePayload(payload, parseRule)
|
||||
if err != nil {
|
||||
@@ -79,7 +77,7 @@ func (r Range) containRange(preStart, preEnd int) bool {
|
||||
return preStart < r.start && preEnd > r.end
|
||||
}
|
||||
|
||||
func (logic *Logic) payloadToRule(subPayload string, parseRule ParseRuleFunc) (C.Rule, error) {
|
||||
func (logic *Logic) payloadToRule(subPayload string, parseRule common.ParseRuleFunc) (C.Rule, error) {
|
||||
splitStr := strings.SplitN(subPayload, ",", 2)
|
||||
if len(splitStr) < 2 {
|
||||
return nil, fmt.Errorf("[%s] format is error", subPayload)
|
||||
@@ -160,7 +158,7 @@ func (logic *Logic) findSubRuleRange(payload string, ruleRanges []Range) []Range
|
||||
return subRuleRange
|
||||
}
|
||||
|
||||
func (logic *Logic) parsePayload(payload string, parseRule ParseRuleFunc) error {
|
||||
func (logic *Logic) parsePayload(payload string, parseRule common.ParseRuleFunc) error {
|
||||
regex, err := regexp.Compile("\\(.*\\)")
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -91,3 +91,5 @@ func ParseRule(tp, payload, target string, params []string, subRules map[string]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var _ RC.ParseRuleFunc = ParseRule
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/rules/common"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -16,17 +17,18 @@ var (
|
||||
)
|
||||
|
||||
type ruleProviderSchema struct {
|
||||
Type string `provider:"type"`
|
||||
Behavior string `provider:"behavior"`
|
||||
Path string `provider:"path,omitempty"`
|
||||
URL string `provider:"url,omitempty"`
|
||||
Proxy string `provider:"proxy,omitempty"`
|
||||
Format string `provider:"format,omitempty"`
|
||||
Interval int `provider:"interval,omitempty"`
|
||||
SizeLimit int64 `provider:"size-limit,omitempty"`
|
||||
Type string `provider:"type"`
|
||||
Behavior string `provider:"behavior"`
|
||||
Path string `provider:"path,omitempty"`
|
||||
URL string `provider:"url,omitempty"`
|
||||
Proxy string `provider:"proxy,omitempty"`
|
||||
Format string `provider:"format,omitempty"`
|
||||
Interval int `provider:"interval,omitempty"`
|
||||
SizeLimit int64 `provider:"size-limit,omitempty"`
|
||||
Payload []string `provider:"payload,omitempty"`
|
||||
}
|
||||
|
||||
func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) (P.RuleProvider, error) {
|
||||
func ParseRuleProvider(name string, mapping map[string]any, parse common.ParseRuleFunc) (P.RuleProvider, error) {
|
||||
schema := &ruleProviderSchema{}
|
||||
decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true})
|
||||
if err := decoder.Decode(mapping, schema); err != nil {
|
||||
@@ -55,6 +57,8 @@ func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(t
|
||||
}
|
||||
}
|
||||
vehicle = resource.NewHTTPVehicle(schema.URL, path, schema.Proxy, nil, resource.DefaultHttpTimeout, schema.SizeLimit)
|
||||
case "inline":
|
||||
return newInlineProvider(name, behavior, schema.Payload, parse), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported vehicle type: %s", schema.Type)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/rules/common"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -24,9 +25,13 @@ func SetTunnel(t P.Tunnel) {
|
||||
}
|
||||
|
||||
type ruleSetProvider struct {
|
||||
ruleSetProviderBase
|
||||
*resource.Fetcher[ruleStrategy]
|
||||
format P.RuleFormat
|
||||
}
|
||||
|
||||
type ruleSetProviderBase struct {
|
||||
behavior P.RuleBehavior
|
||||
format P.RuleFormat
|
||||
strategy ruleStrategy
|
||||
}
|
||||
|
||||
@@ -61,7 +66,7 @@ type mrsRuleStrategy interface {
|
||||
DumpMrs(f func(key string) bool)
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Type() P.ProviderType {
|
||||
func (rp *ruleSetProviderBase) Type() P.ProviderType {
|
||||
return P.Rule
|
||||
}
|
||||
|
||||
@@ -75,40 +80,51 @@ func (rp *ruleSetProvider) Update() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Behavior() P.RuleBehavior {
|
||||
func (rp *ruleSetProviderBase) Behavior() P.RuleBehavior {
|
||||
return rp.behavior
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Count() int {
|
||||
func (rp *ruleSetProviderBase) Count() int {
|
||||
return rp.strategy.Count()
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Match(metadata *C.Metadata) bool {
|
||||
func (rp *ruleSetProviderBase) Match(metadata *C.Metadata) bool {
|
||||
return rp.strategy != nil && rp.strategy.Match(metadata)
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) ShouldResolveIP() bool {
|
||||
func (rp *ruleSetProviderBase) ShouldResolveIP() bool {
|
||||
return rp.strategy.ShouldResolveIP()
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) ShouldFindProcess() bool {
|
||||
func (rp *ruleSetProviderBase) ShouldFindProcess() bool {
|
||||
return rp.strategy.ShouldFindProcess()
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Strategy() any {
|
||||
func (rp *ruleSetProviderBase) Strategy() any {
|
||||
return rp.strategy
|
||||
}
|
||||
|
||||
type providerForApi struct {
|
||||
Behavior string `json:"behavior"`
|
||||
Format string `json:"format"`
|
||||
Name string `json:"name"`
|
||||
RuleCount int `json:"ruleCount"`
|
||||
Type string `json:"type"`
|
||||
VehicleType string `json:"vehicleType"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
Payload []string `json:"payload,omitempty"`
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(
|
||||
map[string]interface{}{
|
||||
"behavior": rp.behavior.String(),
|
||||
"format": rp.format.String(),
|
||||
"name": rp.Name(),
|
||||
"ruleCount": rp.strategy.Count(),
|
||||
"type": rp.Type().String(),
|
||||
"updatedAt": rp.UpdatedAt(),
|
||||
"vehicleType": rp.VehicleType().String(),
|
||||
providerForApi{
|
||||
Behavior: rp.behavior.String(),
|
||||
Format: rp.format.String(),
|
||||
Name: rp.Fetcher.Name(),
|
||||
RuleCount: rp.strategy.Count(),
|
||||
Type: rp.Type().String(),
|
||||
UpdatedAt: rp.UpdatedAt(),
|
||||
VehicleType: rp.VehicleType().String(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -117,11 +133,12 @@ func (rp *RuleSetProvider) Close() error {
|
||||
return rp.ruleSetProvider.Close()
|
||||
}
|
||||
|
||||
func NewRuleSetProvider(name string, behavior P.RuleBehavior, format P.RuleFormat, interval time.Duration, vehicle P.Vehicle,
|
||||
parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) P.RuleProvider {
|
||||
func NewRuleSetProvider(name string, behavior P.RuleBehavior, format P.RuleFormat, interval time.Duration, vehicle P.Vehicle, parse common.ParseRuleFunc) P.RuleProvider {
|
||||
rp := &ruleSetProvider{
|
||||
behavior: behavior,
|
||||
format: format,
|
||||
ruleSetProviderBase: ruleSetProviderBase{
|
||||
behavior: behavior,
|
||||
},
|
||||
format: format,
|
||||
}
|
||||
|
||||
onUpdate := func(strategy ruleStrategy) {
|
||||
@@ -142,7 +159,7 @@ func NewRuleSetProvider(name string, behavior P.RuleBehavior, format P.RuleForma
|
||||
return wrapper
|
||||
}
|
||||
|
||||
func newStrategy(behavior P.RuleBehavior, parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) ruleStrategy {
|
||||
func newStrategy(behavior P.RuleBehavior, parse common.ParseRuleFunc) ruleStrategy {
|
||||
switch behavior {
|
||||
case P.Domain:
|
||||
strategy := NewDomainStrategy()
|
||||
@@ -158,8 +175,10 @@ func newStrategy(behavior P.RuleBehavior, parse func(tp, payload, target string,
|
||||
}
|
||||
}
|
||||
|
||||
var ErrNoPayload = errors.New("file must have a `payload` field")
|
||||
var ErrInvalidFormat = errors.New("invalid format")
|
||||
var (
|
||||
ErrNoPayload = errors.New("file must have a `payload` field")
|
||||
ErrInvalidFormat = errors.New("invalid format")
|
||||
)
|
||||
|
||||
func rulesParse(buf []byte, strategy ruleStrategy, format P.RuleFormat) (ruleStrategy, error) {
|
||||
strategy.Reset()
|
||||
@@ -254,3 +273,66 @@ func rulesParse(buf []byte, strategy ruleStrategy, format P.RuleFormat) (ruleStr
|
||||
|
||||
return strategy, nil
|
||||
}
|
||||
|
||||
func rulesParseInline(rs []string, strategy ruleStrategy) ruleStrategy {
|
||||
strategy.Reset()
|
||||
for _, r := range rs {
|
||||
if r != "" {
|
||||
strategy.Insert(r)
|
||||
}
|
||||
}
|
||||
strategy.FinishInsert()
|
||||
return strategy
|
||||
}
|
||||
|
||||
type inlineProvider struct {
|
||||
ruleSetProviderBase
|
||||
name string
|
||||
updateTime time.Time
|
||||
payload []string
|
||||
}
|
||||
|
||||
func (i *inlineProvider) Name() string {
|
||||
return i.name
|
||||
}
|
||||
|
||||
func (i *inlineProvider) Initial() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *inlineProvider) Update() error {
|
||||
// make api update happy
|
||||
i.updateTime = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *inlineProvider) VehicleType() P.VehicleType {
|
||||
return P.Inline
|
||||
}
|
||||
|
||||
func (i *inlineProvider) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(
|
||||
providerForApi{
|
||||
Behavior: i.behavior.String(),
|
||||
Name: i.Name(),
|
||||
RuleCount: i.strategy.Count(),
|
||||
Type: i.Type().String(),
|
||||
VehicleType: i.VehicleType().String(),
|
||||
UpdatedAt: i.updateTime,
|
||||
Payload: i.payload,
|
||||
})
|
||||
}
|
||||
|
||||
func newInlineProvider(name string, behavior P.RuleBehavior, payload []string, parse common.ParseRuleFunc) P.RuleProvider {
|
||||
rp := &inlineProvider{
|
||||
ruleSetProviderBase: ruleSetProviderBase{
|
||||
behavior: behavior,
|
||||
strategy: newStrategy(behavior, parse),
|
||||
},
|
||||
payload: payload,
|
||||
name: name,
|
||||
updateTime: time.Now(),
|
||||
}
|
||||
rp.strategy = rulesParseInline(payload, rp.strategy)
|
||||
return rp
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/metacubex/mihomo/common/atomic"
|
||||
|
||||
"github.com/puzpuzpuz/xsync/v3"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
"github.com/shirou/gopsutil/v4/process"
|
||||
)
|
||||
|
||||
var DefaultManager *Manager
|
||||
|
||||
@@ -15,7 +15,8 @@ require (
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/coreos/go-iptables v0.8.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.11.4 // indirect
|
||||
github.com/enfein/mieru/v3 v3.8.3 // indirect
|
||||
github.com/ebitengine/purego v0.8.1 // indirect
|
||||
github.com/enfein/mieru/v3 v3.8.4 // indirect
|
||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 // indirect
|
||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
|
||||
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
|
||||
@@ -30,14 +31,15 @@ require (
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.4.0 // indirect
|
||||
github.com/gofrs/uuid/v5 v5.3.0 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475 // indirect
|
||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef // indirect
|
||||
github.com/josharian/native v1.1.0 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
@@ -76,12 +78,11 @@ require (
|
||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
|
||||
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
||||
github.com/sagernet/sing v0.5.1 // indirect
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 // indirect
|
||||
github.com/sagernet/sing-shadowtls v0.1.4 // indirect
|
||||
github.com/sagernet/sing-mux v0.2.1 // indirect
|
||||
github.com/sagernet/sing-shadowtls v0.1.5 // indirect
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
||||
github.com/samber/lo v1.47.0 // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.24.11 // indirect
|
||||
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect
|
||||
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect
|
||||
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e // indirect
|
||||
@@ -98,17 +99,15 @@ require (
|
||||
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
||||
golang.org/x/crypto v0.29.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/net v0.31.0 // indirect
|
||||
golang.org/x/sync v0.9.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
golang.org/x/net v0.32.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect
|
||||
google.golang.org/grpc v1.64.1 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
|
||||
@@ -26,8 +26,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
|
||||
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/enfein/mieru/v3 v3.8.3 h1:s4K0hMFDg6LHltokR8/nBTVCq15XnnxPsvc1LrHwpoo=
|
||||
github.com/enfein/mieru/v3 v3.8.3/go.mod h1:YtU00qjAEt54mCBQu4WZPCey6cBdB1BUtXjvrHLEUNQ=
|
||||
github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE=
|
||||
github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/enfein/mieru/v3 v3.8.4 h1:PmBQykuEcl8yKcQ647pg8Qbjl433CRYgUbW6VLBgGn4=
|
||||
github.com/enfein/mieru/v3 v3.8.4/go.mod h1:YtU00qjAEt54mCBQu4WZPCey6cBdB1BUtXjvrHLEUNQ=
|
||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 h1:/5RkVc9Rc81XmMyVqawCiDyrBHZbLAZgTTCqou4mwj8=
|
||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I=
|
||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g=
|
||||
@@ -61,6 +63,7 @@ github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk=
|
||||
github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
@@ -69,19 +72,19 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475 h1:hxST5pwMBEOWmxpkX20w9oZG+hXdhKmAIPQ3NGGAxas=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef h1:NzQKDfd5ZOPnuZYf9MnRee8x2qecsVqzsnaLjEZiBko=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc=
|
||||
@@ -163,19 +166,16 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
|
||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 h1:5bCAkvDDzSMITiHFjolBwpdqYsvycdTu71FsMEFXQ14=
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||
github.com/sagernet/sing-mux v0.2.1 h1:N/3MHymfnFZRd29tE3TaXwPUVVgKvxhtOkiCMLp9HVo=
|
||||
github.com/sagernet/sing-mux v0.2.1/go.mod h1:dm3BWL6NvES9pbib7llpylrq7Gq+LjlzG+0RacdxcyE=
|
||||
github.com/sagernet/sing-shadowtls v0.1.5 h1:uXxmq/HXh8DIiBGLzpMjCbWnzIAFs+lIxiTOjdgG5qo=
|
||||
github.com/sagernet/sing-shadowtls v0.1.5/go.mod h1:tvrDPTGLrSM46Wnf7mSr+L8NHvgvF8M4YnJF790rZX4=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
||||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
github.com/shirou/gopsutil/v4 v4.24.11 h1:WaU9xqGFKvFfsUv94SXcUPD7rCkU0vr/asVdQOBZNj8=
|
||||
github.com/shirou/gopsutil/v4 v4.24.11/go.mod h1:s4D/wg+ag4rG0WO7AiTj2BeYCRhym0vM7DHbZRxnIT8=
|
||||
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b h1:rXHg9GrUEtWZhEkrykicdND3VPjlVbYiLdX9J7gimS8=
|
||||
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b/go.mod h1:X7qrxNQViEaAN9LNZOPl9PfvQtp3V3c7LTo0dvGi0fM=
|
||||
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c h1:DjKMC30y6yjG3IxDaeAj3PCoRr+IsO+bzyT+Se2m2Hk=
|
||||
@@ -194,8 +194,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
@@ -225,8 +225,8 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
@@ -235,11 +235,11 @@ golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
|
||||
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -251,17 +251,16 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
@@ -269,10 +268,6 @@ golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 h1:9Xyg6I9IWQZhRVfCWjKK+l6kI0jHcPesVlMnT//aHNo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
||||
google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
|
||||
google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.20
|
||||
require (
|
||||
github.com/dlclark/regexp2 v1.11.4
|
||||
github.com/metacubex/mihomo v1.7.0
|
||||
golang.org/x/sync v0.9.0
|
||||
golang.org/x/sync v0.10.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
@@ -23,7 +23,8 @@ require (
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/coreos/go-iptables v0.8.0 // indirect
|
||||
github.com/enfein/mieru/v3 v3.8.3 // indirect
|
||||
github.com/ebitengine/purego v0.8.1 // indirect
|
||||
github.com/enfein/mieru/v3 v3.8.4 // indirect
|
||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 // indirect
|
||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
|
||||
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
|
||||
@@ -38,14 +39,15 @@ require (
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/gobwas/ws v1.4.0 // indirect
|
||||
github.com/gofrs/uuid/v5 v5.3.0 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475 // indirect
|
||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef // indirect
|
||||
github.com/josharian/native v1.1.0 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
@@ -83,12 +85,11 @@ require (
|
||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
|
||||
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
||||
github.com/sagernet/sing v0.5.1 // indirect
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 // indirect
|
||||
github.com/sagernet/sing-shadowtls v0.1.4 // indirect
|
||||
github.com/sagernet/sing-mux v0.2.1 // indirect
|
||||
github.com/sagernet/sing-shadowtls v0.1.5 // indirect
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
||||
github.com/samber/lo v1.47.0 // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.24.11 // indirect
|
||||
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect
|
||||
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect
|
||||
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e // indirect
|
||||
@@ -105,16 +106,14 @@ require (
|
||||
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
||||
golang.org/x/crypto v0.29.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/net v0.31.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
golang.org/x/net v0.32.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect
|
||||
google.golang.org/grpc v1.64.1 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
)
|
||||
|
||||
@@ -26,8 +26,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
|
||||
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/enfein/mieru/v3 v3.8.3 h1:s4K0hMFDg6LHltokR8/nBTVCq15XnnxPsvc1LrHwpoo=
|
||||
github.com/enfein/mieru/v3 v3.8.3/go.mod h1:YtU00qjAEt54mCBQu4WZPCey6cBdB1BUtXjvrHLEUNQ=
|
||||
github.com/ebitengine/purego v0.8.1 h1:sdRKd6plj7KYW33EH5As6YKfe8m9zbN9JMrOjNVF/BE=
|
||||
github.com/ebitengine/purego v0.8.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/enfein/mieru/v3 v3.8.4 h1:PmBQykuEcl8yKcQ647pg8Qbjl433CRYgUbW6VLBgGn4=
|
||||
github.com/enfein/mieru/v3 v3.8.4/go.mod h1:YtU00qjAEt54mCBQu4WZPCey6cBdB1BUtXjvrHLEUNQ=
|
||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 h1:/5RkVc9Rc81XmMyVqawCiDyrBHZbLAZgTTCqou4mwj8=
|
||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I=
|
||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g=
|
||||
@@ -61,6 +63,7 @@ github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk=
|
||||
github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
@@ -69,19 +72,19 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475 h1:hxST5pwMBEOWmxpkX20w9oZG+hXdhKmAIPQ3NGGAxas=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef h1:NzQKDfd5ZOPnuZYf9MnRee8x2qecsVqzsnaLjEZiBko=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc=
|
||||
@@ -163,19 +166,16 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
|
||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 h1:5bCAkvDDzSMITiHFjolBwpdqYsvycdTu71FsMEFXQ14=
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||
github.com/sagernet/sing-mux v0.2.1 h1:N/3MHymfnFZRd29tE3TaXwPUVVgKvxhtOkiCMLp9HVo=
|
||||
github.com/sagernet/sing-mux v0.2.1/go.mod h1:dm3BWL6NvES9pbib7llpylrq7Gq+LjlzG+0RacdxcyE=
|
||||
github.com/sagernet/sing-shadowtls v0.1.5 h1:uXxmq/HXh8DIiBGLzpMjCbWnzIAFs+lIxiTOjdgG5qo=
|
||||
github.com/sagernet/sing-shadowtls v0.1.5/go.mod h1:tvrDPTGLrSM46Wnf7mSr+L8NHvgvF8M4YnJF790rZX4=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
||||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
github.com/shirou/gopsutil/v4 v4.24.11 h1:WaU9xqGFKvFfsUv94SXcUPD7rCkU0vr/asVdQOBZNj8=
|
||||
github.com/shirou/gopsutil/v4 v4.24.11/go.mod h1:s4D/wg+ag4rG0WO7AiTj2BeYCRhym0vM7DHbZRxnIT8=
|
||||
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b h1:rXHg9GrUEtWZhEkrykicdND3VPjlVbYiLdX9J7gimS8=
|
||||
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b/go.mod h1:X7qrxNQViEaAN9LNZOPl9PfvQtp3V3c7LTo0dvGi0fM=
|
||||
github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c h1:DjKMC30y6yjG3IxDaeAj3PCoRr+IsO+bzyT+Se2m2Hk=
|
||||
@@ -194,8 +194,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
@@ -225,8 +225,8 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
@@ -235,11 +235,11 @@ golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
|
||||
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -251,17 +251,16 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
@@ -269,10 +268,6 @@ golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 h1:9Xyg6I9IWQZhRVfCWjKK+l6kI0jHcPesVlMnT//aHNo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
||||
google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
|
||||
google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
|
||||
@@ -35,6 +35,7 @@ data class Proxy(
|
||||
WireGuard(false),
|
||||
Dns(false),
|
||||
Ssh(false),
|
||||
Mieru(false),
|
||||
|
||||
|
||||
Relay(true),
|
||||
|
||||
@@ -13,6 +13,7 @@ const (
|
||||
File VehicleType = iota
|
||||
HTTP
|
||||
Compatible
|
||||
Inline
|
||||
)
|
||||
|
||||
// VehicleType defined
|
||||
@@ -26,6 +27,8 @@ func (v VehicleType) String() string {
|
||||
return "HTTP"
|
||||
case Compatible:
|
||||
return "Compatible"
|
||||
case Inline:
|
||||
return "Inline"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
@@ -1014,6 +1014,14 @@ rule-providers:
|
||||
format: mrs
|
||||
behavior: domain
|
||||
path: /path/to/save/file.mrs
|
||||
rule4:
|
||||
type: inline
|
||||
behavior: domain # classical / ipcidr
|
||||
payload:
|
||||
- '.blogger.com'
|
||||
- '*.*.microsoft.com'
|
||||
- 'books.itunes.apple.com'
|
||||
|
||||
rules:
|
||||
- RULE-SET,rule1,REJECT
|
||||
- IP-ASN,1,PROXY
|
||||
|
||||
@@ -20,7 +20,7 @@ func init() {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
FullTimestamp: true,
|
||||
TimestampFormat: "2006-01-02T15:04:05.999999999Z07:00",
|
||||
TimestampFormat: "2006-01-02T15:04:05.000000000Z07:00",
|
||||
EnvironmentOverrideColors: true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package common
|
||||
import (
|
||||
"errors"
|
||||
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
@@ -38,3 +40,5 @@ func ParseParams(params []string) (isSrc bool, noResolve bool) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ParseRuleFunc func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (C.Rule, error)
|
||||
|
||||
@@ -23,9 +23,7 @@ type Logic struct {
|
||||
payloadOnce sync.Once
|
||||
}
|
||||
|
||||
type ParseRuleFunc func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (C.Rule, error)
|
||||
|
||||
func NewSubRule(payload, adapter string, subRules map[string][]C.Rule, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewSubRule(payload, adapter string, subRules map[string][]C.Rule, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.SubRules, subRules: subRules}
|
||||
err := logic.parsePayload(fmt.Sprintf("(%s)", payload), parseRule)
|
||||
if err != nil {
|
||||
@@ -38,7 +36,7 @@ func NewSubRule(payload, adapter string, subRules map[string][]C.Rule, parseRule
|
||||
return logic, nil
|
||||
}
|
||||
|
||||
func NewNOT(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewNOT(payload string, adapter string, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.NOT}
|
||||
err := logic.parsePayload(payload, parseRule)
|
||||
if err != nil {
|
||||
@@ -51,7 +49,7 @@ func NewNOT(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, er
|
||||
return logic, nil
|
||||
}
|
||||
|
||||
func NewOR(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewOR(payload string, adapter string, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.OR}
|
||||
err := logic.parsePayload(payload, parseRule)
|
||||
if err != nil {
|
||||
@@ -60,7 +58,7 @@ func NewOR(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, err
|
||||
return logic, nil
|
||||
}
|
||||
|
||||
func NewAND(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewAND(payload string, adapter string, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.AND}
|
||||
err := logic.parsePayload(payload, parseRule)
|
||||
if err != nil {
|
||||
@@ -79,7 +77,7 @@ func (r Range) containRange(preStart, preEnd int) bool {
|
||||
return preStart < r.start && preEnd > r.end
|
||||
}
|
||||
|
||||
func (logic *Logic) payloadToRule(subPayload string, parseRule ParseRuleFunc) (C.Rule, error) {
|
||||
func (logic *Logic) payloadToRule(subPayload string, parseRule common.ParseRuleFunc) (C.Rule, error) {
|
||||
splitStr := strings.SplitN(subPayload, ",", 2)
|
||||
if len(splitStr) < 2 {
|
||||
return nil, fmt.Errorf("[%s] format is error", subPayload)
|
||||
@@ -160,7 +158,7 @@ func (logic *Logic) findSubRuleRange(payload string, ruleRanges []Range) []Range
|
||||
return subRuleRange
|
||||
}
|
||||
|
||||
func (logic *Logic) parsePayload(payload string, parseRule ParseRuleFunc) error {
|
||||
func (logic *Logic) parsePayload(payload string, parseRule common.ParseRuleFunc) error {
|
||||
regex, err := regexp.Compile("\\(.*\\)")
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -91,3 +91,5 @@ func ParseRule(tp, payload, target string, params []string, subRules map[string]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var _ RC.ParseRuleFunc = ParseRule
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/rules/common"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -16,17 +17,18 @@ var (
|
||||
)
|
||||
|
||||
type ruleProviderSchema struct {
|
||||
Type string `provider:"type"`
|
||||
Behavior string `provider:"behavior"`
|
||||
Path string `provider:"path,omitempty"`
|
||||
URL string `provider:"url,omitempty"`
|
||||
Proxy string `provider:"proxy,omitempty"`
|
||||
Format string `provider:"format,omitempty"`
|
||||
Interval int `provider:"interval,omitempty"`
|
||||
SizeLimit int64 `provider:"size-limit,omitempty"`
|
||||
Type string `provider:"type"`
|
||||
Behavior string `provider:"behavior"`
|
||||
Path string `provider:"path,omitempty"`
|
||||
URL string `provider:"url,omitempty"`
|
||||
Proxy string `provider:"proxy,omitempty"`
|
||||
Format string `provider:"format,omitempty"`
|
||||
Interval int `provider:"interval,omitempty"`
|
||||
SizeLimit int64 `provider:"size-limit,omitempty"`
|
||||
Payload []string `provider:"payload,omitempty"`
|
||||
}
|
||||
|
||||
func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) (P.RuleProvider, error) {
|
||||
func ParseRuleProvider(name string, mapping map[string]any, parse common.ParseRuleFunc) (P.RuleProvider, error) {
|
||||
schema := &ruleProviderSchema{}
|
||||
decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true})
|
||||
if err := decoder.Decode(mapping, schema); err != nil {
|
||||
@@ -55,6 +57,8 @@ func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(t
|
||||
}
|
||||
}
|
||||
vehicle = resource.NewHTTPVehicle(schema.URL, path, schema.Proxy, nil, resource.DefaultHttpTimeout, schema.SizeLimit)
|
||||
case "inline":
|
||||
return newInlineProvider(name, behavior, schema.Payload, parse), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported vehicle type: %s", schema.Type)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/rules/common"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -24,9 +25,13 @@ func SetTunnel(t P.Tunnel) {
|
||||
}
|
||||
|
||||
type ruleSetProvider struct {
|
||||
ruleSetProviderBase
|
||||
*resource.Fetcher[ruleStrategy]
|
||||
format P.RuleFormat
|
||||
}
|
||||
|
||||
type ruleSetProviderBase struct {
|
||||
behavior P.RuleBehavior
|
||||
format P.RuleFormat
|
||||
strategy ruleStrategy
|
||||
}
|
||||
|
||||
@@ -61,7 +66,7 @@ type mrsRuleStrategy interface {
|
||||
DumpMrs(f func(key string) bool)
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Type() P.ProviderType {
|
||||
func (rp *ruleSetProviderBase) Type() P.ProviderType {
|
||||
return P.Rule
|
||||
}
|
||||
|
||||
@@ -75,40 +80,51 @@ func (rp *ruleSetProvider) Update() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Behavior() P.RuleBehavior {
|
||||
func (rp *ruleSetProviderBase) Behavior() P.RuleBehavior {
|
||||
return rp.behavior
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Count() int {
|
||||
func (rp *ruleSetProviderBase) Count() int {
|
||||
return rp.strategy.Count()
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Match(metadata *C.Metadata) bool {
|
||||
func (rp *ruleSetProviderBase) Match(metadata *C.Metadata) bool {
|
||||
return rp.strategy != nil && rp.strategy.Match(metadata)
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) ShouldResolveIP() bool {
|
||||
func (rp *ruleSetProviderBase) ShouldResolveIP() bool {
|
||||
return rp.strategy.ShouldResolveIP()
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) ShouldFindProcess() bool {
|
||||
func (rp *ruleSetProviderBase) ShouldFindProcess() bool {
|
||||
return rp.strategy.ShouldFindProcess()
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Strategy() any {
|
||||
func (rp *ruleSetProviderBase) Strategy() any {
|
||||
return rp.strategy
|
||||
}
|
||||
|
||||
type providerForApi struct {
|
||||
Behavior string `json:"behavior"`
|
||||
Format string `json:"format"`
|
||||
Name string `json:"name"`
|
||||
RuleCount int `json:"ruleCount"`
|
||||
Type string `json:"type"`
|
||||
VehicleType string `json:"vehicleType"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
Payload []string `json:"payload,omitempty"`
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(
|
||||
map[string]interface{}{
|
||||
"behavior": rp.behavior.String(),
|
||||
"format": rp.format.String(),
|
||||
"name": rp.Name(),
|
||||
"ruleCount": rp.strategy.Count(),
|
||||
"type": rp.Type().String(),
|
||||
"updatedAt": rp.UpdatedAt(),
|
||||
"vehicleType": rp.VehicleType().String(),
|
||||
providerForApi{
|
||||
Behavior: rp.behavior.String(),
|
||||
Format: rp.format.String(),
|
||||
Name: rp.Fetcher.Name(),
|
||||
RuleCount: rp.strategy.Count(),
|
||||
Type: rp.Type().String(),
|
||||
UpdatedAt: rp.UpdatedAt(),
|
||||
VehicleType: rp.VehicleType().String(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -117,11 +133,12 @@ func (rp *RuleSetProvider) Close() error {
|
||||
return rp.ruleSetProvider.Close()
|
||||
}
|
||||
|
||||
func NewRuleSetProvider(name string, behavior P.RuleBehavior, format P.RuleFormat, interval time.Duration, vehicle P.Vehicle,
|
||||
parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) P.RuleProvider {
|
||||
func NewRuleSetProvider(name string, behavior P.RuleBehavior, format P.RuleFormat, interval time.Duration, vehicle P.Vehicle, parse common.ParseRuleFunc) P.RuleProvider {
|
||||
rp := &ruleSetProvider{
|
||||
behavior: behavior,
|
||||
format: format,
|
||||
ruleSetProviderBase: ruleSetProviderBase{
|
||||
behavior: behavior,
|
||||
},
|
||||
format: format,
|
||||
}
|
||||
|
||||
onUpdate := func(strategy ruleStrategy) {
|
||||
@@ -142,7 +159,7 @@ func NewRuleSetProvider(name string, behavior P.RuleBehavior, format P.RuleForma
|
||||
return wrapper
|
||||
}
|
||||
|
||||
func newStrategy(behavior P.RuleBehavior, parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) ruleStrategy {
|
||||
func newStrategy(behavior P.RuleBehavior, parse common.ParseRuleFunc) ruleStrategy {
|
||||
switch behavior {
|
||||
case P.Domain:
|
||||
strategy := NewDomainStrategy()
|
||||
@@ -158,8 +175,10 @@ func newStrategy(behavior P.RuleBehavior, parse func(tp, payload, target string,
|
||||
}
|
||||
}
|
||||
|
||||
var ErrNoPayload = errors.New("file must have a `payload` field")
|
||||
var ErrInvalidFormat = errors.New("invalid format")
|
||||
var (
|
||||
ErrNoPayload = errors.New("file must have a `payload` field")
|
||||
ErrInvalidFormat = errors.New("invalid format")
|
||||
)
|
||||
|
||||
func rulesParse(buf []byte, strategy ruleStrategy, format P.RuleFormat) (ruleStrategy, error) {
|
||||
strategy.Reset()
|
||||
@@ -254,3 +273,66 @@ func rulesParse(buf []byte, strategy ruleStrategy, format P.RuleFormat) (ruleStr
|
||||
|
||||
return strategy, nil
|
||||
}
|
||||
|
||||
func rulesParseInline(rs []string, strategy ruleStrategy) ruleStrategy {
|
||||
strategy.Reset()
|
||||
for _, r := range rs {
|
||||
if r != "" {
|
||||
strategy.Insert(r)
|
||||
}
|
||||
}
|
||||
strategy.FinishInsert()
|
||||
return strategy
|
||||
}
|
||||
|
||||
type inlineProvider struct {
|
||||
ruleSetProviderBase
|
||||
name string
|
||||
updateTime time.Time
|
||||
payload []string
|
||||
}
|
||||
|
||||
func (i *inlineProvider) Name() string {
|
||||
return i.name
|
||||
}
|
||||
|
||||
func (i *inlineProvider) Initial() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *inlineProvider) Update() error {
|
||||
// make api update happy
|
||||
i.updateTime = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *inlineProvider) VehicleType() P.VehicleType {
|
||||
return P.Inline
|
||||
}
|
||||
|
||||
func (i *inlineProvider) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(
|
||||
providerForApi{
|
||||
Behavior: i.behavior.String(),
|
||||
Name: i.Name(),
|
||||
RuleCount: i.strategy.Count(),
|
||||
Type: i.Type().String(),
|
||||
VehicleType: i.VehicleType().String(),
|
||||
UpdatedAt: i.updateTime,
|
||||
Payload: i.payload,
|
||||
})
|
||||
}
|
||||
|
||||
func newInlineProvider(name string, behavior P.RuleBehavior, payload []string, parse common.ParseRuleFunc) P.RuleProvider {
|
||||
rp := &inlineProvider{
|
||||
ruleSetProviderBase: ruleSetProviderBase{
|
||||
behavior: behavior,
|
||||
strategy: newStrategy(behavior, parse),
|
||||
},
|
||||
payload: payload,
|
||||
name: name,
|
||||
updateTime: time.Now(),
|
||||
}
|
||||
rp.strategy = rulesParseInline(payload, rp.strategy)
|
||||
return rp
|
||||
}
|
||||
|
||||
@@ -18,6 +18,6 @@
|
||||
"swr": "2.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "19.0.1"
|
||||
"@types/react": "19.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
"@csstools/normalize.css": "12.1.1",
|
||||
"@emotion/babel-plugin": "11.13.5",
|
||||
"@emotion/react": "11.14.0",
|
||||
"@iconify/json": "2.2.285",
|
||||
"@iconify/json": "2.2.286",
|
||||
"@monaco-editor/react": "4.6.0",
|
||||
"@tanstack/react-router": "1.89.2",
|
||||
"@tanstack/router-devtools": "1.89.2",
|
||||
@@ -65,7 +65,7 @@
|
||||
"@tauri-apps/plugin-process": "2.2.0",
|
||||
"@tauri-apps/plugin-shell": "2.2.0",
|
||||
"@tauri-apps/plugin-updater": "2.3.0",
|
||||
"@types/react": "19.0.1",
|
||||
"@types/react": "19.0.2",
|
||||
"@types/react-dom": "19.0.2",
|
||||
"@types/validator": "13.12.2",
|
||||
"@vitejs/plugin-legacy": "6.0.0",
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"@radix-ui/react-scroll-area": "1.2.2",
|
||||
"@tauri-apps/api": "2.1.1",
|
||||
"@types/d3": "7.4.3",
|
||||
"@types/react": "19.0.1",
|
||||
"@types/react": "19.0.2",
|
||||
"@vitejs/plugin-react": "4.3.4",
|
||||
"ahooks": "3.8.4",
|
||||
"d3": "7.9.0",
|
||||
@@ -45,6 +45,6 @@
|
||||
"sass-embedded": "1.83.0",
|
||||
"tailwind-merge": "2.5.5",
|
||||
"typescript-plugin-css-modules": "5.1.0",
|
||||
"vite-plugin-dts": "4.3.0"
|
||||
"vite-plugin-dts": "4.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +83,8 @@
|
||||
"eslint-plugin-react": "7.37.2",
|
||||
"eslint-plugin-react-compiler": "19.0.0-beta-df7b47d-20241124",
|
||||
"eslint-plugin-react-hooks": "5.1.0",
|
||||
"globals": "15.13.0",
|
||||
"knip": "5.40.0",
|
||||
"globals": "15.14.0",
|
||||
"knip": "5.41.1",
|
||||
"lint-staged": "15.2.11",
|
||||
"neostandard": "0.12.0",
|
||||
"npm-run-all2": "7.0.1",
|
||||
|
||||
Generated
+277
-358
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,6 @@
|
||||
"picocolors": "1.1.1",
|
||||
"tar": "7.4.3",
|
||||
"telegram": "2.26.8",
|
||||
"undici": "7.1.1"
|
||||
"undici": "7.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,11 +170,11 @@ CONFIG_CONTIG_ALLOC=y
|
||||
CONFIG_CPUFREQ_DT=y
|
||||
CONFIG_CPUFREQ_DT_PLATDEV=y
|
||||
CONFIG_CPU_FREQ=y
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
|
||||
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
|
||||
CONFIG_CPU_FREQ_GOV_ATTR_SET=y
|
||||
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
|
||||
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
|
||||
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
|
||||
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
|
||||
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
|
||||
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
|
||||
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
From af20b3384e8723077cc6484160b0cf4e9be321de Mon Sep 17 00:00:00 2001
|
||||
From: Tianling Shen <cnsztl@gmail.com>
|
||||
Date: Mon, 7 Jun 2021 15:45:37 +0800
|
||||
Subject: [PATCH] arm64: dts: rockchip: add EEPROM node for NanoPi R4S
|
||||
|
||||
NanoPi R4S has a EEPROM attached to the 2nd I2C bus (U92), which
|
||||
stores the MAC address.
|
||||
|
||||
Signed-off-by: Tianling Shen <cnsztl@gmail.com>
|
||||
---
|
||||
arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts
|
||||
@@ -68,6 +68,15 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+&i2c2 {
|
||||
+ eeprom@51 {
|
||||
+ compatible = "microchip,24c02", "atmel,24c02";
|
||||
+ reg = <0x51>;
|
||||
+ pagesize = <16>;
|
||||
+ read-only; /* This holds our MAC */
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
&i2c4 {
|
||||
status = "disabled";
|
||||
};
|
||||
+7486
File diff suppressed because it is too large
Load Diff
+119
@@ -0,0 +1,119 @@
|
||||
From 86e2ed4e9a9680013ec9ab7c0428c9b8c5108efe Mon Sep 17 00:00:00 2001
|
||||
From: Frank Wang <frank.wang@rock-chips.com>
|
||||
Date: Wed, 16 Oct 2024 15:37:10 +0800
|
||||
Subject: [PATCH] phy: rockchip: inno-usb2: convert clock management to bulk
|
||||
|
||||
Since some Rockchip SoCs (e.g RK3576) have more than one clock,
|
||||
this converts the clock management from single to bulk method to
|
||||
make the driver more flexible.
|
||||
|
||||
Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
|
||||
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
|
||||
Link: https://lore.kernel.org/r/20241016073713.14133-1-frawang.cn@gmail.com
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 45 +++++++++++++++----
|
||||
1 file changed, 37 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
|
||||
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
|
||||
@@ -229,9 +229,10 @@ struct rockchip_usb2phy_port {
|
||||
* @dev: pointer to device.
|
||||
* @grf: General Register Files regmap.
|
||||
* @usbgrf: USB General Register Files regmap.
|
||||
- * @clk: clock struct of phy input clk.
|
||||
+ * @clks: array of phy input clocks.
|
||||
* @clk480m: clock struct of phy output clk.
|
||||
* @clk480m_hw: clock struct of phy output clk management.
|
||||
+ * @num_clks: number of phy input clocks.
|
||||
* @phy_reset: phy reset control.
|
||||
* @chg_state: states involved in USB charger detection.
|
||||
* @chg_type: USB charger types.
|
||||
@@ -246,9 +247,10 @@ struct rockchip_usb2phy {
|
||||
struct device *dev;
|
||||
struct regmap *grf;
|
||||
struct regmap *usbgrf;
|
||||
- struct clk *clk;
|
||||
+ struct clk_bulk_data *clks;
|
||||
struct clk *clk480m;
|
||||
struct clk_hw clk480m_hw;
|
||||
+ int num_clks;
|
||||
struct reset_control *phy_reset;
|
||||
enum usb_chg_state chg_state;
|
||||
enum power_supply_type chg_type;
|
||||
@@ -310,6 +312,13 @@ static int rockchip_usb2phy_reset(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void rockchip_usb2phy_clk_bulk_disable(void *data)
|
||||
+{
|
||||
+ struct rockchip_usb2phy *rphy = data;
|
||||
+
|
||||
+ clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks);
|
||||
+}
|
||||
+
|
||||
static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_usb2phy *rphy =
|
||||
@@ -376,7 +385,9 @@ rockchip_usb2phy_clk480m_register(struct
|
||||
{
|
||||
struct device_node *node = rphy->dev->of_node;
|
||||
struct clk_init_data init;
|
||||
+ struct clk *refclk = NULL;
|
||||
const char *clk_name;
|
||||
+ int i;
|
||||
int ret = 0;
|
||||
|
||||
init.flags = 0;
|
||||
@@ -386,8 +397,15 @@ rockchip_usb2phy_clk480m_register(struct
|
||||
/* optional override of the clockname */
|
||||
of_property_read_string(node, "clock-output-names", &init.name);
|
||||
|
||||
- if (rphy->clk) {
|
||||
- clk_name = __clk_get_name(rphy->clk);
|
||||
+ for (i = 0; i < rphy->num_clks; i++) {
|
||||
+ if (!strncmp(rphy->clks[i].id, "phyclk", 6)) {
|
||||
+ refclk = rphy->clks[i].clk;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!IS_ERR(refclk)) {
|
||||
+ clk_name = __clk_get_name(refclk);
|
||||
init.parent_names = &clk_name;
|
||||
init.num_parents = 1;
|
||||
} else {
|
||||
@@ -1406,11 +1424,13 @@ static int rockchip_usb2phy_probe(struct
|
||||
if (IS_ERR(rphy->phy_reset))
|
||||
return PTR_ERR(rphy->phy_reset);
|
||||
|
||||
- rphy->clk = devm_clk_get_optional_enabled(dev, "phyclk");
|
||||
- if (IS_ERR(rphy->clk)) {
|
||||
- return dev_err_probe(&pdev->dev, PTR_ERR(rphy->clk),
|
||||
- "failed to get phyclk\n");
|
||||
- }
|
||||
+ ret = devm_clk_bulk_get_all(dev, &rphy->clks);
|
||||
+ if (ret == -EPROBE_DEFER)
|
||||
+ return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
|
||||
+ "failed to get phy clock\n");
|
||||
+
|
||||
+ /* Clocks are optional */
|
||||
+ rphy->num_clks = ret < 0 ? 0 : ret;
|
||||
|
||||
ret = rockchip_usb2phy_clk480m_register(rphy);
|
||||
if (ret) {
|
||||
@@ -1418,6 +1438,14 @@ static int rockchip_usb2phy_probe(struct
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ ret = clk_bulk_prepare_enable(rphy->num_clks, rphy->clks);
|
||||
+ if (ret)
|
||||
+ return dev_err_probe(dev, ret, "failed to enable phy clock\n");
|
||||
+
|
||||
+ ret = devm_add_action_or_reset(dev, rockchip_usb2phy_clk_bulk_disable, rphy);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
if (rphy->phy_cfg->phy_tuning) {
|
||||
ret = rphy->phy_cfg->phy_tuning(rphy);
|
||||
if (ret)
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
From 3d7de6e870ece5a32153382df9df6fb87613335e Mon Sep 17 00:00:00 2001
|
||||
From: William Wu <william.wu@rock-chips.com>
|
||||
Date: Wed, 16 Oct 2024 15:37:13 +0800
|
||||
Subject: [PATCH] phy: rockchip: inno-usb2: Add usb2 phys support for rk3576
|
||||
|
||||
The RK3576 SoC has two independent USB2.0 PHYs, and each PHY has
|
||||
one port. This adds device specific data for it.
|
||||
|
||||
Signed-off-by: William Wu <william.wu@rock-chips.com>
|
||||
Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
|
||||
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
|
||||
Link: https://lore.kernel.org/r/20241016073713.14133-4-frawang.cn@gmail.com
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 103 ++++++++++++++++++
|
||||
1 file changed, 103 insertions(+)
|
||||
|
||||
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
|
||||
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
|
||||
@@ -1523,6 +1523,30 @@ static int rk3128_usb2phy_tuning(struct
|
||||
BIT(2) << BIT_WRITEABLE_SHIFT | 0);
|
||||
}
|
||||
|
||||
+static int rk3576_usb2phy_tuning(struct rockchip_usb2phy *rphy)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u32 reg = rphy->phy_cfg->reg;
|
||||
+
|
||||
+ /* Deassert SIDDQ to power on analog block */
|
||||
+ ret = regmap_write(rphy->grf, reg + 0x0010, GENMASK(29, 29) | 0x0000);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Do reset after exit IDDQ mode */
|
||||
+ ret = rockchip_usb2phy_reset(rphy);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */
|
||||
+ ret |= regmap_write(rphy->grf, reg + 0x000c, GENMASK(27, 24) | 0x0900);
|
||||
+
|
||||
+ /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */
|
||||
+ ret |= regmap_write(rphy->grf, reg + 0x0010, GENMASK(20, 19) | 0x0010);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int rk3588_usb2phy_tuning(struct rockchip_usb2phy *rphy)
|
||||
{
|
||||
int ret;
|
||||
@@ -1951,6 +1975,84 @@ static const struct rockchip_usb2phy_cfg
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
+static const struct rockchip_usb2phy_cfg rk3576_phy_cfgs[] = {
|
||||
+ {
|
||||
+ .reg = 0x0,
|
||||
+ .num_ports = 1,
|
||||
+ .phy_tuning = rk3576_usb2phy_tuning,
|
||||
+ .clkout_ctl = { 0x0008, 0, 0, 1, 0 },
|
||||
+ .port_cfgs = {
|
||||
+ [USB2PHY_PORT_OTG] = {
|
||||
+ .phy_sus = { 0x0000, 8, 0, 0, 0x1d1 },
|
||||
+ .bvalid_det_en = { 0x00c0, 1, 1, 0, 1 },
|
||||
+ .bvalid_det_st = { 0x00c4, 1, 1, 0, 1 },
|
||||
+ .bvalid_det_clr = { 0x00c8, 1, 1, 0, 1 },
|
||||
+ .ls_det_en = { 0x00c0, 0, 0, 0, 1 },
|
||||
+ .ls_det_st = { 0x00c4, 0, 0, 0, 1 },
|
||||
+ .ls_det_clr = { 0x00c8, 0, 0, 0, 1 },
|
||||
+ .disfall_en = { 0x00c0, 6, 6, 0, 1 },
|
||||
+ .disfall_st = { 0x00c4, 6, 6, 0, 1 },
|
||||
+ .disfall_clr = { 0x00c8, 6, 6, 0, 1 },
|
||||
+ .disrise_en = { 0x00c0, 5, 5, 0, 1 },
|
||||
+ .disrise_st = { 0x00c4, 5, 5, 0, 1 },
|
||||
+ .disrise_clr = { 0x00c8, 5, 5, 0, 1 },
|
||||
+ .utmi_avalid = { 0x0080, 1, 1, 0, 1 },
|
||||
+ .utmi_bvalid = { 0x0080, 0, 0, 0, 1 },
|
||||
+ .utmi_ls = { 0x0080, 5, 4, 0, 1 },
|
||||
+ }
|
||||
+ },
|
||||
+ .chg_det = {
|
||||
+ .cp_det = { 0x0080, 8, 8, 0, 1 },
|
||||
+ .dcp_det = { 0x0080, 8, 8, 0, 1 },
|
||||
+ .dp_det = { 0x0080, 9, 9, 1, 0 },
|
||||
+ .idm_sink_en = { 0x0010, 5, 5, 1, 0 },
|
||||
+ .idp_sink_en = { 0x0010, 5, 5, 0, 1 },
|
||||
+ .idp_src_en = { 0x0010, 14, 14, 0, 1 },
|
||||
+ .rdm_pdwn_en = { 0x0010, 14, 14, 0, 1 },
|
||||
+ .vdm_src_en = { 0x0010, 7, 6, 0, 3 },
|
||||
+ .vdp_src_en = { 0x0010, 7, 6, 0, 3 },
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .reg = 0x2000,
|
||||
+ .num_ports = 1,
|
||||
+ .phy_tuning = rk3576_usb2phy_tuning,
|
||||
+ .clkout_ctl = { 0x2008, 0, 0, 1, 0 },
|
||||
+ .port_cfgs = {
|
||||
+ [USB2PHY_PORT_OTG] = {
|
||||
+ .phy_sus = { 0x2000, 8, 0, 0, 0x1d1 },
|
||||
+ .bvalid_det_en = { 0x20c0, 1, 1, 0, 1 },
|
||||
+ .bvalid_det_st = { 0x20c4, 1, 1, 0, 1 },
|
||||
+ .bvalid_det_clr = { 0x20c8, 1, 1, 0, 1 },
|
||||
+ .ls_det_en = { 0x20c0, 0, 0, 0, 1 },
|
||||
+ .ls_det_st = { 0x20c4, 0, 0, 0, 1 },
|
||||
+ .ls_det_clr = { 0x20c8, 0, 0, 0, 1 },
|
||||
+ .disfall_en = { 0x20c0, 6, 6, 0, 1 },
|
||||
+ .disfall_st = { 0x20c4, 6, 6, 0, 1 },
|
||||
+ .disfall_clr = { 0x20c8, 6, 6, 0, 1 },
|
||||
+ .disrise_en = { 0x20c0, 5, 5, 0, 1 },
|
||||
+ .disrise_st = { 0x20c4, 5, 5, 0, 1 },
|
||||
+ .disrise_clr = { 0x20c8, 5, 5, 0, 1 },
|
||||
+ .utmi_avalid = { 0x2080, 1, 1, 0, 1 },
|
||||
+ .utmi_bvalid = { 0x2080, 0, 0, 0, 1 },
|
||||
+ .utmi_ls = { 0x2080, 5, 4, 0, 1 },
|
||||
+ }
|
||||
+ },
|
||||
+ .chg_det = {
|
||||
+ .cp_det = { 0x2080, 8, 8, 0, 1 },
|
||||
+ .dcp_det = { 0x2080, 8, 8, 0, 1 },
|
||||
+ .dp_det = { 0x2080, 9, 9, 1, 0 },
|
||||
+ .idm_sink_en = { 0x2010, 5, 5, 1, 0 },
|
||||
+ .idp_sink_en = { 0x2010, 5, 5, 0, 1 },
|
||||
+ .idp_src_en = { 0x2010, 14, 14, 0, 1 },
|
||||
+ .rdm_pdwn_en = { 0x2010, 14, 14, 0, 1 },
|
||||
+ .vdm_src_en = { 0x2010, 7, 6, 0, 3 },
|
||||
+ .vdp_src_en = { 0x2010, 7, 6, 0, 3 },
|
||||
+ },
|
||||
+ },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+
|
||||
static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = {
|
||||
{
|
||||
.reg = 0x0000,
|
||||
@@ -2122,6 +2224,7 @@ static const struct of_device_id rockchi
|
||||
{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
|
||||
{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
|
||||
{ .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
|
||||
+ { .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs },
|
||||
{ .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs },
|
||||
{ .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
|
||||
{}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
From a76de028c619dd18f89786805bcc7bb4d379ea9f Mon Sep 17 00:00:00 2001
|
||||
From: Frank Wang <frank.wang@rock-chips.com>
|
||||
Date: Mon, 14 Oct 2024 10:03:42 +0800
|
||||
Subject: [PATCH] phy: rockchip: usbdp: add rk3576 device match data
|
||||
|
||||
This adds RK3576 device match data support.
|
||||
|
||||
Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
|
||||
Acked-by: Dragan Simic <dsimic@manjaro.org>
|
||||
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
|
||||
Link: https://lore.kernel.org/r/20241014020342.15974-2-frawang.cn@gmail.com
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
drivers/phy/rockchip/phy-rockchip-usbdp.c | 41 +++++++++++++++++++++++
|
||||
1 file changed, 41 insertions(+)
|
||||
|
||||
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
|
||||
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
|
||||
@@ -1538,6 +1538,43 @@ static const char * const rk_udphy_rst_l
|
||||
"init", "cmn", "lane", "pcs_apb", "pma_apb"
|
||||
};
|
||||
|
||||
+static const struct rk_udphy_cfg rk3576_udphy_cfgs = {
|
||||
+ .num_phys = 1,
|
||||
+ .phy_ids = { 0x2b010000 },
|
||||
+ .num_rsts = ARRAY_SIZE(rk_udphy_rst_list),
|
||||
+ .rst_list = rk_udphy_rst_list,
|
||||
+ .grfcfg = {
|
||||
+ /* u2phy-grf */
|
||||
+ .bvalid_phy_con = RK_UDPHY_GEN_GRF_REG(0x0010, 1, 0, 0x2, 0x3),
|
||||
+ .bvalid_grf_con = RK_UDPHY_GEN_GRF_REG(0x0000, 15, 14, 0x1, 0x3),
|
||||
+
|
||||
+ /* usb-grf */
|
||||
+ .usb3otg0_cfg = RK_UDPHY_GEN_GRF_REG(0x0030, 15, 0, 0x1100, 0x0188),
|
||||
+
|
||||
+ /* usbdpphy-grf */
|
||||
+ .low_pwrn = RK_UDPHY_GEN_GRF_REG(0x0004, 13, 13, 0, 1),
|
||||
+ .rx_lfps = RK_UDPHY_GEN_GRF_REG(0x0004, 14, 14, 0, 1),
|
||||
+ },
|
||||
+ .vogrfcfg = {
|
||||
+ {
|
||||
+ .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0000, 11, 10, 1, 3),
|
||||
+ .dp_lane_reg = 0x0000,
|
||||
+ },
|
||||
+ },
|
||||
+ .dp_tx_ctrl_cfg = {
|
||||
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
|
||||
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
|
||||
+ rk3588_dp_tx_drv_ctrl_hbr2,
|
||||
+ rk3588_dp_tx_drv_ctrl_hbr3,
|
||||
+ },
|
||||
+ .dp_tx_ctrl_cfg_typec = {
|
||||
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
|
||||
+ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec,
|
||||
+ rk3588_dp_tx_drv_ctrl_hbr2,
|
||||
+ rk3588_dp_tx_drv_ctrl_hbr3,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static const struct rk_udphy_cfg rk3588_udphy_cfgs = {
|
||||
.num_phys = 2,
|
||||
.phy_ids = {
|
||||
@@ -1585,6 +1622,10 @@ static const struct rk_udphy_cfg rk3588_
|
||||
|
||||
static const struct of_device_id rk_udphy_dt_match[] = {
|
||||
{
|
||||
+ .compatible = "rockchip,rk3576-usbdp-phy",
|
||||
+ .data = &rk3576_udphy_cfgs
|
||||
+ },
|
||||
+ {
|
||||
.compatible = "rockchip,rk3588-usbdp-phy",
|
||||
.data = &rk3588_udphy_cfgs
|
||||
},
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
From 591ae6bed250e4067db926313ff7279d23a1c7d1 Mon Sep 17 00:00:00 2001
|
||||
From: Ye Zhang <ye.zhang@rock-chips.com>
|
||||
Date: Tue, 12 Nov 2024 09:54:05 +0800
|
||||
Subject: [PATCH] gpio: rockchip: explan the format of the GPIO version ID
|
||||
|
||||
Remove redundant comments and provide a detailed explanation of the
|
||||
GPIO version ID.
|
||||
|
||||
Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
|
||||
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
Link: https://lore.kernel.org/r/20241112015408.3139996-2-ye.zhang@rock-chips.com
|
||||
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
|
||||
---
|
||||
drivers/gpio/gpio-rockchip.c | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/gpio/gpio-rockchip.c
|
||||
+++ b/drivers/gpio/gpio-rockchip.c
|
||||
@@ -26,9 +26,15 @@
|
||||
#include "../pinctrl/core.h"
|
||||
#include "../pinctrl/pinctrl-rockchip.h"
|
||||
|
||||
+/*
|
||||
+ * Version ID Register
|
||||
+ * Bits [31:24] - Major Version
|
||||
+ * Bits [23:16] - Minor Version
|
||||
+ * Bits [15:0] - Revision Number
|
||||
+ */
|
||||
#define GPIO_TYPE_V1 (0) /* GPIO Version ID reserved */
|
||||
-#define GPIO_TYPE_V2 (0x01000C2B) /* GPIO Version ID 0x01000C2B */
|
||||
-#define GPIO_TYPE_V2_1 (0x0101157C) /* GPIO Version ID 0x0101157C */
|
||||
+#define GPIO_TYPE_V2 (0x01000C2B)
|
||||
+#define GPIO_TYPE_V2_1 (0x0101157C)
|
||||
|
||||
static const struct rockchip_gpio_regs gpio_regs_v1 = {
|
||||
.port_dr = 0x00,
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
From 41209307cad7f14c387c68375a93b50e54261a53 Mon Sep 17 00:00:00 2001
|
||||
From: Ye Zhang <ye.zhang@rock-chips.com>
|
||||
Date: Tue, 12 Nov 2024 09:54:06 +0800
|
||||
Subject: [PATCH] gpio: rockchip: change the GPIO version judgment logic
|
||||
|
||||
Have a list of valid IDs and default to -ENODEV.
|
||||
|
||||
Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
|
||||
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
Link: https://lore.kernel.org/r/20241112015408.3139996-3-ye.zhang@rock-chips.com
|
||||
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
|
||||
---
|
||||
drivers/gpio/gpio-rockchip.c | 12 +++++++++---
|
||||
1 file changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/gpio/gpio-rockchip.c
|
||||
+++ b/drivers/gpio/gpio-rockchip.c
|
||||
@@ -667,8 +667,9 @@ static int rockchip_get_bank_data(struct
|
||||
clk_prepare_enable(bank->clk);
|
||||
id = readl(bank->reg_base + gpio_regs_v2.version_id);
|
||||
|
||||
- /* If not gpio v2, that is default to v1. */
|
||||
- if (id == GPIO_TYPE_V2 || id == GPIO_TYPE_V2_1) {
|
||||
+ switch (id) {
|
||||
+ case GPIO_TYPE_V2:
|
||||
+ case GPIO_TYPE_V2_1:
|
||||
bank->gpio_regs = &gpio_regs_v2;
|
||||
bank->gpio_type = GPIO_TYPE_V2;
|
||||
bank->db_clk = of_clk_get(bank->of_node, 1);
|
||||
@@ -677,9 +678,14 @@ static int rockchip_get_bank_data(struct
|
||||
clk_disable_unprepare(bank->clk);
|
||||
return -EINVAL;
|
||||
}
|
||||
- } else {
|
||||
+ break;
|
||||
+ case GPIO_TYPE_V1:
|
||||
bank->gpio_regs = &gpio_regs_v1;
|
||||
bank->gpio_type = GPIO_TYPE_V1;
|
||||
+ break;
|
||||
+ default:
|
||||
+ dev_err(bank->dev, "unsupported version ID: 0x%08x\n", id);
|
||||
+ return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
From 8bcbd0379c05c66ce2e842c7e8901aa317cdf04e Mon Sep 17 00:00:00 2001
|
||||
From: Ye Zhang <ye.zhang@rock-chips.com>
|
||||
Date: Tue, 12 Nov 2024 09:54:07 +0800
|
||||
Subject: [PATCH] gpio: rockchip: support new version GPIO
|
||||
|
||||
Support the next version GPIO controller on SoCs like rk3576.
|
||||
|
||||
Signed-off-by: Ye Zhang <ye.zhang@rock-chips.com>
|
||||
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
||||
Link: https://lore.kernel.org/r/20241112015408.3139996-4-ye.zhang@rock-chips.com
|
||||
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
|
||||
---
|
||||
drivers/gpio/gpio-rockchip.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/drivers/gpio/gpio-rockchip.c
|
||||
+++ b/drivers/gpio/gpio-rockchip.c
|
||||
@@ -35,6 +35,7 @@
|
||||
#define GPIO_TYPE_V1 (0) /* GPIO Version ID reserved */
|
||||
#define GPIO_TYPE_V2 (0x01000C2B)
|
||||
#define GPIO_TYPE_V2_1 (0x0101157C)
|
||||
+#define GPIO_TYPE_V2_2 (0x010219C8)
|
||||
|
||||
static const struct rockchip_gpio_regs gpio_regs_v1 = {
|
||||
.port_dr = 0x00,
|
||||
@@ -670,6 +671,7 @@ static int rockchip_get_bank_data(struct
|
||||
switch (id) {
|
||||
case GPIO_TYPE_V2:
|
||||
case GPIO_TYPE_V2_1:
|
||||
+ case GPIO_TYPE_V2_2:
|
||||
bank->gpio_regs = &gpio_regs_v2;
|
||||
bank->gpio_type = GPIO_TYPE_V2;
|
||||
bank->db_clk = of_clk_get(bank->of_node, 1);
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
From d2166e3b3680bd2b206aebf1e1ce4c0d346f3c50 Mon Sep 17 00:00:00 2001
|
||||
From: Tianling Shen <cnsztl@gmail.com>
|
||||
Date: Fri, 19 May 2023 12:10:52 +0800
|
||||
Subject: [PATCH] arm64: dts: rockchip: Update LED properties for Orange Pi R1
|
||||
Plus
|
||||
|
||||
Add OpenWrt's LED aliases for showing system status.
|
||||
|
||||
Signed-off-by: Tianling Shen <cnsztl@gmail.com>
|
||||
---
|
||||
.../dts/rockchip/rk3328-orangepi-r1-plus.dts | 17 +++++++++--------
|
||||
1 file changed, 9 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts
|
||||
@@ -18,6 +18,11 @@
|
||||
ethernet0 = &gmac2io;
|
||||
ethernet1 = &rtl8153;
|
||||
mmc0 = &sdmmc;
|
||||
+
|
||||
+ led-boot = &status_led;
|
||||
+ led-failsafe = &status_led;
|
||||
+ led-running = &status_led;
|
||||
+ led-upgrade = &status_led;
|
||||
};
|
||||
|
||||
chosen {
|
||||
@@ -42,11 +47,10 @@
|
||||
gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
- led-1 {
|
||||
+ status_led: led-1 {
|
||||
function = LED_FUNCTION_STATUS;
|
||||
color = <LED_COLOR_ID_RED>;
|
||||
gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
|
||||
- linux,default-trigger = "heartbeat";
|
||||
};
|
||||
|
||||
led-2 {
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
From b46a530d12ada422b9d5b2b97059e0d3ed950b40 Mon Sep 17 00:00:00 2001
|
||||
From: Tianling Shen <cnsztl@gmail.com>
|
||||
Date: Fri, 19 May 2023 12:38:04 +0800
|
||||
Subject: [PATCH] arm64: dts: rockchip: add LED configuration to Orange Pi R1
|
||||
Plus
|
||||
|
||||
Add the correct value for the RTL8153 LED configuration register to
|
||||
match the blink behavior of the other port on the device.
|
||||
|
||||
Signed-off-by: Tianling Shen <cnsztl@gmail.com>
|
||||
---
|
||||
arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3328-orangepi-r1-plus.dts
|
||||
@@ -366,6 +366,7 @@
|
||||
rtl8153: device@2 {
|
||||
compatible = "usbbda,8153";
|
||||
reg = <2>;
|
||||
+ realtek,led-data = <0x87>;
|
||||
};
|
||||
};
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
From 04202df5cb497b1934c95211cf43784ef62245a4 Mon Sep 17 00:00:00 2001
|
||||
From: Tianling Shen <cnsztl@immortalwrt.org>
|
||||
Date: Mon, 18 Oct 2021 12:47:30 +0800
|
||||
Subject: [PATCH] rockchip: rk3399: overclock to 2.2/1.8 GHz
|
||||
|
||||
It's stable enough to overclock cpu frequency to 2.2/1.8 GHz,
|
||||
and for better performance.
|
||||
|
||||
Co-development-by: gzelvis <gzelvis@gmail.com>
|
||||
Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
|
||||
---
|
||||
arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
--- /dev/null
|
||||
+++ b/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi
|
||||
@@ -0,0 +1,26 @@
|
||||
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
+/*
|
||||
+ * Copyright (c) 2016-2017 Fuzhou Rockchip Electronics Co., Ltd
|
||||
+ */
|
||||
+
|
||||
+#include "rk3399-op1.dtsi"
|
||||
+
|
||||
+/ {
|
||||
+ cluster0_opp: opp-table-0 {
|
||||
+ opp07 {
|
||||
+ opp-hz = /bits/ 64 <1608000000>;
|
||||
+ opp-microvolt = <1225000 1225000 1225000>;
|
||||
+ };
|
||||
+ opp08 {
|
||||
+ opp-hz = /bits/ 64 <1800000000>;
|
||||
+ opp-microvolt = <1275000 1275000 1275000>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ cluster1_opp: opp-table-1 {
|
||||
+ opp09 {
|
||||
+ opp-hz = /bits/ 64 <2208000000>;
|
||||
+ opp-microvolt = <1325000 1325000 1325000>;
|
||||
+ };
|
||||
+ };
|
||||
+};
|
||||
@@ -13,6 +13,7 @@ const (
|
||||
File VehicleType = iota
|
||||
HTTP
|
||||
Compatible
|
||||
Inline
|
||||
)
|
||||
|
||||
// VehicleType defined
|
||||
@@ -26,6 +27,8 @@ func (v VehicleType) String() string {
|
||||
return "HTTP"
|
||||
case Compatible:
|
||||
return "Compatible"
|
||||
case Inline:
|
||||
return "Inline"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
@@ -1014,6 +1014,14 @@ rule-providers:
|
||||
format: mrs
|
||||
behavior: domain
|
||||
path: /path/to/save/file.mrs
|
||||
rule4:
|
||||
type: inline
|
||||
behavior: domain # classical / ipcidr
|
||||
payload:
|
||||
- '.blogger.com'
|
||||
- '*.*.microsoft.com'
|
||||
- 'books.itunes.apple.com'
|
||||
|
||||
rules:
|
||||
- RULE-SET,rule1,REJECT
|
||||
- IP-ASN,1,PROXY
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ func init() {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
FullTimestamp: true,
|
||||
TimestampFormat: "2006-01-02T15:04:05.999999999Z07:00",
|
||||
TimestampFormat: "2006-01-02T15:04:05.000000000Z07:00",
|
||||
EnvironmentOverrideColors: true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package common
|
||||
import (
|
||||
"errors"
|
||||
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
@@ -38,3 +40,5 @@ func ParseParams(params []string) (isSrc bool, noResolve bool) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ParseRuleFunc func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (C.Rule, error)
|
||||
|
||||
@@ -23,9 +23,7 @@ type Logic struct {
|
||||
payloadOnce sync.Once
|
||||
}
|
||||
|
||||
type ParseRuleFunc func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (C.Rule, error)
|
||||
|
||||
func NewSubRule(payload, adapter string, subRules map[string][]C.Rule, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewSubRule(payload, adapter string, subRules map[string][]C.Rule, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.SubRules, subRules: subRules}
|
||||
err := logic.parsePayload(fmt.Sprintf("(%s)", payload), parseRule)
|
||||
if err != nil {
|
||||
@@ -38,7 +36,7 @@ func NewSubRule(payload, adapter string, subRules map[string][]C.Rule, parseRule
|
||||
return logic, nil
|
||||
}
|
||||
|
||||
func NewNOT(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewNOT(payload string, adapter string, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.NOT}
|
||||
err := logic.parsePayload(payload, parseRule)
|
||||
if err != nil {
|
||||
@@ -51,7 +49,7 @@ func NewNOT(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, er
|
||||
return logic, nil
|
||||
}
|
||||
|
||||
func NewOR(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewOR(payload string, adapter string, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.OR}
|
||||
err := logic.parsePayload(payload, parseRule)
|
||||
if err != nil {
|
||||
@@ -60,7 +58,7 @@ func NewOR(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, err
|
||||
return logic, nil
|
||||
}
|
||||
|
||||
func NewAND(payload string, adapter string, parseRule ParseRuleFunc) (*Logic, error) {
|
||||
func NewAND(payload string, adapter string, parseRule common.ParseRuleFunc) (*Logic, error) {
|
||||
logic := &Logic{Base: &common.Base{}, payload: payload, adapter: adapter, ruleType: C.AND}
|
||||
err := logic.parsePayload(payload, parseRule)
|
||||
if err != nil {
|
||||
@@ -79,7 +77,7 @@ func (r Range) containRange(preStart, preEnd int) bool {
|
||||
return preStart < r.start && preEnd > r.end
|
||||
}
|
||||
|
||||
func (logic *Logic) payloadToRule(subPayload string, parseRule ParseRuleFunc) (C.Rule, error) {
|
||||
func (logic *Logic) payloadToRule(subPayload string, parseRule common.ParseRuleFunc) (C.Rule, error) {
|
||||
splitStr := strings.SplitN(subPayload, ",", 2)
|
||||
if len(splitStr) < 2 {
|
||||
return nil, fmt.Errorf("[%s] format is error", subPayload)
|
||||
@@ -160,7 +158,7 @@ func (logic *Logic) findSubRuleRange(payload string, ruleRanges []Range) []Range
|
||||
return subRuleRange
|
||||
}
|
||||
|
||||
func (logic *Logic) parsePayload(payload string, parseRule ParseRuleFunc) error {
|
||||
func (logic *Logic) parsePayload(payload string, parseRule common.ParseRuleFunc) error {
|
||||
regex, err := regexp.Compile("\\(.*\\)")
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -91,3 +91,5 @@ func ParseRule(tp, payload, target string, params []string, subRules map[string]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var _ RC.ParseRuleFunc = ParseRule
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/rules/common"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -16,17 +17,18 @@ var (
|
||||
)
|
||||
|
||||
type ruleProviderSchema struct {
|
||||
Type string `provider:"type"`
|
||||
Behavior string `provider:"behavior"`
|
||||
Path string `provider:"path,omitempty"`
|
||||
URL string `provider:"url,omitempty"`
|
||||
Proxy string `provider:"proxy,omitempty"`
|
||||
Format string `provider:"format,omitempty"`
|
||||
Interval int `provider:"interval,omitempty"`
|
||||
SizeLimit int64 `provider:"size-limit,omitempty"`
|
||||
Type string `provider:"type"`
|
||||
Behavior string `provider:"behavior"`
|
||||
Path string `provider:"path,omitempty"`
|
||||
URL string `provider:"url,omitempty"`
|
||||
Proxy string `provider:"proxy,omitempty"`
|
||||
Format string `provider:"format,omitempty"`
|
||||
Interval int `provider:"interval,omitempty"`
|
||||
SizeLimit int64 `provider:"size-limit,omitempty"`
|
||||
Payload []string `provider:"payload,omitempty"`
|
||||
}
|
||||
|
||||
func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) (P.RuleProvider, error) {
|
||||
func ParseRuleProvider(name string, mapping map[string]any, parse common.ParseRuleFunc) (P.RuleProvider, error) {
|
||||
schema := &ruleProviderSchema{}
|
||||
decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true})
|
||||
if err := decoder.Decode(mapping, schema); err != nil {
|
||||
@@ -55,6 +57,8 @@ func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(t
|
||||
}
|
||||
}
|
||||
vehicle = resource.NewHTTPVehicle(schema.URL, path, schema.Proxy, nil, resource.DefaultHttpTimeout, schema.SizeLimit)
|
||||
case "inline":
|
||||
return newInlineProvider(name, behavior, schema.Payload, parse), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported vehicle type: %s", schema.Type)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
P "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/rules/common"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -24,9 +25,13 @@ func SetTunnel(t P.Tunnel) {
|
||||
}
|
||||
|
||||
type ruleSetProvider struct {
|
||||
ruleSetProviderBase
|
||||
*resource.Fetcher[ruleStrategy]
|
||||
format P.RuleFormat
|
||||
}
|
||||
|
||||
type ruleSetProviderBase struct {
|
||||
behavior P.RuleBehavior
|
||||
format P.RuleFormat
|
||||
strategy ruleStrategy
|
||||
}
|
||||
|
||||
@@ -61,7 +66,7 @@ type mrsRuleStrategy interface {
|
||||
DumpMrs(f func(key string) bool)
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Type() P.ProviderType {
|
||||
func (rp *ruleSetProviderBase) Type() P.ProviderType {
|
||||
return P.Rule
|
||||
}
|
||||
|
||||
@@ -75,40 +80,51 @@ func (rp *ruleSetProvider) Update() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Behavior() P.RuleBehavior {
|
||||
func (rp *ruleSetProviderBase) Behavior() P.RuleBehavior {
|
||||
return rp.behavior
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Count() int {
|
||||
func (rp *ruleSetProviderBase) Count() int {
|
||||
return rp.strategy.Count()
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Match(metadata *C.Metadata) bool {
|
||||
func (rp *ruleSetProviderBase) Match(metadata *C.Metadata) bool {
|
||||
return rp.strategy != nil && rp.strategy.Match(metadata)
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) ShouldResolveIP() bool {
|
||||
func (rp *ruleSetProviderBase) ShouldResolveIP() bool {
|
||||
return rp.strategy.ShouldResolveIP()
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) ShouldFindProcess() bool {
|
||||
func (rp *ruleSetProviderBase) ShouldFindProcess() bool {
|
||||
return rp.strategy.ShouldFindProcess()
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) Strategy() any {
|
||||
func (rp *ruleSetProviderBase) Strategy() any {
|
||||
return rp.strategy
|
||||
}
|
||||
|
||||
type providerForApi struct {
|
||||
Behavior string `json:"behavior"`
|
||||
Format string `json:"format"`
|
||||
Name string `json:"name"`
|
||||
RuleCount int `json:"ruleCount"`
|
||||
Type string `json:"type"`
|
||||
VehicleType string `json:"vehicleType"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
Payload []string `json:"payload,omitempty"`
|
||||
}
|
||||
|
||||
func (rp *ruleSetProvider) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(
|
||||
map[string]interface{}{
|
||||
"behavior": rp.behavior.String(),
|
||||
"format": rp.format.String(),
|
||||
"name": rp.Name(),
|
||||
"ruleCount": rp.strategy.Count(),
|
||||
"type": rp.Type().String(),
|
||||
"updatedAt": rp.UpdatedAt(),
|
||||
"vehicleType": rp.VehicleType().String(),
|
||||
providerForApi{
|
||||
Behavior: rp.behavior.String(),
|
||||
Format: rp.format.String(),
|
||||
Name: rp.Fetcher.Name(),
|
||||
RuleCount: rp.strategy.Count(),
|
||||
Type: rp.Type().String(),
|
||||
UpdatedAt: rp.UpdatedAt(),
|
||||
VehicleType: rp.VehicleType().String(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -117,11 +133,12 @@ func (rp *RuleSetProvider) Close() error {
|
||||
return rp.ruleSetProvider.Close()
|
||||
}
|
||||
|
||||
func NewRuleSetProvider(name string, behavior P.RuleBehavior, format P.RuleFormat, interval time.Duration, vehicle P.Vehicle,
|
||||
parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) P.RuleProvider {
|
||||
func NewRuleSetProvider(name string, behavior P.RuleBehavior, format P.RuleFormat, interval time.Duration, vehicle P.Vehicle, parse common.ParseRuleFunc) P.RuleProvider {
|
||||
rp := &ruleSetProvider{
|
||||
behavior: behavior,
|
||||
format: format,
|
||||
ruleSetProviderBase: ruleSetProviderBase{
|
||||
behavior: behavior,
|
||||
},
|
||||
format: format,
|
||||
}
|
||||
|
||||
onUpdate := func(strategy ruleStrategy) {
|
||||
@@ -142,7 +159,7 @@ func NewRuleSetProvider(name string, behavior P.RuleBehavior, format P.RuleForma
|
||||
return wrapper
|
||||
}
|
||||
|
||||
func newStrategy(behavior P.RuleBehavior, parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) ruleStrategy {
|
||||
func newStrategy(behavior P.RuleBehavior, parse common.ParseRuleFunc) ruleStrategy {
|
||||
switch behavior {
|
||||
case P.Domain:
|
||||
strategy := NewDomainStrategy()
|
||||
@@ -158,8 +175,10 @@ func newStrategy(behavior P.RuleBehavior, parse func(tp, payload, target string,
|
||||
}
|
||||
}
|
||||
|
||||
var ErrNoPayload = errors.New("file must have a `payload` field")
|
||||
var ErrInvalidFormat = errors.New("invalid format")
|
||||
var (
|
||||
ErrNoPayload = errors.New("file must have a `payload` field")
|
||||
ErrInvalidFormat = errors.New("invalid format")
|
||||
)
|
||||
|
||||
func rulesParse(buf []byte, strategy ruleStrategy, format P.RuleFormat) (ruleStrategy, error) {
|
||||
strategy.Reset()
|
||||
@@ -254,3 +273,66 @@ func rulesParse(buf []byte, strategy ruleStrategy, format P.RuleFormat) (ruleStr
|
||||
|
||||
return strategy, nil
|
||||
}
|
||||
|
||||
func rulesParseInline(rs []string, strategy ruleStrategy) ruleStrategy {
|
||||
strategy.Reset()
|
||||
for _, r := range rs {
|
||||
if r != "" {
|
||||
strategy.Insert(r)
|
||||
}
|
||||
}
|
||||
strategy.FinishInsert()
|
||||
return strategy
|
||||
}
|
||||
|
||||
type inlineProvider struct {
|
||||
ruleSetProviderBase
|
||||
name string
|
||||
updateTime time.Time
|
||||
payload []string
|
||||
}
|
||||
|
||||
func (i *inlineProvider) Name() string {
|
||||
return i.name
|
||||
}
|
||||
|
||||
func (i *inlineProvider) Initial() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *inlineProvider) Update() error {
|
||||
// make api update happy
|
||||
i.updateTime = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *inlineProvider) VehicleType() P.VehicleType {
|
||||
return P.Inline
|
||||
}
|
||||
|
||||
func (i *inlineProvider) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(
|
||||
providerForApi{
|
||||
Behavior: i.behavior.String(),
|
||||
Name: i.Name(),
|
||||
RuleCount: i.strategy.Count(),
|
||||
Type: i.Type().String(),
|
||||
VehicleType: i.VehicleType().String(),
|
||||
UpdatedAt: i.updateTime,
|
||||
Payload: i.payload,
|
||||
})
|
||||
}
|
||||
|
||||
func newInlineProvider(name string, behavior P.RuleBehavior, payload []string, parse common.ParseRuleFunc) P.RuleProvider {
|
||||
rp := &inlineProvider{
|
||||
ruleSetProviderBase: ruleSetProviderBase{
|
||||
behavior: behavior,
|
||||
strategy: newStrategy(behavior, parse),
|
||||
},
|
||||
payload: payload,
|
||||
name: name,
|
||||
updateTime: time.Now(),
|
||||
}
|
||||
rp.strategy = rulesParseInline(payload, rp.strategy)
|
||||
return rp
|
||||
}
|
||||
|
||||
@@ -166,11 +166,11 @@ end
|
||||
function get_now_use_node()
|
||||
local path = "/tmp/etc/passwall/acl/default"
|
||||
local e = {}
|
||||
local tcp_node = api.get_cache_var("GLOBAL_TCP_node")
|
||||
local tcp_node = api.get_cache_var("ACL_GLOBAL_TCP_node")
|
||||
if tcp_node then
|
||||
e["TCP"] = tcp_node
|
||||
end
|
||||
local udp_node = api.get_cache_var("GLOBAL_UDP_node")
|
||||
local udp_node = api.get_cache_var("ACL_GLOBAL_UDP_node")
|
||||
if udp_node then
|
||||
e["UDP"] = udp_node
|
||||
end
|
||||
@@ -364,8 +364,8 @@ end
|
||||
|
||||
function clear_all_nodes()
|
||||
uci:set(appname, '@global[0]', "enabled", "0")
|
||||
uci:set(appname, '@global[0]', "tcp_node", "nil")
|
||||
uci:set(appname, '@global[0]', "udp_node", "nil")
|
||||
uci:delete(appname, '@global[0]', "tcp_node")
|
||||
uci:delete(appname, '@global[0]', "udp_node")
|
||||
uci:foreach(appname, "socks", function(t)
|
||||
uci:delete(appname, t[".name"])
|
||||
uci:set_list(appname, t[".name"], "autoswitch_backup_node", {})
|
||||
@@ -374,8 +374,8 @@ function clear_all_nodes()
|
||||
uci:delete(appname, t[".name"])
|
||||
end)
|
||||
uci:foreach(appname, "acl_rule", function(t)
|
||||
uci:set(appname, t[".name"], "tcp_node", "nil")
|
||||
uci:set(appname, t[".name"], "udp_node", "nil")
|
||||
uci:delete(appname, t[".name"], "tcp_node")
|
||||
uci:delete(appname, t[".name"], "udp_node")
|
||||
end)
|
||||
uci:foreach(appname, "nodes", function(node)
|
||||
uci:delete(appname, node['.name'])
|
||||
@@ -388,11 +388,11 @@ end
|
||||
function delete_select_nodes()
|
||||
local ids = luci.http.formvalue("ids")
|
||||
string.gsub(ids, '[^' .. "," .. ']+', function(w)
|
||||
if (uci:get(appname, "@global[0]", "tcp_node") or "nil") == w then
|
||||
uci:set(appname, '@global[0]', "tcp_node", "nil")
|
||||
if (uci:get(appname, "@global[0]", "tcp_node") or "") == w then
|
||||
uci:delete(appname, '@global[0]', "tcp_node")
|
||||
end
|
||||
if (uci:get(appname, "@global[0]", "udp_node") or "nil") == w then
|
||||
uci:set(appname, '@global[0]', "udp_node", "nil")
|
||||
if (uci:get(appname, "@global[0]", "udp_node") or "") == w then
|
||||
uci:delete(appname, '@global[0]', "udp_node")
|
||||
end
|
||||
uci:foreach(appname, "socks", function(t)
|
||||
if t["node"] == w then
|
||||
@@ -413,10 +413,10 @@ function delete_select_nodes()
|
||||
end)
|
||||
uci:foreach(appname, "acl_rule", function(t)
|
||||
if t["tcp_node"] == w then
|
||||
uci:set(appname, t[".name"], "tcp_node", "nil")
|
||||
uci:delete(appname, t[".name"], "tcp_node")
|
||||
end
|
||||
if t["udp_node"] == w then
|
||||
uci:set(appname, t[".name"], "udp_node", "nil")
|
||||
uci:delete(appname, t[".name"], "udp_node")
|
||||
end
|
||||
end)
|
||||
uci:foreach(appname, "nodes", function(t)
|
||||
|
||||
+58
-38
@@ -52,7 +52,7 @@ o.rmempty = false
|
||||
---- Remarks
|
||||
o = s:option(Value, "remarks", translate("Remarks"))
|
||||
o.default = arg[1]
|
||||
o.rmempty = true
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "interface", translate("Source Interface"))
|
||||
o:value("", translate("All"))
|
||||
@@ -148,97 +148,117 @@ sources.write = dynamicList_write
|
||||
---- TCP No Redir Ports
|
||||
local TCP_NO_REDIR_PORTS = uci:get(appname, "@global_forwarding[0]", "tcp_no_redir_ports")
|
||||
o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports"))
|
||||
o.default = "default"
|
||||
o:value("", translate("Use global config") .. "(" .. TCP_NO_REDIR_PORTS .. ")")
|
||||
o:value("disable", translate("No patterns are used"))
|
||||
o:value("default", translate("Use global config") .. "(" .. TCP_NO_REDIR_PORTS .. ")")
|
||||
o:value("1:65535", translate("All"))
|
||||
o.validate = port_validate
|
||||
|
||||
---- UDP No Redir Ports
|
||||
local UDP_NO_REDIR_PORTS = uci:get(appname, "@global_forwarding[0]", "udp_no_redir_ports")
|
||||
o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"),
|
||||
"<font color='red'>" .. translate(
|
||||
"Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") ..
|
||||
"</font>")
|
||||
o.default = "default"
|
||||
"<font color='red'>" ..
|
||||
translate("Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") ..
|
||||
"</font>")
|
||||
o:value("", translate("Use global config") .. "(" .. UDP_NO_REDIR_PORTS .. ")")
|
||||
o:value("disable", translate("No patterns are used"))
|
||||
o:value("default", translate("Use global config") .. "(" .. UDP_NO_REDIR_PORTS .. ")")
|
||||
o:value("1:65535", translate("All"))
|
||||
o.validate = port_validate
|
||||
|
||||
o = s:option(DummyValue, "_hide_node_option", "")
|
||||
o.template = "passwall/cbi/hidevalue"
|
||||
o.value = "1"
|
||||
o:depends({ tcp_no_redir_ports = "1:65535", udp_no_redir_ports = "1:65535" })
|
||||
if TCP_NO_REDIR_PORTS == "1:65535" and UDP_NO_REDIR_PORTS == "1:65535" then
|
||||
o:depends({ tcp_no_redir_ports = "", udp_no_redir_ports = "" })
|
||||
end
|
||||
|
||||
o = s:option(Flag, "use_global_config", translatef("Use global config"))
|
||||
o.default = "0"
|
||||
o.rmempty = false
|
||||
o:depends({ _hide_node_option = "1", ['!reverse'] = true })
|
||||
|
||||
tcp_node = s:option(ListValue, "tcp_node", "<a style='color: red'>" .. translate("TCP Node") .. "</a>")
|
||||
tcp_node.default = ""
|
||||
tcp_node:value("", translate("Close"))
|
||||
tcp_node:depends("use_global_config", false)
|
||||
o = s:option(ListValue, "tcp_node", "<a style='color: red'>" .. translate("TCP Node") .. "</a>")
|
||||
o.default = ""
|
||||
o:depends({ _hide_node_option = false, use_global_config = false })
|
||||
|
||||
udp_node = s:option(ListValue, "udp_node", "<a style='color: red'>" .. translate("UDP Node") .. "</a>")
|
||||
udp_node.default = ""
|
||||
udp_node:value("", translate("Close"))
|
||||
udp_node:value("tcp", translate("Same as the tcp node"))
|
||||
udp_node:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
o = s:option(DummyValue, "_tcp_node_bool", "")
|
||||
o.template = "passwall/cbi/hidevalue"
|
||||
o.value = "1"
|
||||
o:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
|
||||
o = s:option(ListValue, "udp_node", "<a style='color: red'>" .. translate("UDP Node") .. "</a>")
|
||||
o.default = ""
|
||||
o:value("", translate("Close"))
|
||||
o:value("tcp", translate("Same as the tcp node"))
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
|
||||
for k, v in pairs(nodes_table) do
|
||||
tcp_node:value(v.id, v["remark"])
|
||||
udp_node:value(v.id, v["remark"])
|
||||
s.fields["tcp_node"]:value(v.id, v["remark"])
|
||||
s.fields["udp_node"]:value(v.id, v["remark"])
|
||||
end
|
||||
|
||||
o = s:option(DummyValue, "_udp_node_bool", "")
|
||||
o.template = "passwall/cbi/hidevalue"
|
||||
o.value = "1"
|
||||
o:depends({ udp_node = "", ['!reverse'] = true })
|
||||
|
||||
---- TCP Proxy Drop Ports
|
||||
local TCP_PROXY_DROP_PORTS = uci:get(appname, "@global_forwarding[0]", "tcp_proxy_drop_ports")
|
||||
o = s:option(Value, "tcp_proxy_drop_ports", translate("TCP Proxy Drop Ports"))
|
||||
o.default = "default"
|
||||
o:value("", translate("Use global config") .. "(" .. TCP_PROXY_DROP_PORTS .. ")")
|
||||
o:value("disable", translate("No patterns are used"))
|
||||
o:value("default", translate("Use global config") .. "(" .. TCP_PROXY_DROP_PORTS .. ")")
|
||||
o.validate = port_validate
|
||||
o:depends({ use_global_config = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
|
||||
---- UDP Proxy Drop Ports
|
||||
local UDP_PROXY_DROP_PORTS = uci:get(appname, "@global_forwarding[0]", "udp_proxy_drop_ports")
|
||||
o = s:option(Value, "udp_proxy_drop_ports", translate("UDP Proxy Drop Ports"))
|
||||
o.default = "default"
|
||||
o:value("", translate("Use global config") .. "(" .. UDP_PROXY_DROP_PORTS .. ")")
|
||||
o:value("disable", translate("No patterns are used"))
|
||||
o:value("default", translate("Use global config") .. "(" .. UDP_PROXY_DROP_PORTS .. ")")
|
||||
o:value("443", translate("QUIC"))
|
||||
o.validate = port_validate
|
||||
o:depends({ use_global_config = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
|
||||
---- TCP Redir Ports
|
||||
local TCP_REDIR_PORTS = uci:get(appname, "@global_forwarding[0]", "tcp_redir_ports")
|
||||
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"), translatef("Only work with using the %s node.", "TCP"))
|
||||
o.default = "default"
|
||||
o:value("default", translate("Use global config") .. "(" .. TCP_REDIR_PORTS .. ")")
|
||||
o:value("", translate("Use global config") .. "(" .. TCP_REDIR_PORTS .. ")")
|
||||
o:value("1:65535", translate("All"))
|
||||
o:value("80,443", "80,443")
|
||||
o:value("80:65535", "80 " .. translate("or more"))
|
||||
o:value("1:443", "443 " .. translate("or less"))
|
||||
o.validate = port_validate
|
||||
o:depends({ use_global_config = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
|
||||
---- UDP Redir Ports
|
||||
local UDP_REDIR_PORTS = uci:get(appname, "@global_forwarding[0]", "udp_redir_ports")
|
||||
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"), translatef("Only work with using the %s node.", "UDP"))
|
||||
o.default = "default"
|
||||
o:value("default", translate("Use global config") .. "(" .. UDP_REDIR_PORTS .. ")")
|
||||
o:value("", translate("Use global config") .. "(" .. UDP_REDIR_PORTS .. ")")
|
||||
o:value("1:65535", translate("All"))
|
||||
o:value("53", "53")
|
||||
o.validate = port_validate
|
||||
o:depends({ use_global_config = true })
|
||||
o:depends({ _udp_node_bool = "1" })
|
||||
|
||||
o = s:option(Flag, "use_direct_list", translatef("Use %s", translate("Direct List")))
|
||||
o.default = "1"
|
||||
o:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
|
||||
o = s:option(Flag, "use_proxy_list", translatef("Use %s", translate("Proxy List")))
|
||||
o.default = "1"
|
||||
o:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
|
||||
o = s:option(Flag, "use_block_list", translatef("Use %s", translate("Block List")))
|
||||
o.default = "1"
|
||||
o:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
|
||||
if has_gfwlist then
|
||||
o = s:option(Flag, "use_gfw_list", translatef("Use %s", translate("GFW List")))
|
||||
o.default = "1"
|
||||
o:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
end
|
||||
|
||||
if has_chnlist or has_chnroute then
|
||||
@@ -247,36 +267,36 @@ if has_chnlist or has_chnroute then
|
||||
o:value("direct", translate("Direct Connection"))
|
||||
o:value("proxy", translate("Proxy"))
|
||||
o.default = "direct"
|
||||
o:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
end
|
||||
|
||||
o = s:option(ListValue, "tcp_proxy_mode", "TCP " .. translate("Proxy Mode"))
|
||||
o:value("disable", translate("No Proxy"))
|
||||
o:value("proxy", translate("Proxy"))
|
||||
o:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
|
||||
o = s:option(ListValue, "udp_proxy_mode", "UDP " .. translate("Proxy Mode"))
|
||||
o:value("disable", translate("No Proxy"))
|
||||
o:value("proxy", translate("Proxy"))
|
||||
o:depends({ udp_node = "", ['!reverse'] = true })
|
||||
o:depends({ _udp_node_bool = "1" })
|
||||
|
||||
o = s:option(DummyValue, "switch_mode", " ")
|
||||
o.template = appname .. "/global/proxy"
|
||||
o:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
|
||||
---- DNS
|
||||
o = s:option(ListValue, "dns_shunt", "DNS " .. translate("Shunt"))
|
||||
o:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
o:value("dnsmasq", "Dnsmasq")
|
||||
o:value("chinadns-ng", translate("ChinaDNS-NG (recommended)"))
|
||||
|
||||
o = s:option(Flag, "filter_proxy_ipv6", translate("Filter Proxy Host IPv6"), translate("Experimental feature."))
|
||||
o.default = "0"
|
||||
o:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
|
||||
---- DNS Forward Mode
|
||||
o = s:option(ListValue, "dns_mode", translate("Filter Mode"))
|
||||
o:depends({ tcp_node = "", ['!reverse'] = true })
|
||||
o:depends({ _tcp_node_bool = "1" })
|
||||
if api.is_finded("dns2socks") then
|
||||
o:value("dns2socks", "dns2socks")
|
||||
end
|
||||
|
||||
@@ -126,19 +126,19 @@ o = s:taboption("Main", Flag, "enabled", translate("Main switch"))
|
||||
o.rmempty = false
|
||||
|
||||
---- TCP Node
|
||||
tcp_node = s:taboption("Main", ListValue, "tcp_node", "<a style='color: red'>" .. translate("TCP Node") .. "</a>")
|
||||
tcp_node:value("nil", translate("Close"))
|
||||
o = s:taboption("Main", ListValue, "tcp_node", "<a style='color: red'>" .. translate("TCP Node") .. "</a>")
|
||||
o:value("", translate("Close"))
|
||||
|
||||
---- UDP Node
|
||||
udp_node = s:taboption("Main", ListValue, "udp_node", "<a style='color: red'>" .. translate("UDP Node") .. "</a>")
|
||||
udp_node:value("nil", translate("Close"))
|
||||
udp_node:value("tcp", translate("Same as the tcp node"))
|
||||
o = s:taboption("Main", ListValue, "udp_node", "<a style='color: red'>" .. translate("UDP Node") .. "</a>")
|
||||
o:value("", translate("Close"))
|
||||
o:value("tcp", translate("Same as the tcp node"))
|
||||
|
||||
-- 分流
|
||||
if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
local function get_cfgvalue(shunt_node_id, option)
|
||||
return function(self, section)
|
||||
return m:get(shunt_node_id, option) or "nil"
|
||||
return m:get(shunt_node_id, option)
|
||||
end
|
||||
end
|
||||
local function get_write(shunt_node_id, option)
|
||||
@@ -146,6 +146,11 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
m:set(shunt_node_id, option, value)
|
||||
end
|
||||
end
|
||||
local function get_remove(shunt_node_id, option)
|
||||
return function(self, section)
|
||||
m:del(shunt_node_id, option)
|
||||
end
|
||||
end
|
||||
if #normal_list > 0 then
|
||||
for k, v in pairs(shunt_list) do
|
||||
local vid = v.id
|
||||
@@ -187,7 +192,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
if (has_singbox and has_xray) or (v.type == "sing-box" and not has_singbox) or (v.type == "Xray" and not has_xray) then
|
||||
type:depends("tcp_node", v.id)
|
||||
else
|
||||
type:depends("tcp_node", "hide") --不存在的依赖,即始终隐藏
|
||||
type:depends("tcp_node", "__hide") --不存在的依赖,即始终隐藏
|
||||
end
|
||||
|
||||
uci:foreach(appname, "shunt_rules", function(e)
|
||||
@@ -197,8 +202,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
o = s:taboption("Main", ListValue, node_option, string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", id), e.remarks))
|
||||
o.cfgvalue = get_cfgvalue(v.id, id)
|
||||
o.write = get_write(v.id, id)
|
||||
o.remove = get_remove(v.id, id)
|
||||
o:depends("tcp_node", v.id)
|
||||
o:value("nil", translate("Close"))
|
||||
o:value("", translate("Close"))
|
||||
o:value("_default", translate("Default"))
|
||||
o:value("_direct", translate("Direct Connection"))
|
||||
o:value("_blackhole", translate("Blackhole"))
|
||||
@@ -206,9 +212,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
local pt = s:taboption("Main", ListValue, vid .. "-".. id .. "_proxy_tag", string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
|
||||
pt.cfgvalue = get_cfgvalue(v.id, id .. "_proxy_tag")
|
||||
pt.write = get_write(v.id, id .. "_proxy_tag")
|
||||
pt:value("nil", translate("Close"))
|
||||
pt.remove = get_remove(v.id, id .. "_proxy_tag")
|
||||
pt:value("", translate("Close"))
|
||||
pt:value("main", translate("Preproxy Node"))
|
||||
pt.default = "nil"
|
||||
for k1, v1 in pairs(socks_list) do
|
||||
o:value(v1.id, v1.remark)
|
||||
end
|
||||
@@ -229,6 +235,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
o = s:taboption("Main", ListValue, vid .. "-" .. id, string.format('* <a style="color:red">%s</a>', translate("Default")))
|
||||
o.cfgvalue = get_cfgvalue(v.id, id)
|
||||
o.write = get_write(v.id, id)
|
||||
o.remove = get_remove(v.id, id)
|
||||
o:depends("tcp_node", v.id)
|
||||
o:value("_direct", translate("Direct Connection"))
|
||||
o:value("_blackhole", translate("Blackhole"))
|
||||
@@ -249,7 +256,8 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
o = s:taboption("Main", ListValue, vid .. "-" .. id, string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
|
||||
o.cfgvalue = get_cfgvalue(v.id, id)
|
||||
o.write = get_write(v.id, id)
|
||||
o:value("nil", translate("Close"))
|
||||
o.remove = get_remove(v.id, id)
|
||||
o:value("", translate("Close"))
|
||||
o:value("main", translate("Preproxy Node"))
|
||||
for k1, v1 in pairs(normal_list) do
|
||||
if v1.protocol ~= "_balancing" then
|
||||
@@ -263,7 +271,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
tips.cfgvalue = function(t, n)
|
||||
return string.format('<a style="color: red">%s</a>', translate("There are no available nodes, please add or subscribe nodes first."))
|
||||
end
|
||||
tips:depends({ tcp_node = "nil", ["!reverse"] = true })
|
||||
tips:depends({ tcp_node = "", ["!reverse"] = true })
|
||||
for k, v in pairs(shunt_list) do
|
||||
tips:depends("udp_node", v.id)
|
||||
end
|
||||
@@ -273,36 +281,35 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
end
|
||||
end
|
||||
|
||||
tcp_node_socks_port = s:taboption("Main", Value, "tcp_node_socks_port", translate("TCP Node") .. " Socks " .. translate("Listen Port"))
|
||||
tcp_node_socks_port.default = 1070
|
||||
tcp_node_socks_port.datatype = "port"
|
||||
tcp_node_socks_port:depends({ tcp_node = "nil", ["!reverse"] = true })
|
||||
o = s:taboption("Main", Value, "tcp_node_socks_port", translate("TCP Node") .. " Socks " .. translate("Listen Port"))
|
||||
o.default = 1070
|
||||
o.datatype = "port"
|
||||
o:depends({ tcp_node = "", ["!reverse"] = true })
|
||||
--[[
|
||||
if has_singbox or has_xray then
|
||||
tcp_node_http_port = s:taboption("Main", Value, "tcp_node_http_port", translate("TCP Node") .. " HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use"))
|
||||
tcp_node_http_port.default = 0
|
||||
tcp_node_http_port.datatype = "port"
|
||||
o = s:taboption("Main", Value, "tcp_node_http_port", translate("TCP Node") .. " HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use"))
|
||||
o.default = 0
|
||||
o.datatype = "port"
|
||||
end
|
||||
]]--
|
||||
tcp_node_socks_bind_local = s:taboption("Main", Flag, "tcp_node_socks_bind_local", translate("TCP Node") .. " Socks " .. translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
|
||||
tcp_node_socks_bind_local.default = "1"
|
||||
tcp_node_socks_bind_local:depends({ tcp_node = "nil", ["!reverse"] = true })
|
||||
o = s:taboption("Main", Flag, "tcp_node_socks_bind_local", translate("TCP Node") .. " Socks " .. translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
|
||||
o.default = "1"
|
||||
o:depends({ tcp_node = "", ["!reverse"] = true })
|
||||
|
||||
s:tab("DNS", translate("DNS"))
|
||||
|
||||
dns_shunt = s:taboption("DNS", ListValue, "dns_shunt", "DNS " .. translate("Shunt"))
|
||||
dns_shunt:value("dnsmasq", "Dnsmasq")
|
||||
dns_shunt:value("chinadns-ng", translate("ChinaDNS-NG (recommended)"))
|
||||
o = s:taboption("DNS", ListValue, "dns_shunt", "DNS " .. translate("Shunt"))
|
||||
o:value("dnsmasq", "Dnsmasq")
|
||||
o:value("chinadns-ng", translate("ChinaDNS-NG (recommended)"))
|
||||
if api.is_finded("smartdns") then
|
||||
dns_shunt:value("smartdns", "SmartDNS")
|
||||
group_domestic = s:taboption("DNS", Value, "group_domestic", translate("Domestic group name"))
|
||||
group_domestic.placeholder = "local"
|
||||
group_domestic:depends("dns_shunt", "smartdns")
|
||||
group_domestic.description = translate("You only need to configure domestic DNS packets in SmartDNS and set it redirect or as Dnsmasq upstream, and fill in the domestic DNS group name here.")
|
||||
o:value("smartdns", "SmartDNS")
|
||||
o = s:taboption("DNS", Value, "group_domestic", translate("Domestic group name"))
|
||||
o.placeholder = "local"
|
||||
o:depends("dns_shunt", "smartdns")
|
||||
o.description = translate("You only need to configure domestic DNS packets in SmartDNS and set it redirect or as Dnsmasq upstream, and fill in the domestic DNS group name here.")
|
||||
end
|
||||
|
||||
o = s:taboption("DNS", ListValue, "direct_dns_mode", translate("Direct DNS") .. " " .. translate("Request protocol"))
|
||||
o.default = ""
|
||||
o:value("", translate("Auto"))
|
||||
o:value("udp", translatef("Requery DNS By %s", "UDP"))
|
||||
o:value("tcp", translatef("Requery DNS By %s", "TCP"))
|
||||
@@ -399,23 +406,23 @@ if api.is_finded("smartdns") then
|
||||
end
|
||||
|
||||
---- DNS Forward Mode
|
||||
dns_mode = s:taboption("DNS", ListValue, "dns_mode", translate("Filter Mode"))
|
||||
dns_mode:value("udp", translatef("Requery DNS By %s", "UDP"))
|
||||
dns_mode:value("tcp", translatef("Requery DNS By %s", "TCP"))
|
||||
o = s:taboption("DNS", ListValue, "dns_mode", translate("Filter Mode"))
|
||||
o:value("udp", translatef("Requery DNS By %s", "UDP"))
|
||||
o:value("tcp", translatef("Requery DNS By %s", "TCP"))
|
||||
if chinadns_tls == 0 then
|
||||
dns_mode:value("dot", translatef("Requery DNS By %s", "DoT"))
|
||||
o:value("dot", translatef("Requery DNS By %s", "DoT"))
|
||||
end
|
||||
if api.is_finded("dns2socks") then
|
||||
dns_mode:value("dns2socks", "dns2socks")
|
||||
o:value("dns2socks", "dns2socks")
|
||||
end
|
||||
if has_singbox then
|
||||
dns_mode:value("sing-box", "Sing-Box")
|
||||
o:value("sing-box", "Sing-Box")
|
||||
end
|
||||
if has_xray then
|
||||
dns_mode:value("xray", "Xray")
|
||||
o:value("xray", "Xray")
|
||||
end
|
||||
if api.is_finded("smartdns") then
|
||||
dns_mode:depends({ dns_shunt = "smartdns", ['!reverse'] = true })
|
||||
o:depends({ dns_shunt = "smartdns", ['!reverse'] = true })
|
||||
end
|
||||
|
||||
o = s:taboption("DNS", ListValue, "xray_dns_mode", translate("Request protocol"))
|
||||
@@ -426,7 +433,7 @@ o.cfgvalue = function(self, section)
|
||||
return m:get(section, "v2ray_dns_mode")
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
if dns_mode:formvalue(section) == "xray" then
|
||||
if s.fields["dns_mode"]:formvalue(section) == "xray" then
|
||||
return m:set(section, "v2ray_dns_mode", value)
|
||||
end
|
||||
end
|
||||
@@ -439,7 +446,7 @@ o.cfgvalue = function(self, section)
|
||||
return m:get(section, "v2ray_dns_mode")
|
||||
end
|
||||
o.write = function(self, section, value)
|
||||
if dns_mode:formvalue(section) == "sing-box" then
|
||||
if s.fields["dns_mode"]:formvalue(section) == "sing-box" then
|
||||
return m:set(section, "v2ray_dns_mode", value)
|
||||
end
|
||||
end
|
||||
@@ -518,9 +525,9 @@ o.default = "0"
|
||||
o:depends({dns_mode = "sing-box", dns_shunt = "dnsmasq"})
|
||||
o.validate = function(self, value, t)
|
||||
if value and value == "1" then
|
||||
local _dns_mode = dns_mode:formvalue(t)
|
||||
local _tcp_node = tcp_node:formvalue(t)
|
||||
if _dns_mode and _tcp_node and _tcp_node ~= "nil" then
|
||||
local _dns_mode = s.fields["dns_mode"]:formvalue(t)
|
||||
local _tcp_node = s.fields["tcp_node"]:formvalue(t)
|
||||
if _dns_mode and _tcp_node then
|
||||
if m:get(_tcp_node, "type"):lower() ~= _dns_mode then
|
||||
return nil, translatef("TCP node must be '%s' type to use FakeDNS.", _dns_mode)
|
||||
end
|
||||
@@ -597,16 +604,16 @@ if has_chnlist or has_chnroute then
|
||||
end
|
||||
|
||||
---- TCP Default Proxy Mode
|
||||
tcp_proxy_mode = s:taboption("Proxy", ListValue, "tcp_proxy_mode", "TCP " .. translate("Default Proxy Mode"))
|
||||
tcp_proxy_mode:value("disable", translate("No Proxy"))
|
||||
tcp_proxy_mode:value("proxy", translate("Proxy"))
|
||||
tcp_proxy_mode.default = "proxy"
|
||||
o = s:taboption("Proxy", ListValue, "tcp_proxy_mode", "TCP " .. translate("Default Proxy Mode"))
|
||||
o:value("disable", translate("No Proxy"))
|
||||
o:value("proxy", translate("Proxy"))
|
||||
o.default = "proxy"
|
||||
|
||||
---- UDP Default Proxy Mode
|
||||
udp_proxy_mode = s:taboption("Proxy", ListValue, "udp_proxy_mode", "UDP " .. translate("Default Proxy Mode"))
|
||||
udp_proxy_mode:value("disable", translate("No Proxy"))
|
||||
udp_proxy_mode:value("proxy", translate("Proxy"))
|
||||
udp_proxy_mode.default = "proxy"
|
||||
o = s:taboption("Proxy", ListValue, "udp_proxy_mode", "UDP " .. translate("Default Proxy Mode"))
|
||||
o:value("disable", translate("No Proxy"))
|
||||
o:value("proxy", translate("Proxy"))
|
||||
o.default = "proxy"
|
||||
|
||||
o = s:taboption("Proxy", DummyValue, "switch_mode", " ")
|
||||
o.template = appname .. "/global/proxy"
|
||||
@@ -634,20 +641,20 @@ o = s:taboption("log", Flag, "log_udp", translate("Enable") .. " " .. translatef
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
loglevel = s:taboption("log", ListValue, "loglevel", "Sing-Box/Xray " .. translate("Log Level"))
|
||||
loglevel.default = "warning"
|
||||
loglevel:value("debug")
|
||||
loglevel:value("info")
|
||||
loglevel:value("warning")
|
||||
loglevel:value("error")
|
||||
o = s:taboption("log", ListValue, "loglevel", "Sing-Box/Xray " .. translate("Log Level"))
|
||||
o.default = "warning"
|
||||
o:value("debug")
|
||||
o:value("info")
|
||||
o:value("warning")
|
||||
o:value("error")
|
||||
|
||||
trojan_loglevel = s:taboption("log", ListValue, "trojan_loglevel", "Trojan " .. translate("Log Level"))
|
||||
trojan_loglevel.default = "2"
|
||||
trojan_loglevel:value("0", "all")
|
||||
trojan_loglevel:value("1", "info")
|
||||
trojan_loglevel:value("2", "warn")
|
||||
trojan_loglevel:value("3", "error")
|
||||
trojan_loglevel:value("4", "fatal")
|
||||
o = s:taboption("log", ListValue, "trojan_loglevel", "Trojan " .. translate("Log Level"))
|
||||
o.default = "2"
|
||||
o:value("0", "all")
|
||||
o:value("1", "info")
|
||||
o:value("2", "warn")
|
||||
o:value("3", "error")
|
||||
o:value("4", "fatal")
|
||||
|
||||
o = s:taboption("log", Flag, "advanced_log_feature", translate("Advanced log feature"), translate("For professionals only."))
|
||||
o.default = "0"
|
||||
@@ -670,30 +677,30 @@ o.template = appname .. "/global/faq"
|
||||
o = s:taboption("Main", Flag, "socks_enabled", "Socks " .. translate("Main switch"))
|
||||
o.rmempty = false
|
||||
|
||||
s = m:section(TypedSection, "socks", translate("Socks Config"))
|
||||
s.template = "cbi/tblsection"
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
s.extedit = api.url("socks_config", "%s")
|
||||
function s.create(e, t)
|
||||
s2 = m:section(TypedSection, "socks", translate("Socks Config"))
|
||||
s2.template = "cbi/tblsection"
|
||||
s2.anonymous = true
|
||||
s2.addremove = true
|
||||
s2.extedit = api.url("socks_config", "%s")
|
||||
function s2.create(e, t)
|
||||
local uuid = api.gen_short_uuid()
|
||||
t = uuid
|
||||
TypedSection.create(e, t)
|
||||
luci.http.redirect(e.extedit:format(t))
|
||||
end
|
||||
|
||||
o = s:option(DummyValue, "status", translate("Status"))
|
||||
o = s2:option(DummyValue, "status", translate("Status"))
|
||||
o.rawhtml = true
|
||||
o.cfgvalue = function(t, n)
|
||||
return string.format('<div class="_status" socks_id="%s"></div>', n)
|
||||
end
|
||||
|
||||
---- Enable
|
||||
o = s:option(Flag, "enabled", translate("Enable"))
|
||||
o = s2:option(Flag, "enabled", translate("Enable"))
|
||||
o.default = 1
|
||||
o.rmempty = false
|
||||
|
||||
socks_node = s:option(ListValue, "node", translate("Socks Node"))
|
||||
o = s2:option(ListValue, "node", translate("Socks Node"))
|
||||
|
||||
local n = 1
|
||||
uci:foreach(appname, "socks", function(s)
|
||||
@@ -703,26 +710,26 @@ uci:foreach(appname, "socks", function(s)
|
||||
n = n + 1
|
||||
end)
|
||||
|
||||
o = s:option(Value, "port", "Socks " .. translate("Listen Port"))
|
||||
o = s2:option(Value, "port", "Socks " .. translate("Listen Port"))
|
||||
o.default = n + 1080
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
|
||||
if has_singbox or has_xray then
|
||||
o = s:option(Value, "http_port", "HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use"))
|
||||
o = s2:option(Value, "http_port", "HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use"))
|
||||
o.default = 0
|
||||
o.datatype = "port"
|
||||
end
|
||||
|
||||
for k, v in pairs(nodes_table) do
|
||||
tcp_node:value(v.id, v["remark"])
|
||||
udp_node:value(v.id, v["remark"])
|
||||
s.fields["tcp_node"]:value(v.id, v["remark"])
|
||||
s.fields["udp_node"]:value(v.id, v["remark"])
|
||||
if v.type == "Socks" then
|
||||
if has_singbox or has_xray then
|
||||
socks_node:value(v.id, v["remark"])
|
||||
s2.fields["node"]:value(v.id, v["remark"])
|
||||
end
|
||||
else
|
||||
socks_node:value(v.id, v["remark"])
|
||||
s2.fields["node"]:value(v.id, v["remark"])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -61,15 +61,15 @@ function s.remove(e, t)
|
||||
end
|
||||
end)
|
||||
TypedSection.remove(e, t)
|
||||
local new_node = "nil"
|
||||
local new_node = ""
|
||||
local node0 = m:get("@nodes[0]") or nil
|
||||
if node0 then
|
||||
new_node = node0[".name"]
|
||||
end
|
||||
if (m:get("@global[0]", "tcp_node") or "nil") == t then
|
||||
if (m:get("@global[0]", "tcp_node") or "") == t then
|
||||
m:set('@global[0]', "tcp_node", new_node)
|
||||
end
|
||||
if (m:get("@global[0]", "udp_node") or "nil") == t then
|
||||
if (m:get("@global[0]", "udp_node") or "") == t then
|
||||
m:set('@global[0]', "udp_node", new_node)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,44 +17,44 @@ s = m:section(TypedSection, "global_delay", translate("Delay Settings"))
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
---- Delay Start
|
||||
o = s:option(Value, "start_delay", translate("Delay Start"),
|
||||
translate("Units:seconds"))
|
||||
o.default = "1"
|
||||
o.rmempty = true
|
||||
|
||||
---- Open and close Daemon
|
||||
o = s:option(Flag, "start_daemon", translate("Open and close Daemon"))
|
||||
o.default = 1
|
||||
o.rmempty = false
|
||||
|
||||
--[[
|
||||
---- Open and close automatically
|
||||
o = s:option(Flag, "auto_on", translate("Open and close automatically"))
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
---- Delay Start
|
||||
o = s:option(Value, "start_delay", translate("Delay Start"), translate("Units:seconds"))
|
||||
o.default = "1"
|
||||
o.rmempty = true
|
||||
|
||||
---- Automatically turn off time
|
||||
o = s:option(ListValue, "time_off", translate("Automatically turn off time"))
|
||||
o.default = nil
|
||||
o:depends("auto_on", true)
|
||||
o:value(nil, translate("Disable"))
|
||||
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
|
||||
|
||||
---- Automatically turn on time
|
||||
o = s:option(ListValue, "time_on", translate("Automatically turn on time"))
|
||||
o.default = nil
|
||||
o:depends("auto_on", true)
|
||||
o:value(nil, translate("Disable"))
|
||||
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
|
||||
|
||||
---- Automatically restart time
|
||||
o = s:option(ListValue, "time_restart", translate("Automatically restart time"))
|
||||
o.default = nil
|
||||
o:depends("auto_on", true)
|
||||
o:value(nil, translate("Disable"))
|
||||
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
|
||||
--]]
|
||||
for index, value in ipairs({"stop", "start", "restart"}) do
|
||||
o = s:option(ListValue, value .. "_week_mode", translate(value .. " automatically mode"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value(8, translate("Loop Mode"))
|
||||
o:value(7, translate("Every day"))
|
||||
o:value(1, translate("Every Monday"))
|
||||
o:value(2, translate("Every Tuesday"))
|
||||
o:value(3, translate("Every Wednesday"))
|
||||
o:value(4, translate("Every Thursday"))
|
||||
o:value(5, translate("Every Friday"))
|
||||
o:value(6, translate("Every Saturday"))
|
||||
o:value(0, translate("Every Sunday"))
|
||||
o = s:option(ListValue, value .. "_time_mode", translate(value .. " Time(Every day)"))
|
||||
for t = 0, 23 do o:value(t, t .. ":00") end
|
||||
o.default = 0
|
||||
o:depends(value .. "_week_mode", "0")
|
||||
o:depends(value .. "_week_mode", "1")
|
||||
o:depends(value .. "_week_mode", "2")
|
||||
o:depends(value .. "_week_mode", "3")
|
||||
o:depends(value .. "_week_mode", "4")
|
||||
o:depends(value .. "_week_mode", "5")
|
||||
o:depends(value .. "_week_mode", "6")
|
||||
o:depends(value .. "_week_mode", "7")
|
||||
o = s:option(ListValue, value .. "_interval_mode", translate(value .. " Interval(Hour)"))
|
||||
for t = 1, 24 do o:value(t, t .. " " .. translate("Hour")) end
|
||||
o.default = 2
|
||||
o:depends(value .. "_week_mode", "8")
|
||||
end
|
||||
|
||||
-- [[ Forwarding Settings ]]--
|
||||
s = m:section(TypedSection, "global_forwarding",
|
||||
|
||||
+19
-19
@@ -10,7 +10,7 @@ local type_name = "Hysteria2"
|
||||
|
||||
local option_prefix = "hysteria2_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -18,59 +18,59 @@ end
|
||||
|
||||
s.fields["type"]:value(type_name, "Hysteria2")
|
||||
|
||||
o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
|
||||
o = s:option(ListValue, _n("protocol"), translate("Protocol"))
|
||||
o:value("udp", "UDP")
|
||||
|
||||
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)"))
|
||||
o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Port"))
|
||||
o = s:option(Value, _n("port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, option_name("hop"), translate("Additional ports for hysteria hop"))
|
||||
o = s:option(Value, _n("hop"), translate("Additional ports for hysteria hop"))
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("obfs"), translate("Obfs Password"))
|
||||
o = s:option(Value, _n("obfs"), translate("Obfs Password"))
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("auth_password"), translate("Auth Password"))
|
||||
o = s:option(Value, _n("auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Flag, option_name("fast_open"), translate("Fast Open"))
|
||||
o = s:option(Flag, _n("fast_open"), translate("Fast Open"))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Value, option_name("tls_serverName"), translate("Domain"))
|
||||
o = s:option(Value, _n("tls_serverName"), translate("Domain"))
|
||||
|
||||
o = s:option(Flag, option_name("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
|
||||
o = s:option(Flag, _n("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Value, option_name("tls_pinSHA256"), translate("PinSHA256"),translate("Certificate fingerprint"))
|
||||
o = s:option(Value, _n("tls_pinSHA256"), translate("PinSHA256"),translate("Certificate fingerprint"))
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("up_mbps"), translate("Max upload Mbps"))
|
||||
o = s:option(Value, _n("up_mbps"), translate("Max upload Mbps"))
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("down_mbps"), translate("Max download Mbps"))
|
||||
o = s:option(Value, _n("down_mbps"), translate("Max download Mbps"))
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)")
|
||||
o = s:option(Value, _n("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)")
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("recv_window"), translate("QUIC stream receive window"))
|
||||
o = s:option(Value, _n("recv_window"), translate("QUIC stream receive window"))
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("recv_window_conn"), translate("QUIC connection receive window"))
|
||||
o = s:option(Value, _n("recv_window_conn"), translate("QUIC connection receive window"))
|
||||
o.rewrite_option = o.option
|
||||
|
||||
|
||||
o = s:option(Value, option_name("idle_timeout"), translate("Idle Timeout"), translate("Example:") .. "30s (4s-120s)")
|
||||
o = s:option(Value, _n("idle_timeout"), translate("Idle Timeout"), translate("Example:") .. "30s (4s-120s)")
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Flag, option_name("disable_mtu_discovery"), translate("Disable MTU detection"))
|
||||
o = s:option(Flag, _n("disable_mtu_discovery"), translate("Disable MTU detection"))
|
||||
o.default = "0"
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Flag, option_name("lazy_start"), translate("Lazy Start"))
|
||||
o = s:option(Flag, _n("lazy_start"), translate("Lazy Start"))
|
||||
o.default = "0"
|
||||
o.rewrite_option = o.option
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ local type_name = "Naiveproxy"
|
||||
|
||||
local option_prefix = "naive_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -18,18 +18,18 @@ end
|
||||
|
||||
s.fields["type"]:value(type_name, translate("NaiveProxy"))
|
||||
|
||||
o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
|
||||
o = s:option(ListValue, _n("protocol"), translate("Protocol"))
|
||||
o:value("https", translate("HTTPS"))
|
||||
o:value("quic", translate("QUIC"))
|
||||
|
||||
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)"))
|
||||
o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Port"))
|
||||
o = s:option(Value, _n("port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, option_name("username"), translate("Username"))
|
||||
o = s:option(Value, _n("username"), translate("Username"))
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
|
||||
api.luci_types(arg[1], m, s, type_name, option_prefix)
|
||||
|
||||
+226
-229
@@ -14,7 +14,7 @@ local type_name = "Xray"
|
||||
|
||||
local option_prefix = "xray_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -33,7 +33,7 @@ local xray_version = api.get_app_version("xray")
|
||||
|
||||
s.fields["type"]:value(type_name, "Xray")
|
||||
|
||||
o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
|
||||
o = s:option(ListValue, _n("protocol"), translate("Protocol"))
|
||||
o:value("vmess", translate("Vmess"))
|
||||
o:value("vless", translate("VLESS"))
|
||||
o:value("http", translate("HTTP"))
|
||||
@@ -45,9 +45,9 @@ o:value("_balancing", translate("Balancing"))
|
||||
o:value("_shunt", translate("Shunt"))
|
||||
o:value("_iface", translate("Custom Interface"))
|
||||
|
||||
o = s:option(Value, option_name("iface"), translate("Interface"))
|
||||
o = s:option(Value, _n("iface"), translate("Interface"))
|
||||
o.default = "eth1"
|
||||
o:depends({ [option_name("protocol")] = "_iface" })
|
||||
o:depends({ [_n("protocol")] = "_iface" })
|
||||
|
||||
local nodes_table = {}
|
||||
local balancers_table = {}
|
||||
@@ -96,12 +96,12 @@ uci:foreach(appname, "socks", function(s)
|
||||
end)
|
||||
|
||||
-- 负载均衡列表
|
||||
local o = s:option(DynamicList, option_name("balancing_node"), translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>"))
|
||||
o:depends({ [option_name("protocol")] = "_balancing" })
|
||||
local o = s:option(DynamicList, _n("balancing_node"), translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>"))
|
||||
o:depends({ [_n("protocol")] = "_balancing" })
|
||||
for k, v in pairs(nodes_table) do o:value(v.id, v.remark) end
|
||||
|
||||
local o = s:option(ListValue, option_name("balancingStrategy"), translate("Balancing Strategy"))
|
||||
o:depends({ [option_name("protocol")] = "_balancing" })
|
||||
local o = s:option(ListValue, _n("balancingStrategy"), translate("Balancing Strategy"))
|
||||
o:depends({ [_n("protocol")] = "_balancing" })
|
||||
o:value("random")
|
||||
o:value("roundRobin")
|
||||
o:value("leastPing")
|
||||
@@ -109,11 +109,11 @@ o.default = "leastPing"
|
||||
|
||||
-- Fallback Node
|
||||
if api.compare_versions(xray_version, ">=", "1.8.10") then
|
||||
local o = s:option(ListValue, option_name("fallback_node"), translate("Fallback Node"))
|
||||
local o = s:option(ListValue, _n("fallback_node"), translate("Fallback Node"))
|
||||
if api.compare_versions(xray_version, ">=", "1.8.12") then
|
||||
o:depends({ [option_name("protocol")] = "_balancing" })
|
||||
o:depends({ [_n("protocol")] = "_balancing" })
|
||||
else
|
||||
o:depends({ [option_name("balancingStrategy")] = "leastPing" })
|
||||
o:depends({ [_n("balancingStrategy")] = "leastPing" })
|
||||
end
|
||||
local function check_fallback_chain(fb)
|
||||
for k, v in pairs(fallback_table) do
|
||||
@@ -132,11 +132,11 @@ if api.compare_versions(xray_version, ">=", "1.8.10") then
|
||||
end
|
||||
|
||||
-- 探测地址
|
||||
local ucpu = s:option(Flag, option_name("useCustomProbeUrl"), translate("Use Custome Probe URL"), translate("By default the built-in probe URL will be used, enable this option to use a custom probe URL."))
|
||||
ucpu:depends({ [option_name("balancingStrategy")] = "leastPing" })
|
||||
local ucpu = s:option(Flag, _n("useCustomProbeUrl"), translate("Use Custome Probe URL"), translate("By default the built-in probe URL will be used, enable this option to use a custom probe URL."))
|
||||
ucpu:depends({ [_n("balancingStrategy")] = "leastPing" })
|
||||
|
||||
local pu = s:option(Value, option_name("probeUrl"), translate("Probe URL"))
|
||||
pu:depends({ [option_name("useCustomProbeUrl")] = true })
|
||||
local pu = s:option(Value, _n("probeUrl"), translate("Probe URL"))
|
||||
pu:depends({ [_n("useCustomProbeUrl")] = true })
|
||||
pu:value("https://cp.cloudflare.com/", "Cloudflare")
|
||||
pu:value("https://www.gstatic.com/generate_204", "Gstatic")
|
||||
pu:value("https://www.google.com/generate_204", "Google")
|
||||
@@ -147,27 +147,27 @@ pu.default = "https://www.google.com/generate_204"
|
||||
pu.description = translate("The URL used to detect the connection status.")
|
||||
|
||||
-- 探测间隔
|
||||
local pi = s:option(Value, option_name("probeInterval"), translate("Probe Interval"))
|
||||
pi:depends({ [option_name("balancingStrategy")] = "leastPing" })
|
||||
local pi = s:option(Value, _n("probeInterval"), translate("Probe Interval"))
|
||||
pi:depends({ [_n("balancingStrategy")] = "leastPing" })
|
||||
pi.default = "1m"
|
||||
pi.description = translate("The interval between initiating probes. Every time this time elapses, a server status check is performed on a server. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively.")
|
||||
|
||||
if api.compare_versions(xray_version, ">=", "1.8.12") then
|
||||
ucpu:depends({ [option_name("protocol")] = "_balancing" })
|
||||
pi:depends({ [option_name("protocol")] = "_balancing" })
|
||||
ucpu:depends({ [_n("protocol")] = "_balancing" })
|
||||
pi:depends({ [_n("protocol")] = "_balancing" })
|
||||
else
|
||||
ucpu:depends({ [option_name("balancingStrategy")] = "leastPing" })
|
||||
pi:depends({ [option_name("balancingStrategy")] = "leastPing" })
|
||||
ucpu:depends({ [_n("balancingStrategy")] = "leastPing" })
|
||||
pi:depends({ [_n("balancingStrategy")] = "leastPing" })
|
||||
end
|
||||
|
||||
|
||||
-- [[ 分流模块 ]]
|
||||
if #nodes_table > 0 then
|
||||
o = s:option(Flag, option_name("preproxy_enabled"), translate("Preproxy"))
|
||||
o:depends({ [option_name("protocol")] = "_shunt" })
|
||||
o = s:option(Flag, _n("preproxy_enabled"), translate("Preproxy"))
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
|
||||
o = s:option(ListValue, option_name("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not."))
|
||||
o:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true })
|
||||
o = s:option(ListValue, _n("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not."))
|
||||
o:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true })
|
||||
for k, v in pairs(socks_list) do
|
||||
o:value(v.id, v.remark)
|
||||
end
|
||||
@@ -180,16 +180,15 @@ if #nodes_table > 0 then
|
||||
for k, v in pairs(nodes_table) do
|
||||
o:value(v.id, v.remark)
|
||||
end
|
||||
o.default = "nil"
|
||||
end
|
||||
uci:foreach(appname, "shunt_rules", function(e)
|
||||
if e[".name"] and e.remarks then
|
||||
o = s:option(ListValue, option_name(e[".name"]), string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks))
|
||||
o:value("nil", translate("Close"))
|
||||
o = s:option(ListValue, _n(e[".name"]), string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks))
|
||||
o:value("", translate("Close"))
|
||||
o:value("_default", translate("Default"))
|
||||
o:value("_direct", translate("Direct Connection"))
|
||||
o:value("_blackhole", translate("Blackhole"))
|
||||
o:depends({ [option_name("protocol")] = "_shunt" })
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
|
||||
if #nodes_table > 0 then
|
||||
for k, v in pairs(socks_list) do
|
||||
@@ -201,28 +200,27 @@ uci:foreach(appname, "shunt_rules", function(e)
|
||||
for k, v in pairs(iface_table) do
|
||||
o:value(v.id, v.remark)
|
||||
end
|
||||
local pt = s:option(ListValue, option_name(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
|
||||
pt:value("nil", translate("Close"))
|
||||
local pt = s:option(ListValue, _n(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
|
||||
pt:value("", translate("Close"))
|
||||
pt:value("main", translate("Preproxy Node"))
|
||||
pt.default = "nil"
|
||||
for k, v in pairs(nodes_table) do
|
||||
o:value(v.id, v.remark)
|
||||
pt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name(e[".name"])] = v.id })
|
||||
pt:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true, [_n(e[".name"])] = v.id })
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
o = s:option(DummyValue, option_name("shunt_tips"), " ")
|
||||
o = s:option(DummyValue, _n("shunt_tips"), " ")
|
||||
o.not_rewrite = true
|
||||
o.rawhtml = true
|
||||
o.cfgvalue = function(t, n)
|
||||
return string.format('<a style="color: red" href="../rule">%s</a>', translate("No shunt rules? Click me to go to add."))
|
||||
end
|
||||
o:depends({ [option_name("protocol")] = "_shunt" })
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
|
||||
local o = s:option(ListValue, option_name("default_node"), string.format('* <a style="color:red">%s</a>', translate("Default")))
|
||||
o:depends({ [option_name("protocol")] = "_shunt" })
|
||||
local o = s:option(ListValue, _n("default_node"), string.format('* <a style="color:red">%s</a>', translate("Default")))
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
o:value("_direct", translate("Direct Connection"))
|
||||
o:value("_blackhole", translate("Blackhole"))
|
||||
|
||||
@@ -236,17 +234,16 @@ if #nodes_table > 0 then
|
||||
for k, v in pairs(iface_table) do
|
||||
o:value(v.id, v.remark)
|
||||
end
|
||||
local dpt = s:option(ListValue, option_name("default_proxy_tag"), string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
|
||||
dpt:value("nil", translate("Close"))
|
||||
local dpt = s:option(ListValue, _n("default_proxy_tag"), string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
|
||||
dpt:value("", translate("Close"))
|
||||
dpt:value("main", translate("Preproxy Node"))
|
||||
dpt.default = "nil"
|
||||
for k, v in pairs(nodes_table) do
|
||||
o:value(v.id, v.remark)
|
||||
dpt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name("default_node")] = v.id })
|
||||
dpt:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true, [_n("default_node")] = v.id })
|
||||
end
|
||||
end
|
||||
|
||||
o = s:option(ListValue, option_name("domainStrategy"), translate("Domain Strategy"))
|
||||
o = s:option(ListValue, _n("domainStrategy"), translate("Domain Strategy"))
|
||||
o:value("AsIs")
|
||||
o:value("IPIfNonMatch")
|
||||
o:value("IPOnDemand")
|
||||
@@ -255,92 +252,92 @@ o.description = "<br /><ul><li>" .. translate("'AsIs': Only use domain for routi
|
||||
.. "</li><li>" .. translate("'IPIfNonMatch': When no rule matches current domain, resolves it into IP addresses (A or AAAA records) and try all rules again.")
|
||||
.. "</li><li>" .. translate("'IPOnDemand': As long as there is a IP-based rule, resolves the domain into IP immediately.")
|
||||
.. "</li></ul>"
|
||||
o:depends({ [option_name("protocol")] = "_shunt" })
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
|
||||
o = s:option(ListValue, option_name("domainMatcher"), translate("Domain matcher"))
|
||||
o = s:option(ListValue, _n("domainMatcher"), translate("Domain matcher"))
|
||||
o:value("hybrid")
|
||||
o:value("linear")
|
||||
o:depends({ [option_name("protocol")] = "_shunt" })
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
|
||||
-- [[ 分流模块 End ]]
|
||||
|
||||
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)"))
|
||||
o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Port"))
|
||||
o = s:option(Value, _n("port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
local protocols = s.fields[option_name("protocol")].keylist
|
||||
local protocols = s.fields[_n("protocol")].keylist
|
||||
if #protocols > 0 then
|
||||
for index, value in ipairs(protocols) do
|
||||
if not value:find("_") then
|
||||
s.fields[option_name("address")]:depends({ [option_name("protocol")] = value })
|
||||
s.fields[option_name("port")]:depends({ [option_name("protocol")] = value })
|
||||
s.fields[_n("address")]:depends({ [_n("protocol")] = value })
|
||||
s.fields[_n("port")]:depends({ [_n("protocol")] = value })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
o = s:option(Value, option_name("username"), translate("Username"))
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o = s:option(Value, _n("username"), translate("Username"))
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
o = s:option(ListValue, option_name("security"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("security"), translate("Encrypt Method"))
|
||||
for a, t in ipairs(security_list) do o:value(t) end
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
|
||||
o = s:option(Value, option_name("encryption"), translate("Encrypt Method"))
|
||||
o = s:option(Value, _n("encryption"), translate("Encrypt Method"))
|
||||
o.default = "none"
|
||||
o:value("none")
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
|
||||
o = s:option(ListValue, option_name("ss_method"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("ss_method"), translate("Encrypt Method"))
|
||||
o.rewrite_option = "method"
|
||||
for a, t in ipairs(ss_method_list) do o:value(t) end
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(Flag, option_name("iv_check"), translate("IV Check"))
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "aes-128-gcm" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "aes-256-gcm" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "chacha20-poly1305" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "xchacha20-poly1305" })
|
||||
o = s:option(Flag, _n("iv_check"), translate("IV Check"))
|
||||
o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "aes-128-gcm" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "aes-256-gcm" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "chacha20-poly1305" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "xchacha20-poly1305" })
|
||||
|
||||
o = s:option(Flag, option_name("uot"), translate("UDP over TCP"))
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o = s:option(Flag, _n("uot"), translate("UDP over TCP"))
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(Value, option_name("uuid"), translate("ID"))
|
||||
o = s:option(Value, _n("uuid"), translate("ID"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
|
||||
o = s:option(ListValue, option_name("flow"), translate("flow"))
|
||||
o = s:option(ListValue, _n("flow"), translate("flow"))
|
||||
o.default = ""
|
||||
o:value("", translate("Disable"))
|
||||
o:value("xtls-rprx-vision")
|
||||
o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true, [option_name("transport")] = "raw" })
|
||||
o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true, [_n("transport")] = "raw" })
|
||||
|
||||
o = s:option(Flag, option_name("tls"), translate("TLS"))
|
||||
o = s:option(Flag, _n("tls"), translate("TLS"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(Flag, option_name("reality"), translate("REALITY"), translate("Only recommend to use with VLESS-TCP-XTLS-Vision."))
|
||||
o = s:option(Flag, _n("reality"), translate("REALITY"), translate("Only recommend to use with VLESS-TCP-XTLS-Vision."))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "raw" })
|
||||
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "h2" })
|
||||
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "grpc" })
|
||||
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "xhttp" })
|
||||
o:depends({ [_n("tls")] = true, [_n("transport")] = "raw" })
|
||||
o:depends({ [_n("tls")] = true, [_n("transport")] = "h2" })
|
||||
o:depends({ [_n("tls")] = true, [_n("transport")] = "grpc" })
|
||||
o:depends({ [_n("tls")] = true, [_n("transport")] = "xhttp" })
|
||||
|
||||
o = s:option(ListValue, option_name("alpn"), translate("alpn"))
|
||||
o = s:option(ListValue, _n("alpn"), translate("alpn"))
|
||||
o.default = "default"
|
||||
o:value("default", translate("Default"))
|
||||
o:value("h3")
|
||||
@@ -349,36 +346,36 @@ o:value("h3,h2")
|
||||
o:value("http/1.1")
|
||||
o:value("h2,http/1.1")
|
||||
o:value("h3,h2,http/1.1")
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
|
||||
|
||||
-- o = s:option(Value, option_name("minversion"), translate("minversion"))
|
||||
-- o = s:option(Value, _n("minversion"), translate("minversion"))
|
||||
-- o.default = "1.3"
|
||||
-- o:value("1.3")
|
||||
-- o:depends({ [option_name("tls")] = true })
|
||||
-- o:depends({ [_n("tls")] = true })
|
||||
|
||||
o = s:option(Value, option_name("tls_serverName"), translate("Domain"))
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o = s:option(Value, _n("tls_serverName"), translate("Domain"))
|
||||
o:depends({ [_n("tls")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
|
||||
o = s:option(Flag, _n("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
|
||||
|
||||
-- [[ REALITY部分 ]] --
|
||||
o = s:option(Value, option_name("reality_publicKey"), translate("Public Key"))
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
|
||||
o = s:option(Value, _n("reality_publicKey"), translate("Public Key"))
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = true })
|
||||
|
||||
o = s:option(Value, option_name("reality_shortId"), translate("Short Id"))
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
|
||||
o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = true })
|
||||
|
||||
o = s:option(Value, option_name("reality_spiderX"), translate("Spider X"))
|
||||
o = s:option(Value, _n("reality_spiderX"), translate("Spider X"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("utls"), translate("uTLS"))
|
||||
o = s:option(Flag, _n("utls"), translate("uTLS"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
|
||||
|
||||
o = s:option(ListValue, option_name("fingerprint"), translate("Finger Print"))
|
||||
o = s:option(ListValue, _n("fingerprint"), translate("Finger Print"))
|
||||
o:value("chrome")
|
||||
o:value("firefox")
|
||||
o:value("edge")
|
||||
@@ -390,10 +387,10 @@ o:value("android")
|
||||
o:value("random")
|
||||
o:value("randomized")
|
||||
o.default = "chrome"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("utls")] = true })
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
|
||||
o:depends({ [_n("tls")] = true, [_n("utls")] = true })
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = true })
|
||||
|
||||
o = s:option(ListValue, option_name("transport"), translate("Transport"))
|
||||
o = s:option(ListValue, _n("transport"), translate("Transport"))
|
||||
o:value("raw", "RAW (TCP)")
|
||||
o:value("mkcp", "mKCP")
|
||||
o:value("ws", "WebSocket")
|
||||
@@ -403,193 +400,193 @@ o:value("quic", "QUIC")
|
||||
o:value("grpc", "gRPC")
|
||||
o:value("httpupgrade", "HttpUpgrade")
|
||||
o:value("xhttp", "XHTTP (SplitHTTP)")
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
o = s:option(Value, option_name("wireguard_public_key"), translate("Public Key"))
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o = s:option(Value, _n("wireguard_public_key"), translate("Public Key"))
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
|
||||
o = s:option(Value, option_name("wireguard_secret_key"), translate("Private Key"))
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o = s:option(Value, _n("wireguard_secret_key"), translate("Private Key"))
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
|
||||
o = s:option(Value, option_name("wireguard_preSharedKey"), translate("Pre shared key"))
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o = s:option(Value, _n("wireguard_preSharedKey"), translate("Pre shared key"))
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
|
||||
o = s:option(DynamicList, option_name("wireguard_local_address"), translate("Local Address"))
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o = s:option(DynamicList, _n("wireguard_local_address"), translate("Local Address"))
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
|
||||
o = s:option(Value, option_name("wireguard_mtu"), translate("MTU"))
|
||||
o = s:option(Value, _n("wireguard_mtu"), translate("MTU"))
|
||||
o.default = "1420"
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
|
||||
if api.compare_versions(xray_version, ">=", "1.8.0") then
|
||||
o = s:option(Value, option_name("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o = s:option(Value, _n("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
end
|
||||
|
||||
o = s:option(Value, option_name("wireguard_keepAlive"), translate("Keep Alive"))
|
||||
o = s:option(Value, _n("wireguard_keepAlive"), translate("Keep Alive"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
|
||||
-- [[ RAW部分 ]]--
|
||||
|
||||
-- TCP伪装
|
||||
o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type"))
|
||||
o = s:option(ListValue, _n("tcp_guise"), translate("Camouflage Type"))
|
||||
o:value("none", "none")
|
||||
o:value("http", "http")
|
||||
o:depends({ [option_name("transport")] = "raw" })
|
||||
o:depends({ [_n("transport")] = "raw" })
|
||||
|
||||
-- HTTP域名
|
||||
o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host"))
|
||||
o:depends({ [option_name("tcp_guise")] = "http" })
|
||||
o = s:option(DynamicList, _n("tcp_guise_http_host"), translate("HTTP Host"))
|
||||
o:depends({ [_n("tcp_guise")] = "http" })
|
||||
|
||||
-- HTTP路径
|
||||
o = s:option(DynamicList, option_name("tcp_guise_http_path"), translate("HTTP Path"))
|
||||
o = s:option(DynamicList, _n("tcp_guise_http_path"), translate("HTTP Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("tcp_guise")] = "http" })
|
||||
o:depends({ [_n("tcp_guise")] = "http" })
|
||||
|
||||
-- [[ mKCP部分 ]]--
|
||||
|
||||
o = s:option(ListValue, option_name("mkcp_guise"), translate("Camouflage Type"), translate('<br />none: default, no masquerade, data sent is packets with no characteristics.<br />srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br />utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br />wechat-video: packets disguised as WeChat video calls.<br />dtls: disguised as DTLS 1.2 packet.<br />wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)'))
|
||||
o = s:option(ListValue, _n("mkcp_guise"), translate("Camouflage Type"), translate('<br />none: default, no masquerade, data sent is packets with no characteristics.<br />srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br />utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br />wechat-video: packets disguised as WeChat video calls.<br />dtls: disguised as DTLS 1.2 packet.<br />wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)'))
|
||||
for a, t in ipairs(header_type_list) do o:value(t) end
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_mtu"), translate("KCP MTU"))
|
||||
o = s:option(Value, _n("mkcp_mtu"), translate("KCP MTU"))
|
||||
o.default = "1350"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_tti"), translate("KCP TTI"))
|
||||
o = s:option(Value, _n("mkcp_tti"), translate("KCP TTI"))
|
||||
o.default = "20"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity"))
|
||||
o = s:option(Value, _n("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity"))
|
||||
o.default = "5"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity"))
|
||||
o = s:option(Value, _n("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity"))
|
||||
o.default = "20"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Flag, option_name("mkcp_congestion"), translate("KCP Congestion"))
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o = s:option(Flag, _n("mkcp_congestion"), translate("KCP Congestion"))
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_readBufferSize"), translate("KCP readBufferSize"))
|
||||
o = s:option(Value, _n("mkcp_readBufferSize"), translate("KCP readBufferSize"))
|
||||
o.default = "1"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_writeBufferSize"), translate("KCP writeBufferSize"))
|
||||
o = s:option(Value, _n("mkcp_writeBufferSize"), translate("KCP writeBufferSize"))
|
||||
o.default = "1"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_seed"), translate("KCP Seed"))
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o = s:option(Value, _n("mkcp_seed"), translate("KCP Seed"))
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
-- [[ WebSocket部分 ]]--
|
||||
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
|
||||
o:depends({ [option_name("transport")] = "ws" })
|
||||
o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
|
||||
o:depends({ [_n("transport")] = "ws" })
|
||||
|
||||
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path"))
|
||||
o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("transport")] = "ws" })
|
||||
o:depends({ [_n("transport")] = "ws" })
|
||||
|
||||
o = s:option(Value, option_name("ws_heartbeatPeriod"), translate("HeartbeatPeriod(second)"))
|
||||
o = s:option(Value, _n("ws_heartbeatPeriod"), translate("HeartbeatPeriod(second)"))
|
||||
o.datatype = "integer"
|
||||
o:depends({ [option_name("transport")] = "ws" })
|
||||
o:depends({ [_n("transport")] = "ws" })
|
||||
|
||||
-- [[ HTTP/2部分 ]]--
|
||||
o = s:option(Value, option_name("h2_host"), translate("HTTP/2 Host"))
|
||||
o:depends({ [option_name("transport")] = "h2" })
|
||||
o = s:option(Value, _n("h2_host"), translate("HTTP/2 Host"))
|
||||
o:depends({ [_n("transport")] = "h2" })
|
||||
|
||||
o = s:option(Value, option_name("h2_path"), translate("HTTP/2 Path"))
|
||||
o = s:option(Value, _n("h2_path"), translate("HTTP/2 Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("transport")] = "h2" })
|
||||
o:depends({ [_n("transport")] = "h2" })
|
||||
|
||||
o = s:option(Flag, option_name("h2_health_check"), translate("Health check"))
|
||||
o:depends({ [option_name("transport")] = "h2" })
|
||||
o = s:option(Flag, _n("h2_health_check"), translate("Health check"))
|
||||
o:depends({ [_n("transport")] = "h2" })
|
||||
|
||||
o = s:option(Value, option_name("h2_read_idle_timeout"), translate("Idle timeout"))
|
||||
o = s:option(Value, _n("h2_read_idle_timeout"), translate("Idle timeout"))
|
||||
o.default = "10"
|
||||
o:depends({ [option_name("h2_health_check")] = true })
|
||||
o:depends({ [_n("h2_health_check")] = true })
|
||||
|
||||
o = s:option(Value, option_name("h2_health_check_timeout"), translate("Health check timeout"))
|
||||
o = s:option(Value, _n("h2_health_check_timeout"), translate("Health check timeout"))
|
||||
o.default = "15"
|
||||
o:depends({ [option_name("h2_health_check")] = true })
|
||||
o:depends({ [_n("h2_health_check")] = true })
|
||||
|
||||
-- [[ DomainSocket部分 ]]--
|
||||
o = s:option(Value, option_name("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
|
||||
o:depends({ [option_name("transport")] = "ds" })
|
||||
o = s:option(Value, _n("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
|
||||
o:depends({ [_n("transport")] = "ds" })
|
||||
|
||||
-- [[ QUIC部分 ]]--
|
||||
o = s:option(ListValue, option_name("quic_security"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("quic_security"), translate("Encrypt Method"))
|
||||
o:value("none")
|
||||
o:value("aes-128-gcm")
|
||||
o:value("chacha20-poly1305")
|
||||
o:depends({ [option_name("transport")] = "quic" })
|
||||
o:depends({ [_n("transport")] = "quic" })
|
||||
|
||||
o = s:option(Value, option_name("quic_key"), translate("Encrypt Method") .. translate("Key"))
|
||||
o:depends({ [option_name("transport")] = "quic" })
|
||||
o = s:option(Value, _n("quic_key"), translate("Encrypt Method") .. translate("Key"))
|
||||
o:depends({ [_n("transport")] = "quic" })
|
||||
|
||||
o = s:option(ListValue, option_name("quic_guise"), translate("Camouflage Type"))
|
||||
o = s:option(ListValue, _n("quic_guise"), translate("Camouflage Type"))
|
||||
for a, t in ipairs(header_type_list) do o:value(t) end
|
||||
o:depends({ [option_name("transport")] = "quic" })
|
||||
o:depends({ [_n("transport")] = "quic" })
|
||||
|
||||
-- [[ gRPC部分 ]]--
|
||||
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
|
||||
o:depends({ [option_name("transport")] = "grpc" })
|
||||
o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
|
||||
o:depends({ [_n("transport")] = "grpc" })
|
||||
|
||||
o = s:option(ListValue, option_name("grpc_mode"), "gRPC " .. translate("Transfer mode"))
|
||||
o = s:option(ListValue, _n("grpc_mode"), "gRPC " .. translate("Transfer mode"))
|
||||
o:value("gun")
|
||||
o:value("multi")
|
||||
o:depends({ [option_name("transport")] = "grpc" })
|
||||
o:depends({ [_n("transport")] = "grpc" })
|
||||
|
||||
o = s:option(Flag, option_name("grpc_health_check"), translate("Health check"))
|
||||
o:depends({ [option_name("transport")] = "grpc" })
|
||||
o = s:option(Flag, _n("grpc_health_check"), translate("Health check"))
|
||||
o:depends({ [_n("transport")] = "grpc" })
|
||||
|
||||
o = s:option(Value, option_name("grpc_idle_timeout"), translate("Idle timeout"))
|
||||
o = s:option(Value, _n("grpc_idle_timeout"), translate("Idle timeout"))
|
||||
o.default = "10"
|
||||
o:depends({ [option_name("grpc_health_check")] = true })
|
||||
o:depends({ [_n("grpc_health_check")] = true })
|
||||
|
||||
o = s:option(Value, option_name("grpc_health_check_timeout"), translate("Health check timeout"))
|
||||
o = s:option(Value, _n("grpc_health_check_timeout"), translate("Health check timeout"))
|
||||
o.default = "20"
|
||||
o:depends({ [option_name("grpc_health_check")] = true })
|
||||
o:depends({ [_n("grpc_health_check")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("grpc_permit_without_stream"), translate("Permit without stream"))
|
||||
o = s:option(Flag, _n("grpc_permit_without_stream"), translate("Permit without stream"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("grpc_health_check")] = true })
|
||||
o:depends({ [_n("grpc_health_check")] = true })
|
||||
|
||||
o = s:option(Value, option_name("grpc_initial_windows_size"), translate("Initial Windows Size"))
|
||||
o = s:option(Value, _n("grpc_initial_windows_size"), translate("Initial Windows Size"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("transport")] = "grpc" })
|
||||
o:depends({ [_n("transport")] = "grpc" })
|
||||
|
||||
-- [[ HttpUpgrade部分 ]]--
|
||||
o = s:option(Value, option_name("httpupgrade_host"), translate("HttpUpgrade Host"))
|
||||
o:depends({ [option_name("transport")] = "httpupgrade" })
|
||||
o = s:option(Value, _n("httpupgrade_host"), translate("HttpUpgrade Host"))
|
||||
o:depends({ [_n("transport")] = "httpupgrade" })
|
||||
|
||||
o = s:option(Value, option_name("httpupgrade_path"), translate("HttpUpgrade Path"))
|
||||
o = s:option(Value, _n("httpupgrade_path"), translate("HttpUpgrade Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("transport")] = "httpupgrade" })
|
||||
o:depends({ [_n("transport")] = "httpupgrade" })
|
||||
|
||||
-- [[ XHTTP部分 ]]--
|
||||
o = s:option(ListValue, option_name("xhttp_mode"), "XHTTP " .. translate("Mode"))
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
o = s:option(ListValue, _n("xhttp_mode"), "XHTTP " .. translate("Mode"))
|
||||
o:depends({ [_n("transport")] = "xhttp" })
|
||||
o.default = "auto"
|
||||
o:value("auto")
|
||||
o:value("packet-up")
|
||||
o:value("stream-up")
|
||||
o:value("stream-one")
|
||||
|
||||
o = s:option(Value, option_name("xhttp_host"), translate("XHTTP Host"))
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
o = s:option(Value, _n("xhttp_host"), translate("XHTTP Host"))
|
||||
o:depends({ [_n("transport")] = "xhttp" })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_path"), translate("XHTTP Path"))
|
||||
o = s:option(Value, _n("xhttp_path"), translate("XHTTP Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
o:depends({ [_n("transport")] = "xhttp" })
|
||||
|
||||
o = s:option(TextValue, option_name("xhttp_extra"), translate("XHTTP Extra"), translate("An <a target='_blank' href='https://xtls.github.io/config/transports/splithttp.html#extra'>XHTTP extra object</a> in raw json"))
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
o = s:option(TextValue, _n("xhttp_extra"), translate("XHTTP Extra"), translate("An <a target='_blank' href='https://xtls.github.io/config/transports/splithttp.html#extra'>XHTTP extra object</a> in raw json"))
|
||||
o:depends({ [_n("transport")] = "xhttp" })
|
||||
o.rows = 15
|
||||
o.wrap = "off"
|
||||
o.custom_write = function(self, section, value)
|
||||
@@ -618,62 +615,62 @@ o.validate = function(self, value)
|
||||
end
|
||||
|
||||
-- [[ Mux.Cool ]]--
|
||||
o = s:option(Flag, option_name("mux"), "Mux", translate("Enable Mux.Cool"))
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" })
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o = s:option(Flag, _n("mux"), "Mux", translate("Enable Mux.Cool"))
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
o = s:option(Value, option_name("mux_concurrency"), translate("Mux concurrency"))
|
||||
o = s:option(Value, _n("mux_concurrency"), translate("Mux concurrency"))
|
||||
o.default = 8
|
||||
o:depends({ [option_name("mux")] = true })
|
||||
o:depends({ [_n("mux")] = true })
|
||||
|
||||
-- [[ XUDP Mux ]]--
|
||||
o = s:option(Flag, option_name("xmux"), "XUDP Mux")
|
||||
o = s:option(Flag, _n("xmux"), "XUDP Mux")
|
||||
o.default = 1
|
||||
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "xtls-rprx-vision" })
|
||||
o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "xtls-rprx-vision" })
|
||||
|
||||
o = s:option(Value, option_name("xudp_concurrency"), translate("XUDP Mux concurrency"))
|
||||
o = s:option(Value, _n("xudp_concurrency"), translate("XUDP Mux concurrency"))
|
||||
o.default = 8
|
||||
o:depends({ [option_name("xmux")] = true })
|
||||
o:depends({ [_n("xmux")] = true })
|
||||
|
||||
--[[tcpMptcp]]
|
||||
o = s:option(Flag, option_name("tcpMptcp"), "tcpMptcp", translate("Enable Multipath TCP, need to be enabled in both server and client configuration."))
|
||||
o = s:option(Flag, _n("tcpMptcp"), "tcpMptcp", translate("Enable Multipath TCP, need to be enabled in both server and client configuration."))
|
||||
o.default = 0
|
||||
|
||||
o = s:option(Flag, option_name("tcpNoDelay"), "tcpNoDelay")
|
||||
o = s:option(Flag, _n("tcpNoDelay"), "tcpNoDelay")
|
||||
o.default = 0
|
||||
|
||||
o = s:option(ListValue, option_name("chain_proxy"), translate("Chain Proxy"))
|
||||
o = s:option(ListValue, _n("chain_proxy"), translate("Chain Proxy"))
|
||||
o:value("", translate("Close(Not use)"))
|
||||
o:value("1", translate("Preproxy Node"))
|
||||
o:value("2", translate("Landing Node"))
|
||||
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do
|
||||
for i, v in ipairs(s.fields[_n("protocol")].keylist) do
|
||||
if not v:find("_") then
|
||||
o:depends({ [option_name("protocol")] = v })
|
||||
o:depends({ [_n("protocol")] = v })
|
||||
end
|
||||
end
|
||||
|
||||
o = s:option(ListValue, option_name("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
|
||||
o:depends({ [option_name("chain_proxy")] = "1" })
|
||||
o = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
|
||||
o:depends({ [_n("chain_proxy")] = "1" })
|
||||
|
||||
o = s:option(ListValue, option_name("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
|
||||
o:depends({ [option_name("chain_proxy")] = "2" })
|
||||
o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
|
||||
o:depends({ [_n("chain_proxy")] = "2" })
|
||||
|
||||
for k, v in pairs(nodes_table) do
|
||||
if v.type == "Xray" and v.id ~= arg[1] then
|
||||
s.fields[option_name("preproxy_node")]:value(v.id, v.remark)
|
||||
s.fields[option_name("to_node")]:value(v.id, v.remark)
|
||||
s.fields[_n("preproxy_node")]:value(v.id, v.remark)
|
||||
s.fields[_n("to_node")]:value(v.id, v.remark)
|
||||
end
|
||||
end
|
||||
|
||||
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do
|
||||
for i, v in ipairs(s.fields[_n("protocol")].keylist) do
|
||||
if not v:find("_") then
|
||||
s.fields[option_name("tcpMptcp")]:depends({ [option_name("protocol")] = v })
|
||||
s.fields[option_name("tcpNoDelay")]:depends({ [option_name("protocol")] = v })
|
||||
s.fields[option_name("chain_proxy")]:depends({ [option_name("protocol")] = v })
|
||||
s.fields[_n("tcpMptcp")]:depends({ [_n("protocol")] = v })
|
||||
s.fields[_n("tcpNoDelay")]:depends({ [_n("protocol")] = v })
|
||||
s.fields[_n("chain_proxy")]:depends({ [_n("protocol")] = v })
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+261
-264
@@ -17,7 +17,7 @@ local type_name = "sing-box"
|
||||
|
||||
local option_prefix = "singbox_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -35,7 +35,7 @@ local security_list = { "none", "auto", "aes-128-gcm", "chacha20-poly1305", "zer
|
||||
|
||||
s.fields["type"]:value(type_name, "Sing-Box")
|
||||
|
||||
o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
|
||||
o = s:option(ListValue, _n("protocol"), translate("Protocol"))
|
||||
o:value("socks", "Socks")
|
||||
o:value("http", "HTTP")
|
||||
o:value("shadowsocks", "Shadowsocks")
|
||||
@@ -60,9 +60,9 @@ end
|
||||
o:value("_shunt", translate("Shunt"))
|
||||
o:value("_iface", translate("Custom Interface"))
|
||||
|
||||
o = s:option(Value, option_name("iface"), translate("Interface"))
|
||||
o = s:option(Value, _n("iface"), translate("Interface"))
|
||||
o.default = "eth1"
|
||||
o:depends({ [option_name("protocol")] = "_iface" })
|
||||
o:depends({ [_n("protocol")] = "_iface" })
|
||||
|
||||
local nodes_table = {}
|
||||
local iface_table = {}
|
||||
@@ -94,11 +94,11 @@ end)
|
||||
|
||||
-- [[ 分流模块 ]]
|
||||
if #nodes_table > 0 then
|
||||
o = s:option(Flag, option_name("preproxy_enabled"), translate("Preproxy"))
|
||||
o:depends({ [option_name("protocol")] = "_shunt" })
|
||||
o = s:option(Flag, _n("preproxy_enabled"), translate("Preproxy"))
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
|
||||
o = s:option(ListValue, option_name("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not."))
|
||||
o:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true })
|
||||
o = s:option(ListValue, _n("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not."))
|
||||
o:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true })
|
||||
for k, v in pairs(socks_list) do
|
||||
o:value(v.id, v.remark)
|
||||
end
|
||||
@@ -108,16 +108,15 @@ if #nodes_table > 0 then
|
||||
for k, v in pairs(nodes_table) do
|
||||
o:value(v.id, v.remark)
|
||||
end
|
||||
o.default = "nil"
|
||||
end
|
||||
uci:foreach(appname, "shunt_rules", function(e)
|
||||
if e[".name"] and e.remarks then
|
||||
o = s:option(ListValue, option_name(e[".name"]), string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks))
|
||||
o:value("nil", translate("Close"))
|
||||
o = s:option(ListValue, _n(e[".name"]), string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks))
|
||||
o:value("", translate("Close"))
|
||||
o:value("_default", translate("Default"))
|
||||
o:value("_direct", translate("Direct Connection"))
|
||||
o:value("_blackhole", translate("Blackhole"))
|
||||
o:depends({ [option_name("protocol")] = "_shunt" })
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
|
||||
if #nodes_table > 0 then
|
||||
for k, v in pairs(socks_list) do
|
||||
@@ -126,28 +125,27 @@ uci:foreach(appname, "shunt_rules", function(e)
|
||||
for k, v in pairs(iface_table) do
|
||||
o:value(v.id, v.remark)
|
||||
end
|
||||
local pt = s:option(ListValue, option_name(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
|
||||
pt:value("nil", translate("Close"))
|
||||
local pt = s:option(ListValue, _n(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
|
||||
pt:value("", translate("Close"))
|
||||
pt:value("main", translate("Preproxy Node"))
|
||||
pt.default = "nil"
|
||||
for k, v in pairs(nodes_table) do
|
||||
o:value(v.id, v.remark)
|
||||
pt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name(e[".name"])] = v.id })
|
||||
pt:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true, [_n(e[".name"])] = v.id })
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
o = s:option(DummyValue, option_name("shunt_tips"), " ")
|
||||
o = s:option(DummyValue, _n("shunt_tips"), " ")
|
||||
o.not_rewrite = true
|
||||
o.rawhtml = true
|
||||
o.cfgvalue = function(t, n)
|
||||
return string.format('<a style="color: red" href="../rule">%s</a>', translate("No shunt rules? Click me to go to add."))
|
||||
end
|
||||
o:depends({ [option_name("protocol")] = "_shunt" })
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
|
||||
local o = s:option(ListValue, option_name("default_node"), string.format('* <a style="color:red">%s</a>', translate("Default")))
|
||||
o:depends({ [option_name("protocol")] = "_shunt" })
|
||||
local o = s:option(ListValue, _n("default_node"), string.format('* <a style="color:red">%s</a>', translate("Default")))
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
o:value("_direct", translate("Direct Connection"))
|
||||
o:value("_blackhole", translate("Blackhole"))
|
||||
|
||||
@@ -158,61 +156,60 @@ if #nodes_table > 0 then
|
||||
for k, v in pairs(iface_table) do
|
||||
o:value(v.id, v.remark)
|
||||
end
|
||||
local dpt = s:option(ListValue, option_name("default_proxy_tag"), string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
|
||||
dpt:value("nil", translate("Close"))
|
||||
local dpt = s:option(ListValue, _n("default_proxy_tag"), string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
|
||||
dpt:value("", translate("Close"))
|
||||
dpt:value("main", translate("Preproxy Node"))
|
||||
dpt.default = "nil"
|
||||
for k, v in pairs(nodes_table) do
|
||||
o:value(v.id, v.remark)
|
||||
dpt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name("default_node")] = v.id })
|
||||
dpt:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true, [_n("default_node")] = v.id })
|
||||
end
|
||||
end
|
||||
|
||||
-- [[ 分流模块 End ]]
|
||||
|
||||
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)"))
|
||||
o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Port"))
|
||||
o = s:option(Value, _n("port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
local protocols = s.fields[option_name("protocol")].keylist
|
||||
local protocols = s.fields[_n("protocol")].keylist
|
||||
if #protocols > 0 then
|
||||
for index, value in ipairs(protocols) do
|
||||
if not value:find("_") then
|
||||
s.fields[option_name("address")]:depends({ [option_name("protocol")] = value })
|
||||
s.fields[option_name("port")]:depends({ [option_name("protocol")] = value })
|
||||
s.fields[_n("address")]:depends({ [_n("protocol")] = value })
|
||||
s.fields[_n("port")]:depends({ [_n("protocol")] = value })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
o = s:option(Value, option_name("username"), translate("Username"))
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o = s:option(Value, _n("username"), translate("Username"))
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocksr" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocksr" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
|
||||
o = s:option(ListValue, option_name("security"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("security"), translate("Encrypt Method"))
|
||||
for a, t in ipairs(security_list) do o:value(t) end
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
|
||||
o = s:option(ListValue, option_name("ss_method"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("ss_method"), translate("Encrypt Method"))
|
||||
o.rewrite_option = "method"
|
||||
for a, t in ipairs(ss_method_new_list) do o:value(t) end
|
||||
for a, t in ipairs(ss_method_old_list) do o:value(t) end
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
if singbox_tags:find("with_shadowsocksr") then
|
||||
o = s:option(ListValue, option_name("ssr_method"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("ssr_method"), translate("Encrypt Method"))
|
||||
o.rewrite_option = "method"
|
||||
for a, t in ipairs(ss_method_old_list) do o:value(t) end
|
||||
o:depends({ [option_name("protocol")] = "shadowsocksr" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocksr" })
|
||||
|
||||
local ssr_protocol_list = {
|
||||
"origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple",
|
||||
@@ -221,120 +218,120 @@ if singbox_tags:find("with_shadowsocksr") then
|
||||
"auth_chain_d", "auth_chain_e", "auth_chain_f"
|
||||
}
|
||||
|
||||
o = s:option(ListValue, option_name("ssr_protocol"), translate("Protocol"))
|
||||
o = s:option(ListValue, _n("ssr_protocol"), translate("Protocol"))
|
||||
for a, t in ipairs(ssr_protocol_list) do o:value(t) end
|
||||
o:depends({ [option_name("protocol")] = "shadowsocksr" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocksr" })
|
||||
|
||||
o = s:option(Value, option_name("ssr_protocol_param"), translate("Protocol_param"))
|
||||
o:depends({ [option_name("protocol")] = "shadowsocksr" })
|
||||
o = s:option(Value, _n("ssr_protocol_param"), translate("Protocol_param"))
|
||||
o:depends({ [_n("protocol")] = "shadowsocksr" })
|
||||
|
||||
local ssr_obfs_list = {
|
||||
"plain", "http_simple", "http_post", "random_head", "tls_simple",
|
||||
"tls1.0_session_auth", "tls1.2_ticket_auth"
|
||||
}
|
||||
|
||||
o = s:option(ListValue, option_name("ssr_obfs"), translate("Obfs"))
|
||||
o = s:option(ListValue, _n("ssr_obfs"), translate("Obfs"))
|
||||
for a, t in ipairs(ssr_obfs_list) do o:value(t) end
|
||||
o:depends({ [option_name("protocol")] = "shadowsocksr" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocksr" })
|
||||
|
||||
o = s:option(Value, option_name("ssr_obfs_param"), translate("Obfs_param"))
|
||||
o:depends({ [option_name("protocol")] = "shadowsocksr" })
|
||||
o = s:option(Value, _n("ssr_obfs_param"), translate("Obfs_param"))
|
||||
o:depends({ [_n("protocol")] = "shadowsocksr" })
|
||||
end
|
||||
|
||||
o = s:option(Flag, option_name("uot"), translate("UDP over TCP"))
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o = s:option(Flag, _n("uot"), translate("UDP over TCP"))
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(Value, option_name("uuid"), translate("ID"))
|
||||
o = s:option(Value, _n("uuid"), translate("ID"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
|
||||
o = s:option(Value, option_name("alter_id"), "Alter ID")
|
||||
o = s:option(Value, _n("alter_id"), "Alter ID")
|
||||
o.datatype = "uinteger"
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
|
||||
o = s:option(Flag, option_name("global_padding"), "global_padding", translate("Protocol parameter. Will waste traffic randomly if enabled."))
|
||||
o = s:option(Flag, _n("global_padding"), "global_padding", translate("Protocol parameter. Will waste traffic randomly if enabled."))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
|
||||
o = s:option(Flag, option_name("authenticated_length"), "authenticated_length", translate("Protocol parameter. Enable length block encryption."))
|
||||
o = s:option(Flag, _n("authenticated_length"), "authenticated_length", translate("Protocol parameter. Enable length block encryption."))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
|
||||
o = s:option(ListValue, option_name("flow"), translate("flow"))
|
||||
o = s:option(ListValue, _n("flow"), translate("flow"))
|
||||
o.default = ""
|
||||
o:value("", translate("Disable"))
|
||||
o:value("xtls-rprx-vision")
|
||||
o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true })
|
||||
o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true })
|
||||
|
||||
if singbox_tags:find("with_quic") then
|
||||
o = s:option(Value, option_name("hysteria_obfs"), translate("Obfs Password"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(ListValue, option_name("hysteria_auth_type"), translate("Auth Type"))
|
||||
o = s:option(ListValue, _n("hysteria_auth_type"), translate("Auth Type"))
|
||||
o:value("disable", translate("Disable"))
|
||||
o:value("string", translate("STRING"))
|
||||
o:value("base64", translate("BASE64"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria_auth_password"), translate("Auth Password"))
|
||||
o = s:option(Value, _n("hysteria_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "string"})
|
||||
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "base64"})
|
||||
o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "string"})
|
||||
o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "base64"})
|
||||
|
||||
o = s:option(Value, option_name("hysteria_up_mbps"), translate("Max upload Mbps"))
|
||||
o = s:option(Value, _n("hysteria_up_mbps"), translate("Max upload Mbps"))
|
||||
o.default = "10"
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria_down_mbps"), translate("Max download Mbps"))
|
||||
o = s:option(Value, _n("hysteria_down_mbps"), translate("Max download Mbps"))
|
||||
o.default = "50"
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o = s:option(Value, _n("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria_recv_window"), translate("QUIC connection receive window"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o = s:option(Value, _n("hysteria_recv_window"), translate("QUIC connection receive window"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Flag, option_name("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o = s:option(Flag, _n("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria_alpn"), translate("QUIC TLS ALPN"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o = s:option(Value, _n("hysteria_alpn"), translate("QUIC TLS ALPN"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
end
|
||||
|
||||
if singbox_tags:find("with_quic") then
|
||||
o = s:option(ListValue, option_name("tuic_congestion_control"), translate("Congestion control algorithm"))
|
||||
o = s:option(ListValue, _n("tuic_congestion_control"), translate("Congestion control algorithm"))
|
||||
o.default = "cubic"
|
||||
o:value("bbr", translate("BBR"))
|
||||
o:value("cubic", translate("CUBIC"))
|
||||
o:value("new_reno", translate("New Reno"))
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
|
||||
o = s:option(ListValue, option_name("tuic_udp_relay_mode"), translate("UDP relay mode"))
|
||||
o = s:option(ListValue, _n("tuic_udp_relay_mode"), translate("UDP relay mode"))
|
||||
o.default = "native"
|
||||
o:value("native", translate("native"))
|
||||
o:value("quic", translate("QUIC"))
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
|
||||
--[[
|
||||
o = s:option(Flag, option_name("tuic_udp_over_stream"), translate("UDP over stream"))
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o = s:option(Flag, _n("tuic_udp_over_stream"), translate("UDP over stream"))
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
]]--
|
||||
|
||||
o = s:option(Flag, option_name("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
|
||||
o = s:option(Flag, _n("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
|
||||
o = s:option(Value, option_name("tuic_heartbeat"), translate("Heartbeat interval(second)"))
|
||||
o = s:option(Value, _n("tuic_heartbeat"), translate("Heartbeat interval(second)"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = "3"
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
|
||||
o = s:option(ListValue, option_name("tuic_alpn"), translate("QUIC TLS ALPN"))
|
||||
o = s:option(ListValue, _n("tuic_alpn"), translate("QUIC TLS ALPN"))
|
||||
o.default = "default"
|
||||
o:value("default", translate("Default"))
|
||||
o:value("h3")
|
||||
@@ -343,38 +340,38 @@ if singbox_tags:find("with_quic") then
|
||||
o:value("http/1.1")
|
||||
o:value("h2,http/1.1")
|
||||
o:value("h3,h2,http/1.1")
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
end
|
||||
|
||||
if singbox_tags:find("with_quic") then
|
||||
o = s:option(Value, option_name("hysteria2_up_mbps"), translate("Max upload Mbps"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria2_down_mbps"), translate("Max download Mbps"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(ListValue, option_name("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("protocol")] = "hysteria2"})
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
end
|
||||
|
||||
o = s:option(Flag, option_name("tls"), translate("TLS"))
|
||||
o = s:option(Flag, _n("tls"), translate("TLS"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(ListValue, option_name("alpn"), translate("alpn"))
|
||||
o = s:option(ListValue, _n("alpn"), translate("alpn"))
|
||||
o.default = "default"
|
||||
o:value("default", translate("Default"))
|
||||
o:value("h3")
|
||||
@@ -383,36 +380,36 @@ o:value("h3,h2")
|
||||
o:value("http/1.1")
|
||||
o:value("h2,http/1.1")
|
||||
o:value("h3,h2,http/1.1")
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o:depends({ [_n("tls")] = true })
|
||||
|
||||
o = s:option(Value, option_name("tls_serverName"), translate("Domain"))
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o:depends({ [option_name("protocol")] = "hysteria"})
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o = s:option(Value, _n("tls_serverName"), translate("Domain"))
|
||||
o:depends({ [_n("tls")] = true })
|
||||
o:depends({ [_n("protocol")] = "hysteria"})
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(Flag, option_name("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
|
||||
o = s:option(Flag, _n("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o:depends({ [option_name("protocol")] = "hysteria"})
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("tls")] = true })
|
||||
o:depends({ [_n("protocol")] = "hysteria"})
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
if singbox_tags:find("with_ech") then
|
||||
o = s:option(Flag, option_name("ech"), translate("ECH"))
|
||||
o = s:option(Flag, _n("ech"), translate("ECH"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("flow")] = "", [option_name("reality")] = false })
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(TextValue, option_name("ech_config"), translate("ECH Config"))
|
||||
o = s:option(TextValue, _n("ech_config"), translate("ECH Config"))
|
||||
o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ [option_name("ech")] = true })
|
||||
o:depends({ [_n("ech")] = true })
|
||||
o.validate = function(self, value)
|
||||
value = value:gsub("^%s+", ""):gsub("%s+$","\n"):gsub("\r\n","\n"):gsub("[ \t]*\n[ \t]*", "\n")
|
||||
value = value:gsub("^%s*\n", "")
|
||||
@@ -422,21 +419,21 @@ if singbox_tags:find("with_ech") then
|
||||
return value
|
||||
end
|
||||
|
||||
o = s:option(Flag, option_name("pq_signature_schemes_enabled"), translate("PQ signature schemes"))
|
||||
o = s:option(Flag, _n("pq_signature_schemes_enabled"), translate("PQ signature schemes"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("ech")] = true })
|
||||
o:depends({ [_n("ech")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("dynamic_record_sizing_disabled"), translate("Disable adaptive sizing of TLS records"))
|
||||
o = s:option(Flag, _n("dynamic_record_sizing_disabled"), translate("Disable adaptive sizing of TLS records"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("ech")] = true })
|
||||
o:depends({ [_n("ech")] = true })
|
||||
end
|
||||
|
||||
if singbox_tags:find("with_utls") then
|
||||
o = s:option(Flag, option_name("utls"), translate("uTLS"))
|
||||
o = s:option(Flag, _n("utls"), translate("uTLS"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o:depends({ [_n("tls")] = true })
|
||||
|
||||
o = s:option(ListValue, option_name("fingerprint"), translate("Finger Print"))
|
||||
o = s:option(ListValue, _n("fingerprint"), translate("Finger Print"))
|
||||
o:value("chrome")
|
||||
o:value("firefox")
|
||||
o:value("edge")
|
||||
@@ -448,25 +445,25 @@ if singbox_tags:find("with_utls") then
|
||||
o:value("random")
|
||||
-- o:value("randomized")
|
||||
o.default = "chrome"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("utls")] = true })
|
||||
o:depends({ [_n("tls")] = true, [_n("utls")] = true })
|
||||
|
||||
-- [[ REALITY部分 ]] --
|
||||
o = s:option(Flag, option_name("reality"), translate("REALITY"))
|
||||
o = s:option(Flag, _n("reality"), translate("REALITY"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("protocol")] = "vless", [option_name("utls")] = true })
|
||||
o:depends({ [option_name("protocol")] = "vmess", [option_name("utls")] = true })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("utls")] = true })
|
||||
o:depends({ [option_name("protocol")] = "socks", [option_name("utls")] = true })
|
||||
o:depends({ [option_name("protocol")] = "trojan", [option_name("utls")] = true })
|
||||
o:depends({ [_n("protocol")] = "vless", [_n("utls")] = true })
|
||||
o:depends({ [_n("protocol")] = "vmess", [_n("utls")] = true })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks", [_n("utls")] = true })
|
||||
o:depends({ [_n("protocol")] = "socks", [_n("utls")] = true })
|
||||
o:depends({ [_n("protocol")] = "trojan", [_n("utls")] = true })
|
||||
|
||||
o = s:option(Value, option_name("reality_publicKey"), translate("Public Key"))
|
||||
o:depends({ [option_name("utls")] = true, [option_name("reality")] = true })
|
||||
o = s:option(Value, _n("reality_publicKey"), translate("Public Key"))
|
||||
o:depends({ [_n("utls")] = true, [_n("reality")] = true })
|
||||
|
||||
o = s:option(Value, option_name("reality_shortId"), translate("Short Id"))
|
||||
o:depends({ [option_name("utls")] = true, [option_name("reality")] = true })
|
||||
o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
|
||||
o:depends({ [_n("utls")] = true, [_n("reality")] = true })
|
||||
end
|
||||
|
||||
o = s:option(ListValue, option_name("transport"), translate("Transport"))
|
||||
o = s:option(ListValue, _n("transport"), translate("Transport"))
|
||||
o:value("tcp", "TCP")
|
||||
o:value("http", "HTTP")
|
||||
o:value("ws", "WebSocket")
|
||||
@@ -478,158 +475,158 @@ if singbox_tags:find("with_grpc") then
|
||||
o:value("grpc", "gRPC")
|
||||
else o:value("grpc", "gRPC-lite")
|
||||
end
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
if singbox_tags:find("with_wireguard") then
|
||||
o = s:option(Value, option_name("wireguard_public_key"), translate("Public Key"))
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o = s:option(Value, _n("wireguard_public_key"), translate("Public Key"))
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
|
||||
o = s:option(Value, option_name("wireguard_secret_key"), translate("Private Key"))
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o = s:option(Value, _n("wireguard_secret_key"), translate("Private Key"))
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
|
||||
o = s:option(Value, option_name("wireguard_preSharedKey"), translate("Pre shared key"))
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o = s:option(Value, _n("wireguard_preSharedKey"), translate("Pre shared key"))
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
|
||||
o = s:option(DynamicList, option_name("wireguard_local_address"), translate("Local Address"))
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o = s:option(DynamicList, _n("wireguard_local_address"), translate("Local Address"))
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
|
||||
o = s:option(Value, option_name("wireguard_mtu"), translate("MTU"))
|
||||
o = s:option(Value, _n("wireguard_mtu"), translate("MTU"))
|
||||
o.default = "1420"
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
|
||||
o = s:option(Value, option_name("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o = s:option(Value, _n("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
end
|
||||
|
||||
-- [[ HTTP部分 ]]--
|
||||
o = s:option(Value, option_name("http_host"), translate("HTTP Host"))
|
||||
o:depends({ [option_name("transport")] = "http" })
|
||||
o = s:option(Value, _n("http_host"), translate("HTTP Host"))
|
||||
o:depends({ [_n("transport")] = "http" })
|
||||
|
||||
o = s:option(Value, option_name("http_path"), translate("HTTP Path"))
|
||||
o = s:option(Value, _n("http_path"), translate("HTTP Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("transport")] = "http" })
|
||||
o:depends({ [_n("transport")] = "http" })
|
||||
|
||||
o = s:option(Flag, option_name("http_h2_health_check"), translate("Health check"))
|
||||
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "http" })
|
||||
o = s:option(Flag, _n("http_h2_health_check"), translate("Health check"))
|
||||
o:depends({ [_n("tls")] = true, [_n("transport")] = "http" })
|
||||
|
||||
o = s:option(Value, option_name("http_h2_read_idle_timeout"), translate("Idle timeout"))
|
||||
o = s:option(Value, _n("http_h2_read_idle_timeout"), translate("Idle timeout"))
|
||||
o.default = "10"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "http", [option_name("http_h2_health_check")] = true })
|
||||
o:depends({ [_n("tls")] = true, [_n("transport")] = "http", [_n("http_h2_health_check")] = true })
|
||||
|
||||
o = s:option(Value, option_name("http_h2_health_check_timeout"), translate("Health check timeout"))
|
||||
o = s:option(Value, _n("http_h2_health_check_timeout"), translate("Health check timeout"))
|
||||
o.default = "15"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "http", [option_name("http_h2_health_check")] = true })
|
||||
o:depends({ [_n("tls")] = true, [_n("transport")] = "http", [_n("http_h2_health_check")] = true })
|
||||
|
||||
-- [[ WebSocket部分 ]]--
|
||||
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
|
||||
o:depends({ [option_name("transport")] = "ws" })
|
||||
o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
|
||||
o:depends({ [_n("transport")] = "ws" })
|
||||
|
||||
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path"))
|
||||
o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("transport")] = "ws" })
|
||||
o:depends({ [_n("transport")] = "ws" })
|
||||
|
||||
o = s:option(Flag, option_name("ws_enableEarlyData"), translate("Enable early data"))
|
||||
o:depends({ [option_name("transport")] = "ws" })
|
||||
o = s:option(Flag, _n("ws_enableEarlyData"), translate("Enable early data"))
|
||||
o:depends({ [_n("transport")] = "ws" })
|
||||
|
||||
o = s:option(Value, option_name("ws_maxEarlyData"), translate("Early data length"))
|
||||
o = s:option(Value, _n("ws_maxEarlyData"), translate("Early data length"))
|
||||
o.default = "1024"
|
||||
o:depends({ [option_name("ws_enableEarlyData")] = true })
|
||||
o:depends({ [_n("ws_enableEarlyData")] = true })
|
||||
|
||||
o = s:option(Value, option_name("ws_earlyDataHeaderName"), translate("Early data header name"), translate("Recommended value: Sec-WebSocket-Protocol"))
|
||||
o:depends({ [option_name("ws_enableEarlyData")] = true })
|
||||
o = s:option(Value, _n("ws_earlyDataHeaderName"), translate("Early data header name"), translate("Recommended value: Sec-WebSocket-Protocol"))
|
||||
o:depends({ [_n("ws_enableEarlyData")] = true })
|
||||
|
||||
-- [[ HTTPUpgrade部分 ]]--
|
||||
o = s:option(Value, option_name("httpupgrade_host"), translate("HTTPUpgrade Host"))
|
||||
o:depends({ [option_name("transport")] = "httpupgrade" })
|
||||
o = s:option(Value, _n("httpupgrade_host"), translate("HTTPUpgrade Host"))
|
||||
o:depends({ [_n("transport")] = "httpupgrade" })
|
||||
|
||||
o = s:option(Value, option_name("httpupgrade_path"), translate("HTTPUpgrade Path"))
|
||||
o = s:option(Value, _n("httpupgrade_path"), translate("HTTPUpgrade Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("transport")] = "httpupgrade" })
|
||||
o:depends({ [_n("transport")] = "httpupgrade" })
|
||||
|
||||
-- [[ gRPC部分 ]]--
|
||||
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
|
||||
o:depends({ [option_name("transport")] = "grpc" })
|
||||
o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
|
||||
o:depends({ [_n("transport")] = "grpc" })
|
||||
|
||||
o = s:option(Flag, option_name("grpc_health_check"), translate("Health check"))
|
||||
o:depends({ [option_name("transport")] = "grpc" })
|
||||
o = s:option(Flag, _n("grpc_health_check"), translate("Health check"))
|
||||
o:depends({ [_n("transport")] = "grpc" })
|
||||
|
||||
o = s:option(Value, option_name("grpc_idle_timeout"), translate("Idle timeout"))
|
||||
o = s:option(Value, _n("grpc_idle_timeout"), translate("Idle timeout"))
|
||||
o.default = "10"
|
||||
o:depends({ [option_name("grpc_health_check")] = true })
|
||||
o:depends({ [_n("grpc_health_check")] = true })
|
||||
|
||||
o = s:option(Value, option_name("grpc_health_check_timeout"), translate("Health check timeout"))
|
||||
o = s:option(Value, _n("grpc_health_check_timeout"), translate("Health check timeout"))
|
||||
o.default = "20"
|
||||
o:depends({ [option_name("grpc_health_check")] = true })
|
||||
o:depends({ [_n("grpc_health_check")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("grpc_permit_without_stream"), translate("Permit without stream"))
|
||||
o = s:option(Flag, _n("grpc_permit_without_stream"), translate("Permit without stream"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("grpc_health_check")] = true })
|
||||
o:depends({ [_n("grpc_health_check")] = true })
|
||||
|
||||
-- [[ Mux ]]--
|
||||
o = s:option(Flag, option_name("mux"), translate("Mux"))
|
||||
o = s:option(Flag, _n("mux"), translate("Mux"))
|
||||
o.rmempty = false
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("uot")] = "" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks", [_n("uot")] = "" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
o = s:option(ListValue, option_name("mux_type"), translate("Mux"))
|
||||
o = s:option(ListValue, _n("mux_type"), translate("Mux"))
|
||||
o:value("smux")
|
||||
o:value("yamux")
|
||||
o:value("h2mux")
|
||||
o:depends({ [option_name("mux")] = true })
|
||||
o:depends({ [_n("mux")] = true })
|
||||
|
||||
o = s:option(Value, option_name("mux_concurrency"), translate("Mux concurrency"))
|
||||
o = s:option(Value, _n("mux_concurrency"), translate("Mux concurrency"))
|
||||
o.default = 4
|
||||
o:depends({ [option_name("mux")] = true, [option_name("tcpbrutal")] = false })
|
||||
o:depends({ [_n("mux")] = true, [_n("tcpbrutal")] = false })
|
||||
|
||||
o = s:option(Flag, option_name("mux_padding"), translate("Padding"))
|
||||
o = s:option(Flag, _n("mux_padding"), translate("Padding"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("mux")] = true })
|
||||
o:depends({ [_n("mux")] = true })
|
||||
|
||||
-- [[ TCP Brutal ]]--
|
||||
o = s:option(Flag, option_name("tcpbrutal"), translate("TCP Brutal"))
|
||||
o = s:option(Flag, _n("tcpbrutal"), translate("TCP Brutal"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("mux")] = true })
|
||||
o:depends({ [_n("mux")] = true })
|
||||
|
||||
o = s:option(Value, option_name("tcpbrutal_up_mbps"), translate("Max upload Mbps"))
|
||||
o = s:option(Value, _n("tcpbrutal_up_mbps"), translate("Max upload Mbps"))
|
||||
o.default = "10"
|
||||
o:depends({ [option_name("tcpbrutal")] = true })
|
||||
o:depends({ [_n("tcpbrutal")] = true })
|
||||
|
||||
o = s:option(Value, option_name("tcpbrutal_down_mbps"), translate("Max download Mbps"))
|
||||
o = s:option(Value, _n("tcpbrutal_down_mbps"), translate("Max download Mbps"))
|
||||
o.default = "50"
|
||||
o:depends({ [option_name("tcpbrutal")] = true })
|
||||
o:depends({ [_n("tcpbrutal")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("shadowtls"), "ShadowTLS")
|
||||
o = s:option(Flag, _n("shadowtls"), "ShadowTLS")
|
||||
o.default = 0
|
||||
o:depends({ [option_name("protocol")] = "vmess", [option_name("tls")] = false })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("tls")] = false })
|
||||
o:depends({ [_n("protocol")] = "vmess", [_n("tls")] = false })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks", [_n("tls")] = false })
|
||||
|
||||
o = s:option(ListValue, option_name("shadowtls_version"), "ShadowTLS " .. translate("Version"))
|
||||
o = s:option(ListValue, _n("shadowtls_version"), "ShadowTLS " .. translate("Version"))
|
||||
o.default = "1"
|
||||
o:value("1", "ShadowTLS v1")
|
||||
o:value("2", "ShadowTLS v2")
|
||||
o:value("3", "ShadowTLS v3")
|
||||
o:depends({ [option_name("shadowtls")] = true })
|
||||
o:depends({ [_n("shadowtls")] = true })
|
||||
|
||||
o = s:option(Value, option_name("shadowtls_password"), "ShadowTLS " .. translate("Password"))
|
||||
o = s:option(Value, _n("shadowtls_password"), "ShadowTLS " .. translate("Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_version")] = "2" })
|
||||
o:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_version")] = "3" })
|
||||
o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_version")] = "2" })
|
||||
o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_version")] = "3" })
|
||||
|
||||
o = s:option(Value, option_name("shadowtls_serverName"), "ShadowTLS " .. translate("Domain"))
|
||||
o:depends({ [option_name("shadowtls")] = true })
|
||||
o = s:option(Value, _n("shadowtls_serverName"), "ShadowTLS " .. translate("Domain"))
|
||||
o:depends({ [_n("shadowtls")] = true })
|
||||
|
||||
if singbox_tags:find("with_utls") then
|
||||
o = s:option(Flag, option_name("shadowtls_utls"), "ShadowTLS " .. translate("uTLS"))
|
||||
o = s:option(Flag, _n("shadowtls_utls"), "ShadowTLS " .. translate("uTLS"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("shadowtls")] = true })
|
||||
o:depends({ [_n("shadowtls")] = true })
|
||||
|
||||
o = s:option(ListValue, option_name("shadowtls_fingerprint"), "ShadowTLS " .. translate("Finger Print"))
|
||||
o = s:option(ListValue, _n("shadowtls_fingerprint"), "ShadowTLS " .. translate("Finger Print"))
|
||||
o:value("chrome")
|
||||
o:value("firefox")
|
||||
o:value("edge")
|
||||
@@ -641,62 +638,62 @@ if singbox_tags:find("with_utls") then
|
||||
o:value("random")
|
||||
-- o:value("randomized")
|
||||
o.default = "chrome"
|
||||
o:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_utls")] = true })
|
||||
o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_utls")] = true })
|
||||
end
|
||||
|
||||
-- [[ SIP003 plugin ]]--
|
||||
o = s:option(Flag, option_name("plugin_enabled"), translate("plugin"))
|
||||
o = s:option(Flag, _n("plugin_enabled"), translate("plugin"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(ListValue, option_name("plugin"), "SIP003 " .. translate("plugin"))
|
||||
o = s:option(ListValue, _n("plugin"), "SIP003 " .. translate("plugin"))
|
||||
o.default = "obfs-local"
|
||||
o:depends({ [option_name("plugin_enabled")] = true })
|
||||
o:depends({ [_n("plugin_enabled")] = true })
|
||||
o:value("obfs-local")
|
||||
o:value("v2ray-plugin")
|
||||
|
||||
o = s:option(Value, option_name("plugin_opts"), translate("opts"))
|
||||
o:depends({ [option_name("plugin_enabled")] = true })
|
||||
o = s:option(Value, _n("plugin_opts"), translate("opts"))
|
||||
o:depends({ [_n("plugin_enabled")] = true })
|
||||
|
||||
o = s:option(ListValue, option_name("domain_strategy"), translate("Domain Strategy"), translate("If is domain name, The requested domain name will be resolved to IP before connect."))
|
||||
o = s:option(ListValue, _n("domain_strategy"), translate("Domain Strategy"), translate("If is domain name, The requested domain name will be resolved to IP before connect."))
|
||||
o.default = ""
|
||||
o:value("", translate("Auto"))
|
||||
o:value("prefer_ipv4", translate("Prefer IPv4"))
|
||||
o:value("prefer_ipv6", translate("Prefer IPv6"))
|
||||
o:value("ipv4_only", translate("IPv4 Only"))
|
||||
o:value("ipv6_only", translate("IPv6 Only"))
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocksr" })
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocksr" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "wireguard" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(ListValue, option_name("chain_proxy"), translate("Chain Proxy"))
|
||||
o = s:option(ListValue, _n("chain_proxy"), translate("Chain Proxy"))
|
||||
o:value("", translate("Close(Not use)"))
|
||||
o:value("1", translate("Preproxy Node"))
|
||||
o:value("2", translate("Landing Node"))
|
||||
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do
|
||||
for i, v in ipairs(s.fields[_n("protocol")].keylist) do
|
||||
if not v:find("_") then
|
||||
o:depends({ [option_name("protocol")] = v })
|
||||
o:depends({ [_n("protocol")] = v })
|
||||
end
|
||||
end
|
||||
|
||||
o = s:option(ListValue, option_name("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
|
||||
o:depends({ [option_name("chain_proxy")] = "1" })
|
||||
o = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
|
||||
o:depends({ [_n("chain_proxy")] = "1" })
|
||||
|
||||
o = s:option(ListValue, option_name("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
|
||||
o:depends({ [option_name("chain_proxy")] = "2" })
|
||||
o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
|
||||
o:depends({ [_n("chain_proxy")] = "2" })
|
||||
|
||||
for k, v in pairs(nodes_table) do
|
||||
if v.type == "sing-box" and v.id ~= arg[1] then
|
||||
s.fields[option_name("preproxy_node")]:value(v.id, v.remark)
|
||||
s.fields[option_name("to_node")]:value(v.id, v.remark)
|
||||
s.fields[_n("preproxy_node")]:value(v.id, v.remark)
|
||||
s.fields[_n("to_node")]:value(v.id, v.remark)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+12
-12
@@ -10,7 +10,7 @@ local type_name = "SS-Rust"
|
||||
|
||||
local option_prefix = "ssrust_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -24,34 +24,34 @@ local ssrust_encrypt_method_list = {
|
||||
|
||||
s.fields["type"]:value(type_name, translate("Shadowsocks Rust"))
|
||||
|
||||
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)"))
|
||||
o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Port"))
|
||||
o = s:option(Value, _n("port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
|
||||
o = s:option(Value, option_name("method"), translate("Encrypt Method"))
|
||||
o = s:option(Value, _n("method"), translate("Encrypt Method"))
|
||||
for a, t in ipairs(ssrust_encrypt_method_list) do o:value(t) end
|
||||
|
||||
o = s:option(Value, option_name("timeout"), translate("Connection Timeout"))
|
||||
o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 300
|
||||
|
||||
o = s:option(ListValue, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
|
||||
o = s:option(ListValue, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
|
||||
o:value("false")
|
||||
o:value("true")
|
||||
|
||||
o = s:option(ListValue, option_name("plugin"), translate("plugin"))
|
||||
o = s:option(ListValue, _n("plugin"), translate("plugin"))
|
||||
o:value("none", translate("none"))
|
||||
if api.is_finded("xray-plugin") then o:value("xray-plugin") end
|
||||
if api.is_finded("v2ray-plugin") then o:value("v2ray-plugin") end
|
||||
if api.is_finded("obfs-local") then o:value("obfs-local") end
|
||||
|
||||
o = s:option(Value, option_name("plugin_opts"), translate("opts"))
|
||||
o:depends({ [option_name("plugin")] = "xray-plugin"})
|
||||
o:depends({ [option_name("plugin")] = "v2ray-plugin"})
|
||||
o:depends({ [option_name("plugin")] = "obfs-local"})
|
||||
o = s:option(Value, _n("plugin_opts"), translate("opts"))
|
||||
o:depends({ [_n("plugin")] = "xray-plugin"})
|
||||
o:depends({ [_n("plugin")] = "v2ray-plugin"})
|
||||
o:depends({ [_n("plugin")] = "obfs-local"})
|
||||
|
||||
api.luci_types(arg[1], m, s, type_name, option_prefix)
|
||||
|
||||
@@ -10,7 +10,7 @@ local type_name = "SS"
|
||||
|
||||
local option_prefix = "ss_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -25,34 +25,34 @@ local ss_encrypt_method_list = {
|
||||
|
||||
s.fields["type"]:value(type_name, translate("Shadowsocks Libev"))
|
||||
|
||||
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)"))
|
||||
o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Port"))
|
||||
o = s:option(Value, _n("port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
|
||||
o = s:option(Value, option_name("method"), translate("Encrypt Method"))
|
||||
o = s:option(Value, _n("method"), translate("Encrypt Method"))
|
||||
for a, t in ipairs(ss_encrypt_method_list) do o:value(t) end
|
||||
|
||||
o = s:option(Value, option_name("timeout"), translate("Connection Timeout"))
|
||||
o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 300
|
||||
|
||||
o = s:option(ListValue, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
|
||||
o = s:option(ListValue, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
|
||||
o:value("false")
|
||||
o:value("true")
|
||||
|
||||
o = s:option(ListValue, option_name("plugin"), translate("plugin"))
|
||||
o = s:option(ListValue, _n("plugin"), translate("plugin"))
|
||||
o:value("none", translate("none"))
|
||||
if api.is_finded("xray-plugin") then o:value("xray-plugin") end
|
||||
if api.is_finded("v2ray-plugin") then o:value("v2ray-plugin") end
|
||||
if api.is_finded("obfs-local") then o:value("obfs-local") end
|
||||
|
||||
o = s:option(Value, option_name("plugin_opts"), translate("opts"))
|
||||
o:depends({ [option_name("plugin")] = "xray-plugin"})
|
||||
o:depends({ [option_name("plugin")] = "v2ray-plugin"})
|
||||
o:depends({ [option_name("plugin")] = "obfs-local"})
|
||||
o = s:option(Value, _n("plugin_opts"), translate("opts"))
|
||||
o:depends({ [_n("plugin")] = "xray-plugin"})
|
||||
o:depends({ [_n("plugin")] = "v2ray-plugin"})
|
||||
o:depends({ [_n("plugin")] = "obfs-local"})
|
||||
|
||||
api.luci_types(arg[1], m, s, type_name, option_prefix)
|
||||
|
||||
@@ -10,7 +10,7 @@ local type_name = "SSR"
|
||||
|
||||
local option_prefix = "ssr_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -37,32 +37,32 @@ local ssr_obfs_list = {
|
||||
|
||||
s.fields["type"]:value(type_name, translate("ShadowsocksR Libev"))
|
||||
|
||||
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)"))
|
||||
o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Port"))
|
||||
o = s:option(Value, _n("port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
|
||||
o = s:option(ListValue, option_name("method"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
|
||||
for a, t in ipairs(ssr_encrypt_method_list) do o:value(t) end
|
||||
|
||||
o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
|
||||
o = s:option(ListValue, _n("protocol"), translate("Protocol"))
|
||||
for a, t in ipairs(ssr_protocol_list) do o:value(t) end
|
||||
|
||||
o = s:option(Value, option_name("protocol_param"), translate("Protocol_param"))
|
||||
o = s:option(Value, _n("protocol_param"), translate("Protocol_param"))
|
||||
|
||||
o = s:option(ListValue, option_name("obfs"), translate("Obfs"))
|
||||
o = s:option(ListValue, _n("obfs"), translate("Obfs"))
|
||||
for a, t in ipairs(ssr_obfs_list) do o:value(t) end
|
||||
|
||||
o = s:option(Value, option_name("obfs_param"), translate("Obfs_param"))
|
||||
o = s:option(Value, _n("obfs_param"), translate("Obfs_param"))
|
||||
|
||||
o = s:option(Value, option_name("timeout"), translate("Connection Timeout"))
|
||||
o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 300
|
||||
|
||||
o = s:option(ListValue, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
|
||||
o = s:option(ListValue, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
|
||||
o:value("false")
|
||||
o:value("true")
|
||||
|
||||
|
||||
+12
-12
@@ -10,7 +10,7 @@ local type_name = "Trojan-Plus"
|
||||
|
||||
local option_prefix = "trojan_plus_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -18,19 +18,19 @@ end
|
||||
|
||||
s.fields["type"]:value(type_name, "Trojan-Plus")
|
||||
|
||||
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)"))
|
||||
o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Port"))
|
||||
o = s:option(Value, _n("port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
|
||||
o = s:option(ListValue, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
|
||||
o = s:option(ListValue, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
|
||||
o:value("false")
|
||||
o:value("true")
|
||||
|
||||
o = s:option(Flag, option_name("tls"), translate("TLS"))
|
||||
o = s:option(Flag, _n("tls"), translate("TLS"))
|
||||
o.default = 0
|
||||
o.validate = function(self, value, t)
|
||||
if value then
|
||||
@@ -42,15 +42,15 @@ o.validate = function(self, value, t)
|
||||
end
|
||||
end
|
||||
|
||||
o = s:option(Flag, option_name("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
|
||||
o = s:option(Flag, _n("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o:depends({ [_n("tls")] = true })
|
||||
|
||||
o = s:option(Value, option_name("tls_serverName"), translate("Domain"))
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o = s:option(Value, _n("tls_serverName"), translate("Domain"))
|
||||
o:depends({ [_n("tls")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("tls_sessionTicket"), translate("Session Ticket"))
|
||||
o = s:option(Flag, _n("tls_sessionTicket"), translate("Session Ticket"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o:depends({ [_n("tls")] = true })
|
||||
|
||||
api.luci_types(arg[1], m, s, type_name, option_prefix)
|
||||
|
||||
@@ -10,7 +10,7 @@ local type_name = "TUIC"
|
||||
|
||||
local option_prefix = "tuic_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -18,16 +18,16 @@ end
|
||||
|
||||
s.fields["type"]:value(type_name, translate("TUIC"))
|
||||
|
||||
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)"))
|
||||
o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Port"))
|
||||
o = s:option(Value, _n("port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, option_name("uuid"), translate("ID"))
|
||||
o = s:option(Value, _n("uuid"), translate("ID"))
|
||||
o.password = true
|
||||
|
||||
-- Tuic Password for remote server connect
|
||||
o = s:option(Value, option_name("password"), translate("TUIC User Password For Connect Remote Server"))
|
||||
o = s:option(Value, _n("password"), translate("TUIC User Password For Connect Remote Server"))
|
||||
o.password = true
|
||||
o.rmempty = true
|
||||
o.default = ""
|
||||
@@ -35,32 +35,32 @@ o.rewrite_option = o.option
|
||||
|
||||
--[[
|
||||
-- Tuic username for local socks connect
|
||||
o = s:option(Value, option_name("socks_username"), translate("TUIC UserName For Local Socks"))
|
||||
o = s:option(Value, _n("socks_username"), translate("TUIC UserName For Local Socks"))
|
||||
o.rmempty = true
|
||||
o.default = ""
|
||||
o.rewrite_option = o.option
|
||||
|
||||
-- Tuic Password for local socks connect
|
||||
o = s:option(Value, option_name("socks_password"), translate("TUIC Password For Local Socks"))
|
||||
o = s:option(Value, _n("socks_password"), translate("TUIC Password For Local Socks"))
|
||||
o.password = true
|
||||
o.rmempty = true
|
||||
o.default = ""
|
||||
o.rewrite_option = o.option
|
||||
--]]
|
||||
|
||||
o = s:option(Value, option_name("ip"), translate("Set the TUIC proxy server ip address"))
|
||||
o = s:option(Value, _n("ip"), translate("Set the TUIC proxy server ip address"))
|
||||
o.datatype = "ipaddr"
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(ListValue, option_name("udp_relay_mode"), translate("UDP relay mode"))
|
||||
o = s:option(ListValue, _n("udp_relay_mode"), translate("UDP relay mode"))
|
||||
o:value("native", translate("native"))
|
||||
o:value("quic", translate("QUIC"))
|
||||
o.default = "native"
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(ListValue, option_name("congestion_control"), translate("Congestion control algorithm"))
|
||||
o = s:option(ListValue, _n("congestion_control"), translate("Congestion control algorithm"))
|
||||
o:value("bbr", translate("BBR"))
|
||||
o:value("cubic", translate("CUBIC"))
|
||||
o:value("new_reno", translate("New Reno"))
|
||||
@@ -68,65 +68,65 @@ o.default = "cubic"
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("heartbeat"), translate("Heartbeat interval(second)"))
|
||||
o = s:option(Value, _n("heartbeat"), translate("Heartbeat interval(second)"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = "3"
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("timeout"), translate("Timeout for establishing a connection to server(second)"))
|
||||
o = s:option(Value, _n("timeout"), translate("Timeout for establishing a connection to server(second)"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = "8"
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("gc_interval"), translate("Garbage collection interval(second)"))
|
||||
o = s:option(Value, _n("gc_interval"), translate("Garbage collection interval(second)"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = "3"
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("gc_lifetime"), translate("Garbage collection lifetime(second)"))
|
||||
o = s:option(Value, _n("gc_lifetime"), translate("Garbage collection lifetime(second)"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = "15"
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("send_window"), translate("TUIC send window"))
|
||||
o = s:option(Value, _n("send_window"), translate("TUIC send window"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 20971520
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("receive_window"), translate("TUIC receive window"))
|
||||
o = s:option(Value, _n("receive_window"), translate("TUIC receive window"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 10485760
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("max_package_size"), translate("TUIC Maximum packet size the socks5 server can receive from external, in bytes"))
|
||||
o = s:option(Value, _n("max_package_size"), translate("TUIC Maximum packet size the socks5 server can receive from external, in bytes"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 1500
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
--Tuic settings for the local inbound socks5 server
|
||||
o = s:option(Flag, option_name("dual_stack"), translate("Set if the listening socket should be dual-stack"))
|
||||
o = s:option(Flag, _n("dual_stack"), translate("Set if the listening socket should be dual-stack"))
|
||||
o.default = 0
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Flag, option_name("disable_sni"), translate("Disable SNI"))
|
||||
o = s:option(Flag, _n("disable_sni"), translate("Disable SNI"))
|
||||
o.default = 0
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Flag, option_name("zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
|
||||
o = s:option(Flag, _n("zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
|
||||
o.default = 0
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(DynamicList, option_name("tls_alpn"), translate("TLS ALPN"))
|
||||
o = s:option(DynamicList, _n("tls_alpn"), translate("TLS ALPN"))
|
||||
o.rmempty = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
|
||||
+11
-11
@@ -10,7 +10,7 @@ local type_name = "Hysteria2"
|
||||
|
||||
local option_prefix = "hysteria2_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -18,31 +18,31 @@ end
|
||||
|
||||
s.fields["type"]:value(type_name, "Hysteria2")
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Listen Port"))
|
||||
o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, option_name("obfs"), translate("Obfs Password"))
|
||||
o = s:option(Value, _n("obfs"), translate("Obfs Password"))
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("auth_password"), translate("Auth Password"))
|
||||
o = s:option(Value, _n("auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Flag, option_name("udp"), translate("UDP"))
|
||||
o = s:option(Flag, _n("udp"), translate("UDP"))
|
||||
o.default = "1"
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("up_mbps"), translate("Max upload Mbps"))
|
||||
o = s:option(Value, _n("up_mbps"), translate("Max upload Mbps"))
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Value, option_name("down_mbps"), translate("Max download Mbps"))
|
||||
o = s:option(Value, _n("down_mbps"), translate("Max download Mbps"))
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(Flag, option_name("ignoreClientBandwidth"), translate("ignoreClientBandwidth"))
|
||||
o = s:option(Flag, _n("ignoreClientBandwidth"), translate("ignoreClientBandwidth"))
|
||||
o.default = "0"
|
||||
o.rewrite_option = o.option
|
||||
|
||||
o = s:option(FileUpload, option_name("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
|
||||
o = s:option(FileUpload, _n("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
|
||||
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
@@ -55,7 +55,7 @@ o.validate = function(self, value, t)
|
||||
return nil
|
||||
end
|
||||
|
||||
o = s:option(FileUpload, option_name("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
|
||||
o = s:option(FileUpload, _n("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
|
||||
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
@@ -68,7 +68,7 @@ o.validate = function(self, value, t)
|
||||
return nil
|
||||
end
|
||||
|
||||
o = s:option(Flag, option_name("log"), translate("Log"))
|
||||
o = s:option(Flag, _n("log"), translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
|
||||
+158
-159
@@ -10,7 +10,7 @@ local type_name = "Xray"
|
||||
|
||||
local option_prefix = "xray_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -26,7 +26,7 @@ local header_type_list = {
|
||||
|
||||
s.fields["type"]:value(type_name, "Xray")
|
||||
|
||||
o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
|
||||
o = s:option(ListValue, _n("protocol"), translate("Protocol"))
|
||||
o:value("vmess", "Vmess")
|
||||
o:value("vless", "VLESS")
|
||||
o:value("http", "HTTP")
|
||||
@@ -35,91 +35,91 @@ o:value("shadowsocks", "Shadowsocks")
|
||||
o:value("trojan", "Trojan")
|
||||
o:value("dokodemo-door", "dokodemo-door")
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Listen Port"))
|
||||
o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Flag, option_name("auth"), translate("Auth"))
|
||||
o = s:option(Flag, _n("auth"), translate("Auth"))
|
||||
o.validate = function(self, value, t)
|
||||
if value and value == "1" then
|
||||
local user_v = s.fields[option_name("username")] and s.fields[option_name("username")]:formvalue(t) or ""
|
||||
local pass_v = s.fields[option_name("password")] and s.fields[option_name("password")]:formvalue(t) or ""
|
||||
local user_v = s.fields[_n("username")] and s.fields[_n("username")]:formvalue(t) or ""
|
||||
local pass_v = s.fields[_n("password")] and s.fields[_n("password")]:formvalue(t) or ""
|
||||
if user_v == "" or pass_v == "" then
|
||||
return nil, translate("Username and Password must be used together!")
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
|
||||
o = s:option(Value, option_name("username"), translate("Username"))
|
||||
o:depends({ [option_name("auth")] = true })
|
||||
o = s:option(Value, _n("username"), translate("Username"))
|
||||
o:depends({ [_n("auth")] = true })
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("auth")] = true })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("auth")] = true })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(ListValue, option_name("d_protocol"), translate("Destination protocol"))
|
||||
o = s:option(ListValue, _n("d_protocol"), translate("Destination protocol"))
|
||||
o:value("tcp", "TCP")
|
||||
o:value("udp", "UDP")
|
||||
o:value("tcp,udp", "TCP,UDP")
|
||||
o:depends({ [option_name("protocol")] = "dokodemo-door" })
|
||||
o:depends({ [_n("protocol")] = "dokodemo-door" })
|
||||
|
||||
o = s:option(Value, option_name("d_address"), translate("Destination address"))
|
||||
o:depends({ [option_name("protocol")] = "dokodemo-door" })
|
||||
o = s:option(Value, _n("d_address"), translate("Destination address"))
|
||||
o:depends({ [_n("protocol")] = "dokodemo-door" })
|
||||
|
||||
o = s:option(Value, option_name("d_port"), translate("Destination port"))
|
||||
o = s:option(Value, _n("d_port"), translate("Destination port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ [option_name("protocol")] = "dokodemo-door" })
|
||||
o:depends({ [_n("protocol")] = "dokodemo-door" })
|
||||
|
||||
o = s:option(Value, option_name("decryption"), translate("Encrypt Method"))
|
||||
o = s:option(Value, _n("decryption"), translate("Encrypt Method"))
|
||||
o.default = "none"
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
|
||||
o = s:option(ListValue, option_name("x_ss_method"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("x_ss_method"), translate("Encrypt Method"))
|
||||
o.rewrite_option = "method"
|
||||
for a, t in ipairs(x_ss_method_list) do o:value(t) end
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(Flag, option_name("iv_check"), translate("IV Check"))
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o = s:option(Flag, _n("iv_check"), translate("IV Check"))
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(ListValue, option_name("ss_network"), translate("Transport"))
|
||||
o = s:option(ListValue, _n("ss_network"), translate("Transport"))
|
||||
o.default = "tcp,udp"
|
||||
o:value("tcp", "TCP")
|
||||
o:value("udp", "UDP")
|
||||
o:value("tcp,udp", "TCP,UDP")
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(Flag, option_name("udp_forward"), translate("UDP Forward"))
|
||||
o = s:option(Flag, _n("udp_forward"), translate("UDP Forward"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
|
||||
o = s:option(DynamicList, option_name("uuid"), translate("ID") .. "/" .. translate("Password"))
|
||||
o = s:option(DynamicList, _n("uuid"), translate("ID") .. "/" .. translate("Password"))
|
||||
for i = 1, 3 do
|
||||
o:value(api.gen_uuid(1))
|
||||
end
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
o = s:option(ListValue, option_name("flow"), translate("flow"))
|
||||
o = s:option(ListValue, _n("flow"), translate("flow"))
|
||||
o.default = ""
|
||||
o:value("", translate("Disable"))
|
||||
o:value("xtls-rprx-vision")
|
||||
o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true, [option_name("transport")] = "raw" })
|
||||
o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true, [_n("transport")] = "raw" })
|
||||
|
||||
o = s:option(Flag, option_name("tls"), translate("TLS"))
|
||||
o = s:option(Flag, _n("tls"), translate("TLS"))
|
||||
o.default = 0
|
||||
o.validate = function(self, value, t)
|
||||
if value then
|
||||
local reality = s.fields[option_name("reality")] and s.fields[option_name("reality")]:formvalue(t) or nil
|
||||
local reality = s.fields[_n("reality")] and s.fields[_n("reality")]:formvalue(t) or nil
|
||||
if reality and reality == "1" then return value end
|
||||
if value == "1" then
|
||||
local ca = s.fields[option_name("tls_certificateFile")] and s.fields[option_name("tls_certificateFile")]:formvalue(t) or ""
|
||||
local key = s.fields[option_name("tls_keyFile")] and s.fields[option_name("tls_keyFile")]:formvalue(t) or ""
|
||||
local ca = s.fields[_n("tls_certificateFile")] and s.fields[_n("tls_certificateFile")]:formvalue(t) or ""
|
||||
local key = s.fields[_n("tls_keyFile")] and s.fields[_n("tls_keyFile")]:formvalue(t) or ""
|
||||
if ca == "" or key == "" then
|
||||
return nil, translate("Public key and Private key path can not be empty!")
|
||||
end
|
||||
@@ -127,32 +127,32 @@ o.validate = function(self, value, t)
|
||||
return value
|
||||
end
|
||||
end
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
-- [[ REALITY部分 ]] --
|
||||
o = s:option(Flag, option_name("reality"), translate("REALITY"))
|
||||
o = s:option(Flag, _n("reality"), translate("REALITY"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o:depends({ [_n("tls")] = true })
|
||||
|
||||
o = s:option(Value, option_name("reality_private_key"), translate("Private Key"))
|
||||
o:depends({ [option_name("reality")] = true })
|
||||
o = s:option(Value, _n("reality_private_key"), translate("Private Key"))
|
||||
o:depends({ [_n("reality")] = true })
|
||||
|
||||
o = s:option(DynamicList, option_name("reality_shortId"), translate("Short Id"))
|
||||
o:depends({ [option_name("reality")] = true })
|
||||
o = s:option(DynamicList, _n("reality_shortId"), translate("Short Id"))
|
||||
o:depends({ [_n("reality")] = true })
|
||||
|
||||
o = s:option(Value, option_name("reality_dest"), translate("Dest"))
|
||||
o = s:option(Value, _n("reality_dest"), translate("Dest"))
|
||||
o.default = "google.com:443"
|
||||
o:depends({ [option_name("reality")] = true })
|
||||
o:depends({ [_n("reality")] = true })
|
||||
|
||||
o = s:option(Value, option_name("reality_serverNames"), translate("serverNames"))
|
||||
o:depends({ [option_name("reality")] = true })
|
||||
o = s:option(Value, _n("reality_serverNames"), translate("serverNames"))
|
||||
o:depends({ [_n("reality")] = true })
|
||||
|
||||
o = s:option(ListValue, option_name("alpn"), translate("alpn"))
|
||||
o = s:option(ListValue, _n("alpn"), translate("alpn"))
|
||||
o.default = "h2,http/1.1"
|
||||
o:value("h3")
|
||||
o:value("h2")
|
||||
@@ -160,18 +160,18 @@ o:value("h3,h2")
|
||||
o:value("http/1.1")
|
||||
o:value("h2,http/1.1")
|
||||
o:value("h3,h2,http/1.1")
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o:depends({ [_n("tls")] = true })
|
||||
|
||||
-- o = s:option(Value, option_name("minversion"), translate("minversion"))
|
||||
-- o = s:option(Value, _n("minversion"), translate("minversion"))
|
||||
-- o.default = "1.3"
|
||||
-- o:value("1.3")
|
||||
--o:depends({ [option_name("tls")] = true })
|
||||
--o:depends({ [_n("tls")] = true })
|
||||
|
||||
-- [[ TLS部分 ]] --
|
||||
|
||||
o = s:option(FileUpload, option_name("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
|
||||
o = s:option(FileUpload, _n("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
|
||||
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not nixio.fs.access(value) then
|
||||
@@ -183,9 +183,9 @@ o.validate = function(self, value, t)
|
||||
return nil
|
||||
end
|
||||
|
||||
o = s:option(FileUpload, option_name("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
|
||||
o = s:option(FileUpload, _n("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
|
||||
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not nixio.fs.access(value) then
|
||||
@@ -197,7 +197,7 @@ o.validate = function(self, value, t)
|
||||
return nil
|
||||
end
|
||||
|
||||
o = s:option(ListValue, option_name("transport"), translate("Transport"))
|
||||
o = s:option(ListValue, _n("transport"), translate("Transport"))
|
||||
o:value("raw", "RAW")
|
||||
o:value("mkcp", "mKCP")
|
||||
o:value("ws", "WebSocket")
|
||||
@@ -207,157 +207,157 @@ o:value("quic", "QUIC")
|
||||
o:value("grpc", "gRPC")
|
||||
o:value("httpupgrade", "HttpUpgrade")
|
||||
o:value("xhttp", "XHTTP")
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
-- [[ WebSocket部分 ]]--
|
||||
|
||||
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
|
||||
o:depends({ [option_name("transport")] = "ws" })
|
||||
o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
|
||||
o:depends({ [_n("transport")] = "ws" })
|
||||
|
||||
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path"))
|
||||
o:depends({ [option_name("transport")] = "ws" })
|
||||
o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
|
||||
o:depends({ [_n("transport")] = "ws" })
|
||||
|
||||
-- [[ HttpUpgrade部分 ]]--
|
||||
o = s:option(Value, option_name("httpupgrade_host"), translate("HttpUpgrade Host"))
|
||||
o:depends({ [option_name("transport")] = "httpupgrade" })
|
||||
o = s:option(Value, _n("httpupgrade_host"), translate("HttpUpgrade Host"))
|
||||
o:depends({ [_n("transport")] = "httpupgrade" })
|
||||
|
||||
o = s:option(Value, option_name("httpupgrade_path"), translate("HttpUpgrade Path"))
|
||||
o = s:option(Value, _n("httpupgrade_path"), translate("HttpUpgrade Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("transport")] = "httpupgrade" })
|
||||
o:depends({ [_n("transport")] = "httpupgrade" })
|
||||
|
||||
-- [[ SplitHTTP部分 ]]--
|
||||
o = s:option(Value, option_name("xhttp_host"), translate("XHTTP Host"))
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
o = s:option(Value, _n("xhttp_host"), translate("XHTTP Host"))
|
||||
o:depends({ [_n("transport")] = "xhttp" })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_path"), translate("XHTTP Path"))
|
||||
o = s:option(Value, _n("xhttp_path"), translate("XHTTP Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
o:depends({ [_n("transport")] = "xhttp" })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_maxuploadsize"), translate("maxUploadSize"))
|
||||
o = s:option(Value, _n("xhttp_maxuploadsize"), translate("maxUploadSize"))
|
||||
o.default = "1000000"
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
o:depends({ [_n("transport")] = "xhttp" })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_maxconcurrentuploads"), translate("maxConcurrentUploads"))
|
||||
o = s:option(Value, _n("xhttp_maxconcurrentuploads"), translate("maxConcurrentUploads"))
|
||||
o.default = "10"
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
o:depends({ [_n("transport")] = "xhttp" })
|
||||
|
||||
-- [[ HTTP/2部分 ]]--
|
||||
|
||||
o = s:option(Value, option_name("h2_host"), translate("HTTP/2 Host"))
|
||||
o:depends({ [option_name("transport")] = "h2" })
|
||||
o = s:option(Value, _n("h2_host"), translate("HTTP/2 Host"))
|
||||
o:depends({ [_n("transport")] = "h2" })
|
||||
|
||||
o = s:option(Value, option_name("h2_path"), translate("HTTP/2 Path"))
|
||||
o:depends({ [option_name("transport")] = "h2" })
|
||||
o = s:option(Value, _n("h2_path"), translate("HTTP/2 Path"))
|
||||
o:depends({ [_n("transport")] = "h2" })
|
||||
|
||||
-- [[ TCP部分 ]]--
|
||||
|
||||
-- TCP伪装
|
||||
o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type"))
|
||||
o = s:option(ListValue, _n("tcp_guise"), translate("Camouflage Type"))
|
||||
o:value("none", "none")
|
||||
o:value("http", "http")
|
||||
o:depends({ [option_name("transport")] = "raw" })
|
||||
o:depends({ [_n("transport")] = "raw" })
|
||||
|
||||
-- HTTP域名
|
||||
o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host"))
|
||||
o:depends({ [option_name("tcp_guise")] = "http" })
|
||||
o = s:option(DynamicList, _n("tcp_guise_http_host"), translate("HTTP Host"))
|
||||
o:depends({ [_n("tcp_guise")] = "http" })
|
||||
|
||||
-- HTTP路径
|
||||
o = s:option(DynamicList, option_name("tcp_guise_http_path"), translate("HTTP Path"))
|
||||
o:depends({ [option_name("tcp_guise")] = "http" })
|
||||
o = s:option(DynamicList, _n("tcp_guise_http_path"), translate("HTTP Path"))
|
||||
o:depends({ [_n("tcp_guise")] = "http" })
|
||||
|
||||
-- [[ mKCP部分 ]]--
|
||||
|
||||
o = s:option(ListValue, option_name("mkcp_guise"), translate("Camouflage Type"), translate('<br />none: default, no masquerade, data sent is packets with no characteristics.<br />srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br />utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br />wechat-video: packets disguised as WeChat video calls.<br />dtls: disguised as DTLS 1.2 packet.<br />wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)'))
|
||||
o = s:option(ListValue, _n("mkcp_guise"), translate("Camouflage Type"), translate('<br />none: default, no masquerade, data sent is packets with no characteristics.<br />srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br />utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br />wechat-video: packets disguised as WeChat video calls.<br />dtls: disguised as DTLS 1.2 packet.<br />wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)'))
|
||||
for a, t in ipairs(header_type_list) do o:value(t) end
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_mtu"), translate("KCP MTU"))
|
||||
o = s:option(Value, _n("mkcp_mtu"), translate("KCP MTU"))
|
||||
o.default = "1350"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_tti"), translate("KCP TTI"))
|
||||
o = s:option(Value, _n("mkcp_tti"), translate("KCP TTI"))
|
||||
o.default = "20"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity"))
|
||||
o = s:option(Value, _n("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity"))
|
||||
o.default = "5"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity"))
|
||||
o = s:option(Value, _n("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity"))
|
||||
o.default = "20"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Flag, option_name("mkcp_congestion"), translate("KCP Congestion"))
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o = s:option(Flag, _n("mkcp_congestion"), translate("KCP Congestion"))
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_readBufferSize"), translate("KCP readBufferSize"))
|
||||
o = s:option(Value, _n("mkcp_readBufferSize"), translate("KCP readBufferSize"))
|
||||
o.default = "1"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_writeBufferSize"), translate("KCP writeBufferSize"))
|
||||
o = s:option(Value, _n("mkcp_writeBufferSize"), translate("KCP writeBufferSize"))
|
||||
o.default = "1"
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
o = s:option(Value, option_name("mkcp_seed"), translate("KCP Seed"))
|
||||
o:depends({ [option_name("transport")] = "mkcp" })
|
||||
o = s:option(Value, _n("mkcp_seed"), translate("KCP Seed"))
|
||||
o:depends({ [_n("transport")] = "mkcp" })
|
||||
|
||||
-- [[ DomainSocket部分 ]]--
|
||||
|
||||
o = s:option(Value, option_name("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
|
||||
o:depends({ [option_name("transport")] = "ds" })
|
||||
o = s:option(Value, _n("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
|
||||
o:depends({ [_n("transport")] = "ds" })
|
||||
|
||||
-- [[ QUIC部分 ]]--
|
||||
o = s:option(ListValue, option_name("quic_security"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("quic_security"), translate("Encrypt Method"))
|
||||
o:value("none")
|
||||
o:value("aes-128-gcm")
|
||||
o:value("chacha20-poly1305")
|
||||
o:depends({ [option_name("transport")] = "quic" })
|
||||
o:depends({ [_n("transport")] = "quic" })
|
||||
|
||||
o = s:option(Value, option_name("quic_key"), translate("Encrypt Method") .. translate("Key"))
|
||||
o:depends({ [option_name("transport")] = "quic" })
|
||||
o = s:option(Value, _n("quic_key"), translate("Encrypt Method") .. translate("Key"))
|
||||
o:depends({ [_n("transport")] = "quic" })
|
||||
|
||||
o = s:option(ListValue, option_name("quic_guise"), translate("Camouflage Type"))
|
||||
o = s:option(ListValue, _n("quic_guise"), translate("Camouflage Type"))
|
||||
for a, t in ipairs(header_type_list) do o:value(t) end
|
||||
o:depends({ [option_name("transport")] = "quic" })
|
||||
o:depends({ [_n("transport")] = "quic" })
|
||||
|
||||
-- [[ gRPC部分 ]]--
|
||||
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
|
||||
o:depends({ [option_name("transport")] = "grpc" })
|
||||
o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
|
||||
o:depends({ [_n("transport")] = "grpc" })
|
||||
|
||||
o = s:option(Flag, option_name("acceptProxyProtocol"), translate("acceptProxyProtocol"), translate("Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used."))
|
||||
o = s:option(Flag, _n("acceptProxyProtocol"), translate("acceptProxyProtocol"), translate("Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used."))
|
||||
o.default = "0"
|
||||
|
||||
-- [[ Fallback部分 ]]--
|
||||
o = s:option(Flag, option_name("fallback"), translate("Fallback"))
|
||||
o:depends({ [option_name("protocol")] = "vless", [option_name("transport")] = "raw" })
|
||||
o:depends({ [option_name("protocol")] = "trojan", [option_name("transport")] = "raw" })
|
||||
o = s:option(Flag, _n("fallback"), translate("Fallback"))
|
||||
o:depends({ [_n("protocol")] = "vless", [_n("transport")] = "raw" })
|
||||
o:depends({ [_n("protocol")] = "trojan", [_n("transport")] = "raw" })
|
||||
|
||||
--[[
|
||||
o = s:option(Value, option_name("fallback_alpn"), "Fallback alpn")
|
||||
o:depends({ [option_name("fallback")] = true })
|
||||
o = s:option(Value, _n("fallback_alpn"), "Fallback alpn")
|
||||
o:depends({ [_n("fallback")] = true })
|
||||
|
||||
o = s:option(Value, option_name("fallback_path"), "Fallback path")
|
||||
o:depends({ [option_name("fallback")] = true })
|
||||
o = s:option(Value, _n("fallback_path"), "Fallback path")
|
||||
o:depends({ [_n("fallback")] = true })
|
||||
|
||||
o = s:option(Value, option_name("fallback_dest"), "Fallback dest")
|
||||
o:depends({ [option_name("fallback")] = true })
|
||||
o = s:option(Value, _n("fallback_dest"), "Fallback dest")
|
||||
o:depends({ [_n("fallback")] = true })
|
||||
|
||||
o = s:option(Value, option_name("fallback_xver"), "Fallback xver")
|
||||
o = s:option(Value, _n("fallback_xver"), "Fallback xver")
|
||||
o.default = 0
|
||||
o:depends({ [option_name("fallback")] = true })
|
||||
o:depends({ [_n("fallback")] = true })
|
||||
]]--
|
||||
|
||||
o = s:option(DynamicList, option_name("fallback_list"), "Fallback", translate("dest,path"))
|
||||
o:depends({ [option_name("fallback")] = true })
|
||||
o = s:option(DynamicList, _n("fallback_list"), "Fallback", translate("dest,path"))
|
||||
o:depends({ [_n("fallback")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
|
||||
o = s:option(Flag, _n("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Flag, option_name("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
|
||||
o = s:option(Flag, _n("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
|
||||
o.default = "0"
|
||||
|
||||
local nodes_table = {}
|
||||
@@ -370,46 +370,45 @@ for k, e in ipairs(api.get_valid_nodes()) do
|
||||
end
|
||||
end
|
||||
|
||||
o = s:option(ListValue, option_name("outbound_node"), translate("outbound node"))
|
||||
o:value("nil", translate("Close"))
|
||||
o = s:option(ListValue, _n("outbound_node"), translate("outbound node"))
|
||||
o:value("", translate("Close"))
|
||||
o:value("_socks", translate("Custom Socks"))
|
||||
o:value("_http", translate("Custom HTTP"))
|
||||
o:value("_iface", translate("Custom Interface"))
|
||||
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
|
||||
o.default = "nil"
|
||||
|
||||
o = s:option(Value, option_name("outbound_node_address"), translate("Address (Support Domain Name)"))
|
||||
o:depends({ [option_name("outbound_node")] = "_socks"})
|
||||
o:depends({ [option_name("outbound_node")] = "_http"})
|
||||
o = s:option(Value, _n("outbound_node_address"), translate("Address (Support Domain Name)"))
|
||||
o:depends({ [_n("outbound_node")] = "_socks"})
|
||||
o:depends({ [_n("outbound_node")] = "_http"})
|
||||
|
||||
o = s:option(Value, option_name("outbound_node_port"), translate("Port"))
|
||||
o = s:option(Value, _n("outbound_node_port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ [option_name("outbound_node")] = "_socks"})
|
||||
o:depends({ [option_name("outbound_node")] = "_http"})
|
||||
o:depends({ [_n("outbound_node")] = "_socks"})
|
||||
o:depends({ [_n("outbound_node")] = "_http"})
|
||||
|
||||
o = s:option(Value, option_name("outbound_node_username"), translate("Username"))
|
||||
o:depends({ [option_name("outbound_node")] = "_socks"})
|
||||
o:depends({ [option_name("outbound_node")] = "_http"})
|
||||
o = s:option(Value, _n("outbound_node_username"), translate("Username"))
|
||||
o:depends({ [_n("outbound_node")] = "_socks"})
|
||||
o:depends({ [_n("outbound_node")] = "_http"})
|
||||
|
||||
o = s:option(Value, option_name("outbound_node_password"), translate("Password"))
|
||||
o = s:option(Value, _n("outbound_node_password"), translate("Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("outbound_node")] = "_socks"})
|
||||
o:depends({ [option_name("outbound_node")] = "_http"})
|
||||
o:depends({ [_n("outbound_node")] = "_socks"})
|
||||
o:depends({ [_n("outbound_node")] = "_http"})
|
||||
|
||||
o = s:option(Value, option_name("outbound_node_iface"), translate("Interface"))
|
||||
o = s:option(Value, _n("outbound_node_iface"), translate("Interface"))
|
||||
o.default = "eth1"
|
||||
o:depends({ [option_name("outbound_node")] = "_iface"})
|
||||
o:depends({ [_n("outbound_node")] = "_iface"})
|
||||
|
||||
o = s:option(Flag, option_name("log"), translate("Log"))
|
||||
o = s:option(Flag, _n("log"), translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, option_name("loglevel"), translate("Log Level"))
|
||||
o = s:option(ListValue, _n("loglevel"), translate("Log Level"))
|
||||
o.default = "warning"
|
||||
o:value("debug")
|
||||
o:value("info")
|
||||
o:value("warning")
|
||||
o:value("error")
|
||||
o:depends({ [option_name("log")] = true })
|
||||
o:depends({ [_n("log")] = true })
|
||||
|
||||
api.luci_types(arg[1], m, s, type_name, option_prefix)
|
||||
|
||||
+171
-172
@@ -14,7 +14,7 @@ local type_name = "sing-box"
|
||||
|
||||
local option_prefix = "singbox_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -27,7 +27,7 @@ local ss_method_list = {
|
||||
|
||||
s.fields["type"]:value(type_name, "Sing-Box")
|
||||
|
||||
o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
|
||||
o = s:option(ListValue, _n("protocol"), translate("Protocol"))
|
||||
o:value("mixed", "Mixed")
|
||||
o:value("socks", "Socks")
|
||||
o:value("http", "HTTP")
|
||||
@@ -47,166 +47,166 @@ if singbox_tags:find("with_quic") then
|
||||
end
|
||||
o:value("direct", "Direct")
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Listen Port"))
|
||||
o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Flag, option_name("auth"), translate("Auth"))
|
||||
o = s:option(Flag, _n("auth"), translate("Auth"))
|
||||
o.validate = function(self, value, t)
|
||||
if value and value == "1" then
|
||||
local user_v = s.fields[option_name("username")] and s.fields[option_name("username")]:formvalue(t) or ""
|
||||
local pass_v = s.fields[option_name("password")] and s.fields[option_name("password")]:formvalue(t) or ""
|
||||
local user_v = s.fields[_n("username")] and s.fields[_n("username")]:formvalue(t) or ""
|
||||
local pass_v = s.fields[_n("password")] and s.fields[_n("password")]:formvalue(t) or ""
|
||||
if user_v == "" or pass_v == "" then
|
||||
return nil, translate("Username and Password must be used together!")
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
o:depends({ [option_name("protocol")] = "mixed" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "mixed" })
|
||||
o:depends({ [_n("protocol")] = "socks" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
|
||||
o = s:option(Value, option_name("username"), translate("Username"))
|
||||
o:depends({ [option_name("auth")] = true })
|
||||
o:depends({ [option_name("protocol")] = "naive" })
|
||||
o = s:option(Value, _n("username"), translate("Username"))
|
||||
o:depends({ [_n("auth")] = true })
|
||||
o:depends({ [_n("protocol")] = "naive" })
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("auth")] = true })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [option_name("protocol")] = "naive" })
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("auth")] = true })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "naive" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
|
||||
if singbox_tags:find("with_quic") then
|
||||
o = s:option(Value, option_name("hysteria_up_mbps"), translate("Max upload Mbps"))
|
||||
o = s:option(Value, _n("hysteria_up_mbps"), translate("Max upload Mbps"))
|
||||
o.default = "100"
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria_down_mbps"), translate("Max download Mbps"))
|
||||
o = s:option(Value, _n("hysteria_down_mbps"), translate("Max download Mbps"))
|
||||
o.default = "100"
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria_obfs"), translate("Obfs Password"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(ListValue, option_name("hysteria_auth_type"), translate("Auth Type"))
|
||||
o = s:option(ListValue, _n("hysteria_auth_type"), translate("Auth Type"))
|
||||
o:value("disable", translate("Disable"))
|
||||
o:value("string", translate("STRING"))
|
||||
o:value("base64", translate("BASE64"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria_auth_password"), translate("Auth Password"))
|
||||
o = s:option(Value, _n("hysteria_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "string"})
|
||||
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "base64"})
|
||||
o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "string"})
|
||||
o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "base64"})
|
||||
|
||||
o = s:option(Value, option_name("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o = s:option(Value, _n("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria_recv_window_client"), translate("QUIC connection receive window"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o = s:option(Value, _n("hysteria_recv_window_client"), translate("QUIC connection receive window"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria_max_conn_client"), translate("QUIC concurrent bidirectional streams"))
|
||||
o = s:option(Value, _n("hysteria_max_conn_client"), translate("QUIC concurrent bidirectional streams"))
|
||||
o.default = "1024"
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Flag, option_name("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o = s:option(Flag, _n("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria_alpn"), translate("QUIC TLS ALPN"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o = s:option(Value, _n("hysteria_alpn"), translate("QUIC TLS ALPN"))
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
end
|
||||
|
||||
if singbox_tags:find("with_quic") then
|
||||
o = s:option(ListValue, option_name("tuic_congestion_control"), translate("Congestion control algorithm"))
|
||||
o = s:option(ListValue, _n("tuic_congestion_control"), translate("Congestion control algorithm"))
|
||||
o.default = "cubic"
|
||||
o:value("bbr", translate("BBR"))
|
||||
o:value("cubic", translate("CUBIC"))
|
||||
o:value("new_reno", translate("New Reno"))
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
|
||||
o = s:option(Flag, option_name("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
|
||||
o = s:option(Flag, _n("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
|
||||
o = s:option(Value, option_name("tuic_heartbeat"), translate("Heartbeat interval(second)"))
|
||||
o = s:option(Value, _n("tuic_heartbeat"), translate("Heartbeat interval(second)"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = "3"
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
|
||||
o = s:option(Value, option_name("tuic_alpn"), translate("QUIC TLS ALPN"))
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o = s:option(Value, _n("tuic_alpn"), translate("QUIC TLS ALPN"))
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
end
|
||||
|
||||
if singbox_tags:find("with_quic") then
|
||||
o = s:option(Flag, option_name("hysteria2_ignore_client_bandwidth"), translate("Commands the client to use the BBR flow control algorithm"))
|
||||
o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Commands the client to use the BBR flow control algorithm"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria2_up_mbps"), translate("Max upload Mbps"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria2", [option_name("hysteria2_ignore_client_bandwidth")] = false })
|
||||
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwidth")] = false })
|
||||
|
||||
o = s:option(Value, option_name("hysteria2_down_mbps"), translate("Max download Mbps"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria2", [option_name("hysteria2_ignore_client_bandwidth")] = false })
|
||||
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwidth")] = false })
|
||||
|
||||
o = s:option(ListValue, option_name("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
|
||||
o:value("", translate("Disable"))
|
||||
o:value("salamander")
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(Value, option_name("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("protocol")] = "hysteria2"})
|
||||
o:depends({ [_n("protocol")] = "hysteria2"})
|
||||
end
|
||||
|
||||
o = s:option(ListValue, option_name("d_protocol"), translate("Destination protocol"))
|
||||
o = s:option(ListValue, _n("d_protocol"), translate("Destination protocol"))
|
||||
o:value("tcp", "TCP")
|
||||
o:value("udp", "UDP")
|
||||
o:value("tcp,udp", "TCP,UDP")
|
||||
o:depends({ [option_name("protocol")] = "direct" })
|
||||
o:depends({ [_n("protocol")] = "direct" })
|
||||
|
||||
o = s:option(Value, option_name("d_address"), translate("Destination address"))
|
||||
o:depends({ [option_name("protocol")] = "direct" })
|
||||
o = s:option(Value, _n("d_address"), translate("Destination address"))
|
||||
o:depends({ [_n("protocol")] = "direct" })
|
||||
|
||||
o = s:option(Value, option_name("d_port"), translate("Destination port"))
|
||||
o = s:option(Value, _n("d_port"), translate("Destination port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ [option_name("protocol")] = "direct" })
|
||||
o:depends({ [_n("protocol")] = "direct" })
|
||||
|
||||
o = s:option(Value, option_name("decryption"), translate("Encrypt Method"))
|
||||
o = s:option(Value, _n("decryption"), translate("Encrypt Method"))
|
||||
o.default = "none"
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
|
||||
o = s:option(ListValue, option_name("ss_method"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("ss_method"), translate("Encrypt Method"))
|
||||
o.rewrite_option = "method"
|
||||
for a, t in ipairs(ss_method_list) do o:value(t) end
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(DynamicList, option_name("uuid"), translate("ID") .. "/" .. translate("Password"))
|
||||
o = s:option(DynamicList, _n("uuid"), translate("ID") .. "/" .. translate("Password"))
|
||||
for i = 1, 3 do
|
||||
o:value(api.gen_uuid(1))
|
||||
end
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
|
||||
o = s:option(ListValue, option_name("flow"), translate("flow"))
|
||||
o = s:option(ListValue, _n("flow"), translate("flow"))
|
||||
o.default = ""
|
||||
o:value("", translate("Disable"))
|
||||
o:value("xtls-rprx-vision")
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
|
||||
o = s:option(Flag, option_name("tls"), translate("TLS"))
|
||||
o = s:option(Flag, _n("tls"), translate("TLS"))
|
||||
o.default = 0
|
||||
o.validate = function(self, value, t)
|
||||
if value then
|
||||
local reality = s.fields[option_name("reality")] and s.fields[option_name("reality")]:formvalue(t) or nil
|
||||
local reality = s.fields[_n("reality")] and s.fields[_n("reality")]:formvalue(t) or nil
|
||||
if reality and reality == "1" then return value end
|
||||
if value == "1" then
|
||||
local ca = s.fields[option_name("tls_certificateFile")] and s.fields[option_name("tls_certificateFile")]:formvalue(t) or ""
|
||||
local key = s.fields[option_name("tls_keyFile")] and s.fields[option_name("tls_keyFile")]:formvalue(t) or ""
|
||||
local ca = s.fields[_n("tls_certificateFile")] and s.fields[_n("tls_certificateFile")]:formvalue(t) or ""
|
||||
local key = s.fields[_n("tls_keyFile")] and s.fields[_n("tls_keyFile")]:formvalue(t) or ""
|
||||
if ca == "" or key == "" then
|
||||
return nil, translate("Public key and Private key path can not be empty!")
|
||||
end
|
||||
@@ -214,45 +214,45 @@ o.validate = function(self, value, t)
|
||||
return value
|
||||
end
|
||||
end
|
||||
o:depends({ [option_name("protocol")] = "http" })
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "http" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
if singbox_tags:find("with_reality_server") then
|
||||
-- [[ REALITY部分 ]] --
|
||||
o = s:option(Flag, option_name("reality"), translate("REALITY"))
|
||||
o = s:option(Flag, _n("reality"), translate("REALITY"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("protocol")] = "http", [option_name("tls")] = true })
|
||||
o:depends({ [option_name("protocol")] = "vmess", [option_name("tls")] = true })
|
||||
o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true })
|
||||
o:depends({ [option_name("protocol")] = "trojan", [option_name("tls")] = true })
|
||||
o:depends({ [_n("protocol")] = "http", [_n("tls")] = true })
|
||||
o:depends({ [_n("protocol")] = "vmess", [_n("tls")] = true })
|
||||
o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true })
|
||||
o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true })
|
||||
|
||||
o = s:option(Value, option_name("reality_private_key"), translate("Private Key"))
|
||||
o:depends({ [option_name("reality")] = true })
|
||||
o = s:option(Value, _n("reality_private_key"), translate("Private Key"))
|
||||
o:depends({ [_n("reality")] = true })
|
||||
|
||||
o = s:option(Value, option_name("reality_shortId"), translate("Short Id"))
|
||||
o:depends({ [option_name("reality")] = true })
|
||||
o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
|
||||
o:depends({ [_n("reality")] = true })
|
||||
|
||||
o = s:option(Value, option_name("reality_handshake_server"), translate("Handshake Server"))
|
||||
o = s:option(Value, _n("reality_handshake_server"), translate("Handshake Server"))
|
||||
o.default = "google.com"
|
||||
o:depends({ [option_name("reality")] = true })
|
||||
o:depends({ [_n("reality")] = true })
|
||||
|
||||
o = s:option(Value, option_name("reality_handshake_server_port"), translate("Handshake Server Port"))
|
||||
o = s:option(Value, _n("reality_handshake_server_port"), translate("Handshake Server Port"))
|
||||
o.datatype = "port"
|
||||
o.default = "443"
|
||||
o:depends({ [option_name("reality")] = true })
|
||||
o:depends({ [_n("reality")] = true })
|
||||
end
|
||||
|
||||
-- [[ TLS部分 ]] --
|
||||
|
||||
o = s:option(FileUpload, option_name("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
|
||||
o = s:option(FileUpload, _n("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
|
||||
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
|
||||
o:depends({ [option_name("protocol")] = "naive" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
|
||||
o:depends({ [_n("protocol")] = "naive" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not nixio.fs.access(value) then
|
||||
@@ -264,13 +264,13 @@ o.validate = function(self, value, t)
|
||||
return nil
|
||||
end
|
||||
|
||||
o = s:option(FileUpload, option_name("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
|
||||
o = s:option(FileUpload, _n("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
|
||||
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
|
||||
o:depends({ [option_name("protocol")] = "naive" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
|
||||
o:depends({ [_n("protocol")] = "naive" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not nixio.fs.access(value) then
|
||||
@@ -283,19 +283,19 @@ o.validate = function(self, value, t)
|
||||
end
|
||||
|
||||
if singbox_tags:find("with_ech") then
|
||||
o = s:option(Flag, option_name("ech"), translate("ECH"))
|
||||
o = s:option(Flag, _n("ech"), translate("ECH"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("tls")] = true, [option_name("flow")] = "", [option_name("reality")] = false })
|
||||
o:depends({ [option_name("protocol")] = "naive" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria" })
|
||||
o:depends({ [option_name("protocol")] = "tuic" })
|
||||
o:depends({ [option_name("protocol")] = "hysteria2" })
|
||||
o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
|
||||
o:depends({ [_n("protocol")] = "naive" })
|
||||
o:depends({ [_n("protocol")] = "hysteria" })
|
||||
o:depends({ [_n("protocol")] = "tuic" })
|
||||
o:depends({ [_n("protocol")] = "hysteria2" })
|
||||
|
||||
o = s:option(TextValue, option_name("ech_key"), translate("ECH Key"))
|
||||
o = s:option(TextValue, _n("ech_key"), translate("ECH Key"))
|
||||
o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ [option_name("ech")] = true })
|
||||
o:depends({ [_n("ech")] = true })
|
||||
o.validate = function(self, value)
|
||||
value = value:gsub("^%s+", ""):gsub("%s+$","\n"):gsub("\r\n","\n"):gsub("[ \t]*\n[ \t]*", "\n")
|
||||
value = value:gsub("^%s*\n", "")
|
||||
@@ -305,80 +305,80 @@ if singbox_tags:find("with_ech") then
|
||||
return value
|
||||
end
|
||||
|
||||
o = s:option(Flag, option_name("pq_signature_schemes_enabled"), translate("PQ signature schemes"))
|
||||
o = s:option(Flag, _n("pq_signature_schemes_enabled"), translate("PQ signature schemes"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("ech")] = true })
|
||||
o:depends({ [_n("ech")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("dynamic_record_sizing_disabled"), translate("Disable adaptive sizing of TLS records"))
|
||||
o = s:option(Flag, _n("dynamic_record_sizing_disabled"), translate("Disable adaptive sizing of TLS records"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("ech")] = true })
|
||||
o:depends({ [_n("ech")] = true })
|
||||
end
|
||||
|
||||
o = s:option(ListValue, option_name("transport"), translate("Transport"))
|
||||
o = s:option(ListValue, _n("transport"), translate("Transport"))
|
||||
o:value("tcp", "TCP")
|
||||
o:value("http", "HTTP")
|
||||
o:value("ws", "WebSocket")
|
||||
o:value("httpupgrade", "HTTPUpgrade")
|
||||
o:value("quic", "QUIC")
|
||||
o:value("grpc", "gRPC")
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
-- [[ HTTP部分 ]]--
|
||||
|
||||
o = s:option(Value, option_name("http_host"), translate("HTTP Host"))
|
||||
o:depends({ [option_name("transport")] = "http" })
|
||||
o = s:option(Value, _n("http_host"), translate("HTTP Host"))
|
||||
o:depends({ [_n("transport")] = "http" })
|
||||
|
||||
o = s:option(Value, option_name("http_path"), translate("HTTP Path"))
|
||||
o:depends({ [option_name("transport")] = "http" })
|
||||
o = s:option(Value, _n("http_path"), translate("HTTP Path"))
|
||||
o:depends({ [_n("transport")] = "http" })
|
||||
|
||||
-- [[ WebSocket部分 ]]--
|
||||
|
||||
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
|
||||
o:depends({ [option_name("transport")] = "ws" })
|
||||
o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
|
||||
o:depends({ [_n("transport")] = "ws" })
|
||||
|
||||
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path"))
|
||||
o:depends({ [option_name("transport")] = "ws" })
|
||||
o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
|
||||
o:depends({ [_n("transport")] = "ws" })
|
||||
|
||||
-- [[ HTTPUpgrade部分 ]]--
|
||||
|
||||
o = s:option(Value, option_name("httpupgrade_host"), translate("HTTPUpgrade Host"))
|
||||
o:depends({ [option_name("transport")] = "httpupgrade" })
|
||||
o = s:option(Value, _n("httpupgrade_host"), translate("HTTPUpgrade Host"))
|
||||
o:depends({ [_n("transport")] = "httpupgrade" })
|
||||
|
||||
o = s:option(Value, option_name("httpupgrade_path"), translate("HTTPUpgrade Path"))
|
||||
o:depends({ [option_name("transport")] = "httpupgrade" })
|
||||
o = s:option(Value, _n("httpupgrade_path"), translate("HTTPUpgrade Path"))
|
||||
o:depends({ [_n("transport")] = "httpupgrade" })
|
||||
|
||||
-- [[ gRPC部分 ]]--
|
||||
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
|
||||
o:depends({ [option_name("transport")] = "grpc" })
|
||||
o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
|
||||
o:depends({ [_n("transport")] = "grpc" })
|
||||
|
||||
-- [[ Mux ]]--
|
||||
o = s:option(Flag, option_name("mux"), translate("Mux"))
|
||||
o = s:option(Flag, _n("mux"), translate("Mux"))
|
||||
o.rmempty = false
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" })
|
||||
o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
o:depends({ [option_name("protocol")] = "trojan" })
|
||||
o:depends({ [_n("protocol")] = "vmess" })
|
||||
o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "" })
|
||||
o:depends({ [_n("protocol")] = "shadowsocks" })
|
||||
o:depends({ [_n("protocol")] = "trojan" })
|
||||
|
||||
-- [[ TCP Brutal ]]--
|
||||
o = s:option(Flag, option_name("tcpbrutal"), translate("TCP Brutal"))
|
||||
o = s:option(Flag, _n("tcpbrutal"), translate("TCP Brutal"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("mux")] = true })
|
||||
o:depends({ [_n("mux")] = true })
|
||||
|
||||
o = s:option(Value, option_name("tcpbrutal_up_mbps"), translate("Max upload Mbps"))
|
||||
o = s:option(Value, _n("tcpbrutal_up_mbps"), translate("Max upload Mbps"))
|
||||
o.default = "10"
|
||||
o:depends({ [option_name("tcpbrutal")] = true })
|
||||
o:depends({ [_n("tcpbrutal")] = true })
|
||||
|
||||
o = s:option(Value, option_name("tcpbrutal_down_mbps"), translate("Max download Mbps"))
|
||||
o = s:option(Value, _n("tcpbrutal_down_mbps"), translate("Max download Mbps"))
|
||||
o.default = "50"
|
||||
o:depends({ [option_name("tcpbrutal")] = true })
|
||||
o:depends({ [_n("tcpbrutal")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
|
||||
o = s:option(Flag, _n("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Flag, option_name("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
|
||||
o = s:option(Flag, _n("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
|
||||
o.default = "0"
|
||||
|
||||
local nodes_table = {}
|
||||
@@ -391,46 +391,45 @@ for k, e in ipairs(api.get_valid_nodes()) do
|
||||
end
|
||||
end
|
||||
|
||||
o = s:option(ListValue, option_name("outbound_node"), translate("outbound node"))
|
||||
o:value("nil", translate("Close"))
|
||||
o = s:option(ListValue, _n("outbound_node"), translate("outbound node"))
|
||||
o:value("", translate("Close"))
|
||||
o:value("_socks", translate("Custom Socks"))
|
||||
o:value("_http", translate("Custom HTTP"))
|
||||
o:value("_iface", translate("Custom Interface"))
|
||||
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
|
||||
o.default = "nil"
|
||||
|
||||
o = s:option(Value, option_name("outbound_node_address"), translate("Address (Support Domain Name)"))
|
||||
o:depends({ [option_name("outbound_node")] = "_socks" })
|
||||
o:depends({ [option_name("outbound_node")] = "_http" })
|
||||
o = s:option(Value, _n("outbound_node_address"), translate("Address (Support Domain Name)"))
|
||||
o:depends({ [_n("outbound_node")] = "_socks" })
|
||||
o:depends({ [_n("outbound_node")] = "_http" })
|
||||
|
||||
o = s:option(Value, option_name("outbound_node_port"), translate("Port"))
|
||||
o = s:option(Value, _n("outbound_node_port"), translate("Port"))
|
||||
o.datatype = "port"
|
||||
o:depends({ [option_name("outbound_node")] = "_socks" })
|
||||
o:depends({ [option_name("outbound_node")] = "_http" })
|
||||
o:depends({ [_n("outbound_node")] = "_socks" })
|
||||
o:depends({ [_n("outbound_node")] = "_http" })
|
||||
|
||||
o = s:option(Value, option_name("outbound_node_username"), translate("Username"))
|
||||
o:depends({ [option_name("outbound_node")] = "_socks" })
|
||||
o:depends({ [option_name("outbound_node")] = "_http" })
|
||||
o = s:option(Value, _n("outbound_node_username"), translate("Username"))
|
||||
o:depends({ [_n("outbound_node")] = "_socks" })
|
||||
o:depends({ [_n("outbound_node")] = "_http" })
|
||||
|
||||
o = s:option(Value, option_name("outbound_node_password"), translate("Password"))
|
||||
o = s:option(Value, _n("outbound_node_password"), translate("Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("outbound_node")] = "_socks" })
|
||||
o:depends({ [option_name("outbound_node")] = "_http" })
|
||||
o:depends({ [_n("outbound_node")] = "_socks" })
|
||||
o:depends({ [_n("outbound_node")] = "_http" })
|
||||
|
||||
o = s:option(Value, option_name("outbound_node_iface"), translate("Interface"))
|
||||
o = s:option(Value, _n("outbound_node_iface"), translate("Interface"))
|
||||
o.default = "eth1"
|
||||
o:depends({ [option_name("outbound_node")] = "_iface" })
|
||||
o:depends({ [_n("outbound_node")] = "_iface" })
|
||||
|
||||
o = s:option(Flag, option_name("log"), translate("Log"))
|
||||
o = s:option(Flag, _n("log"), translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, option_name("loglevel"), translate("Log Level"))
|
||||
o = s:option(ListValue, _n("loglevel"), translate("Log Level"))
|
||||
o.default = "info"
|
||||
o:value("debug")
|
||||
o:value("info")
|
||||
o:value("warn")
|
||||
o:value("error")
|
||||
o:depends({ [option_name("log")] = true })
|
||||
o:depends({ [_n("log")] = true })
|
||||
|
||||
api.luci_types(arg[1], m, s, type_name, option_prefix)
|
||||
|
||||
+10
-10
@@ -10,7 +10,7 @@ local type_name = "Socks"
|
||||
|
||||
local option_prefix = "socks_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -18,14 +18,14 @@ end
|
||||
|
||||
s.fields["type"]:value(type_name, "Socks")
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Listen Port"))
|
||||
o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Flag, option_name("auth"), translate("Auth"))
|
||||
o = s:option(Flag, _n("auth"), translate("Auth"))
|
||||
o.validate = function(self, value, t)
|
||||
if value and value == "1" then
|
||||
local user_v = s.fields[option_name("username")] and s.fields[option_name("username")]:formvalue(t) or ""
|
||||
local pass_v = s.fields[option_name("password")] and s.fields[option_name("password")]:formvalue(t) or ""
|
||||
local user_v = s.fields[_n("username")] and s.fields[_n("username")]:formvalue(t) or ""
|
||||
local pass_v = s.fields[_n("password")] and s.fields[_n("password")]:formvalue(t) or ""
|
||||
if user_v == "" or pass_v == "" then
|
||||
return nil, translate("Username and Password must be used together!")
|
||||
end
|
||||
@@ -33,14 +33,14 @@ o.validate = function(self, value, t)
|
||||
return value
|
||||
end
|
||||
|
||||
o = s:option(Value, option_name("username"), translate("Username"))
|
||||
o:depends({ [option_name("auth")] = true })
|
||||
o = s:option(Value, _n("username"), translate("Username"))
|
||||
o:depends({ [_n("auth")] = true })
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
o:depends({ [option_name("auth")] = true })
|
||||
o:depends({ [_n("auth")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("log"), translate("Log"))
|
||||
o = s:option(Flag, _n("log"), translate("Log"))
|
||||
o.default = "1"
|
||||
|
||||
api.luci_types(arg[1], m, s, type_name, option_prefix)
|
||||
|
||||
+7
-7
@@ -10,7 +10,7 @@ local type_name = "SS-Rust"
|
||||
|
||||
local option_prefix = "ssrust_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -24,23 +24,23 @@ local ssrust_encrypt_method_list = {
|
||||
|
||||
s.fields["type"]:value(type_name, translate("Shadowsocks Rust"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Listen Port"))
|
||||
o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
|
||||
o = s:option(ListValue, option_name("method"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
|
||||
for a, t in ipairs(ssrust_encrypt_method_list) do o:value(t) end
|
||||
|
||||
o = s:option(Value, option_name("timeout"), translate("Connection Timeout"))
|
||||
o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 300
|
||||
|
||||
o = s:option(Flag, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open"))
|
||||
o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Flag, option_name("log"), translate("Log"))
|
||||
o = s:option(Flag, _n("log"), translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ local type_name = "SS"
|
||||
|
||||
local option_prefix = "ss_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -27,23 +27,23 @@ local ss_encrypt_method_list = {
|
||||
|
||||
s.fields["type"]:value(type_name, translate("Shadowsocks"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Listen Port"))
|
||||
o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
|
||||
o = s:option(ListValue, option_name("method"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
|
||||
for a, t in ipairs(ss_encrypt_method_list) do o:value(t) end
|
||||
|
||||
o = s:option(Value, option_name("timeout"), translate("Connection Timeout"))
|
||||
o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 300
|
||||
|
||||
o = s:option(Flag, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open"))
|
||||
o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Flag, option_name("log"), translate("Log"))
|
||||
o = s:option(Flag, _n("log"), translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ local type_name = "SSR"
|
||||
|
||||
local option_prefix = "ssr_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -37,37 +37,37 @@ local ssr_obfs_list = {
|
||||
|
||||
s.fields["type"]:value(type_name, translate("ShadowsocksR"))
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Listen Port"))
|
||||
o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(Value, option_name("password"), translate("Password"))
|
||||
o = s:option(Value, _n("password"), translate("Password"))
|
||||
o.password = true
|
||||
|
||||
o = s:option(ListValue, option_name("method"), translate("Encrypt Method"))
|
||||
o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
|
||||
for a, t in ipairs(ssr_encrypt_method_list) do o:value(t) end
|
||||
|
||||
o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
|
||||
o = s:option(ListValue, _n("protocol"), translate("Protocol"))
|
||||
for a, t in ipairs(ssr_protocol_list) do o:value(t) end
|
||||
|
||||
o = s:option(Value, option_name("protocol_param"), translate("Protocol_param"))
|
||||
o = s:option(Value, _n("protocol_param"), translate("Protocol_param"))
|
||||
|
||||
o = s:option(ListValue, option_name("obfs"), translate("Obfs"))
|
||||
o = s:option(ListValue, _n("obfs"), translate("Obfs"))
|
||||
for a, t in ipairs(ssr_obfs_list) do o:value(t) end
|
||||
|
||||
o = s:option(Value, option_name("obfs_param"), translate("Obfs_param"))
|
||||
o = s:option(Value, _n("obfs_param"), translate("Obfs_param"))
|
||||
|
||||
o = s:option(Value, option_name("timeout"), translate("Connection Timeout"))
|
||||
o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 300
|
||||
|
||||
o = s:option(Flag, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open"))
|
||||
o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Flag, option_name("udp_forward"), translate("UDP Forward"))
|
||||
o = s:option(Flag, _n("udp_forward"), translate("UDP Forward"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, option_name("log"), translate("Log"))
|
||||
o = s:option(Flag, _n("log"), translate("Log"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
|
||||
+21
-21
@@ -10,7 +10,7 @@ local type_name = "Trojan-Plus"
|
||||
|
||||
local option_prefix = "trojan_plus_"
|
||||
|
||||
local function option_name(name)
|
||||
local function _n(name)
|
||||
return option_prefix .. name
|
||||
end
|
||||
|
||||
@@ -18,15 +18,15 @@ end
|
||||
|
||||
s.fields["type"]:value(type_name, "Trojan-Plus")
|
||||
|
||||
o = s:option(Value, option_name("port"), translate("Listen Port"))
|
||||
o = s:option(Value, _n("port"), translate("Listen Port"))
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:option(DynamicList, option_name("uuid"), translate("ID") .. "/" .. translate("Password"))
|
||||
o = s:option(DynamicList, _n("uuid"), translate("ID") .. "/" .. translate("Password"))
|
||||
for i = 1, 3 do
|
||||
o:value(api.gen_uuid(1))
|
||||
end
|
||||
|
||||
o = s:option(Flag, option_name("tls"), translate("TLS"))
|
||||
o = s:option(Flag, _n("tls"), translate("TLS"))
|
||||
o.default = 0
|
||||
o.validate = function(self, value, t)
|
||||
if value then
|
||||
@@ -35,8 +35,8 @@ o.validate = function(self, value, t)
|
||||
return nil, translate("Original Trojan only supported 'tls', please choose 'tls'.")
|
||||
end
|
||||
if value == "1" then
|
||||
local ca = s.fields[option_name("tls_certificateFile")] and s.fields[option_name("tls_certificateFile")]:formvalue(t) or ""
|
||||
local key = s.fields[option_name("tls_keyFile")] and s.fields[option_name("tls_keyFile")]:formvalue(t) or ""
|
||||
local ca = s.fields[_n("tls_certificateFile")] and s.fields[_n("tls_certificateFile")]:formvalue(t) or ""
|
||||
local key = s.fields[_n("tls_keyFile")] and s.fields[_n("tls_keyFile")]:formvalue(t) or ""
|
||||
if ca == "" or key == "" then
|
||||
return nil, translate("Public key and Private key path can not be empty!")
|
||||
end
|
||||
@@ -45,9 +45,9 @@ o.validate = function(self, value, t)
|
||||
end
|
||||
end
|
||||
|
||||
o = s:option(FileUpload, option_name("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
|
||||
o = s:option(FileUpload, _n("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
|
||||
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o:depends({ [_n("tls")] = true })
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not nixio.fs.access(value) then
|
||||
@@ -59,9 +59,9 @@ o.validate = function(self, value, t)
|
||||
return nil
|
||||
end
|
||||
|
||||
o = s:option(FileUpload, option_name("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
|
||||
o = s:option(FileUpload, _n("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
|
||||
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o:depends({ [_n("tls")] = true })
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not nixio.fs.access(value) then
|
||||
@@ -73,36 +73,36 @@ o.validate = function(self, value, t)
|
||||
return nil
|
||||
end
|
||||
|
||||
o = s:option(Flag, option_name("tls_sessionTicket"), translate("Session Ticket"))
|
||||
o = s:option(Flag, _n("tls_sessionTicket"), translate("Session Ticket"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("tls")] = true })
|
||||
o:depends({ [_n("tls")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("tcp_fast_open"), translate("TCP Fast Open"))
|
||||
o = s:option(Flag, _n("tcp_fast_open"), translate("TCP Fast Open"))
|
||||
o.default = "0"
|
||||
|
||||
o = s:option(Flag, option_name("remote_enable"), translate("Enable Remote"), translate("You can forward to Nginx/Caddy/V2ray/Xray WebSocket and more."))
|
||||
o = s:option(Flag, _n("remote_enable"), translate("Enable Remote"), translate("You can forward to Nginx/Caddy/V2ray/Xray WebSocket and more."))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, option_name("remote_address"), translate("Remote Address"))
|
||||
o = s:option(Value, _n("remote_address"), translate("Remote Address"))
|
||||
o.default = "127.0.0.1"
|
||||
o:depends({ [option_name("remote_enable")] = true })
|
||||
o:depends({ [_n("remote_enable")] = true })
|
||||
|
||||
o = s:option(Value, option_name("remote_port"), translate("Remote Port"))
|
||||
o = s:option(Value, _n("remote_port"), translate("Remote Port"))
|
||||
o.datatype = "port"
|
||||
o.default = "80"
|
||||
o:depends({ [option_name("remote_enable")] = true })
|
||||
o:depends({ [_n("remote_enable")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("log"), translate("Log"))
|
||||
o = s:option(Flag, _n("log"), translate("Log"))
|
||||
o.default = "1"
|
||||
|
||||
o = s:option(ListValue, option_name("loglevel"), translate("Log Level"))
|
||||
o = s:option(ListValue, _n("loglevel"), translate("Log Level"))
|
||||
o.default = "2"
|
||||
o:value("0", "all")
|
||||
o:value("1", "info")
|
||||
o:value("2", "warn")
|
||||
o:value("3", "error")
|
||||
o:value("4", "fatal")
|
||||
o:depends({ [option_name("log")] = true })
|
||||
o:depends({ [_n("log")] = true })
|
||||
|
||||
api.luci_types(arg[1], m, s, type_name, option_prefix)
|
||||
|
||||
@@ -364,6 +364,26 @@ function get_domain_from_url(url)
|
||||
return url
|
||||
end
|
||||
|
||||
function get_node_name(node_id)
|
||||
local e
|
||||
if type(node_id) == "table" then
|
||||
e = node_id
|
||||
else
|
||||
e = uci:get_all(appname, node_id)
|
||||
end
|
||||
if e then
|
||||
if e.type and e.remarks then
|
||||
if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then
|
||||
local type = e.type
|
||||
if type == "sing-box" then type = "Sing-Box" end
|
||||
local remark = "%s:[%s] " % {type .. " " .. i18n.translatef(e.protocol), e.remarks}
|
||||
return remark
|
||||
end
|
||||
end
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
function get_valid_nodes()
|
||||
local show_node_info = uci_get_type("global_other", "show_node_info") or "0"
|
||||
local nodes = {}
|
||||
@@ -1046,7 +1066,7 @@ end
|
||||
function get_version()
|
||||
local version = sys.exec("opkg list-installed luci-app-passwall 2>/dev/null | awk '{print $3}'")
|
||||
if not version or #version == 0 then
|
||||
version = sys.exec("apk info luci-app-passwall 2>/dev/null | awk 'NR == 1 {print $1}' | cut -d'-' -f4-")
|
||||
version = sys.exec("apk info -L luci-app-passwall 2>/dev/null | awk 'NR == 1 {print $1}' | cut -d'-' -f4-")
|
||||
end
|
||||
return version or ""
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ end
|
||||
|
||||
function gen_outbound(flag, node, tag, proxy_table)
|
||||
local result = nil
|
||||
if node and node ~= "nil" then
|
||||
if node then
|
||||
local node_id = node[".name"]
|
||||
if tag == nil then
|
||||
tag = node_id
|
||||
@@ -46,7 +46,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
"127.0.0.1", --bind
|
||||
new_port, --socks port
|
||||
config_file, --config file
|
||||
(proxy_tag and proxy_tag ~= "nil" and relay_port) and tostring(relay_port) or "" --relay port
|
||||
(proxy_tag and relay_port) and tostring(relay_port) or "" --relay port
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -56,7 +56,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
port = new_port
|
||||
}
|
||||
else
|
||||
if proxy_tag and proxy_tag ~= "nil" then
|
||||
if proxy_tag then
|
||||
node.detour = proxy_tag
|
||||
end
|
||||
end
|
||||
@@ -679,7 +679,7 @@ function gen_config_server(node)
|
||||
}
|
||||
}
|
||||
|
||||
if node.outbound_node and node.outbound_node ~= "nil" then
|
||||
if node.outbound_node then
|
||||
local outbound = nil
|
||||
if node.outbound_node == "_iface" and node.outbound_node_iface then
|
||||
outbound = {
|
||||
@@ -905,7 +905,7 @@ function gen_config(var)
|
||||
end
|
||||
|
||||
if node.chain_proxy == "1" and node.preproxy_node then
|
||||
if outbound["_flag_proxy_tag"] and outbound["_flag_proxy_tag"] ~= "nil" then
|
||||
if outbound["_flag_proxy_tag"] then
|
||||
--Ignore
|
||||
else
|
||||
local preproxy_node = uci:get_all(appname, node.preproxy_node)
|
||||
@@ -951,7 +951,7 @@ function gen_config(var)
|
||||
|
||||
local function gen_shunt_node(rule_name, _node_id)
|
||||
if not rule_name then return nil, nil end
|
||||
if not _node_id then _node_id = node[rule_name] or "nil" end
|
||||
if not _node_id then _node_id = node[rule_name] end
|
||||
local rule_outboundTag
|
||||
if _node_id == "_direct" then
|
||||
rule_outboundTag = "direct"
|
||||
@@ -959,7 +959,7 @@ function gen_config(var)
|
||||
rule_outboundTag = "block"
|
||||
elseif _node_id == "_default" and rule_name ~= "default" then
|
||||
rule_outboundTag = "default"
|
||||
elseif _node_id:find("Socks_") then
|
||||
elseif _node_id and _node_id:find("Socks_") then
|
||||
local socks_id = _node_id:sub(1 + #"Socks_")
|
||||
local socks_node = uci:get_all(appname, socks_id) or nil
|
||||
if socks_node then
|
||||
@@ -976,7 +976,7 @@ function gen_config(var)
|
||||
rule_outboundTag = _outbound.tag
|
||||
end
|
||||
end
|
||||
elseif _node_id ~= "nil" then
|
||||
elseif _node_id then
|
||||
local _node = uci:get_all(appname, _node_id)
|
||||
if not _node then return nil, nil end
|
||||
|
||||
@@ -1180,7 +1180,7 @@ function gen_config(var)
|
||||
rule.domain_regex = #domain_table.domain_regex > 0 and domain_table.domain_regex or nil
|
||||
rule.geosite = #domain_table.geosite > 0 and domain_table.geosite or nil
|
||||
|
||||
if outboundTag and outboundTag ~= "nil" then
|
||||
if outboundTag then
|
||||
table.insert(dns_domain_rules, api.clone(domain_table))
|
||||
end
|
||||
end
|
||||
@@ -1476,7 +1476,7 @@ function gen_config(var)
|
||||
tag = "block"
|
||||
})
|
||||
for index, value in ipairs(config.outbounds) do
|
||||
if (not value["_flag_proxy_tag"] or value["_flag_proxy_tag"] == "nil") and not value.detour and value["_id"] and value.server and value.server_port then
|
||||
if not value["_flag_proxy_tag"] and not value.detour and value["_id"] and value.server and value.server_port then
|
||||
sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list"))
|
||||
end
|
||||
for k, v in pairs(config.outbounds[index]) do
|
||||
|
||||
@@ -48,7 +48,7 @@ end
|
||||
|
||||
function gen_outbound(flag, node, tag, proxy_table)
|
||||
local result = nil
|
||||
if node and node ~= "nil" then
|
||||
if node then
|
||||
local node_id = node[".name"]
|
||||
if tag == nil then
|
||||
tag = node_id
|
||||
@@ -82,7 +82,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
"127.0.0.1", --bind
|
||||
new_port, --socks port
|
||||
config_file, --config file
|
||||
(proxy_tag and proxy_tag ~= "nil" and relay_port) and tostring(relay_port) or "" --relay port
|
||||
(proxy_tag and relay_port) and tostring(relay_port) or "" --relay port
|
||||
)
|
||||
))
|
||||
node = {}
|
||||
@@ -95,7 +95,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
else
|
||||
if node.flow == "xtls-rprx-vision" then
|
||||
else
|
||||
if proxy_tag and proxy_tag ~= "nil" then
|
||||
if proxy_tag then
|
||||
node.proxySettings = {
|
||||
tag = proxy_tag,
|
||||
transportLayer = true
|
||||
@@ -404,7 +404,7 @@ function gen_config_server(node)
|
||||
}
|
||||
}
|
||||
|
||||
if node.outbound_node and node.outbound_node ~= "nil" then
|
||||
if node.outbound_node then
|
||||
local outbound = nil
|
||||
if node.outbound_node == "_iface" and node.outbound_node_iface then
|
||||
outbound = {
|
||||
@@ -735,7 +735,7 @@ function gen_config(var)
|
||||
-- fallback node
|
||||
local fallback_node_tag = nil
|
||||
local fallback_node_id = _node.fallback_node
|
||||
if fallback_node_id == "" or fallback_node_id == "nil" then fallback_node_id = nil end
|
||||
if not fallback_node_id or fallback_node_id == "" then fallback_node_id = nil end
|
||||
if fallback_node_id then
|
||||
local is_new_node = true
|
||||
for _, outbound in ipairs(outbounds) do
|
||||
@@ -784,7 +784,7 @@ function gen_config(var)
|
||||
local last_insert_outbound
|
||||
|
||||
if node.chain_proxy == "1" and node.preproxy_node then
|
||||
if outbound["_flag_proxy_tag"] and outbound["_flag_proxy_tag"] ~= "nil" then
|
||||
if outbound["_flag_proxy_tag"] then
|
||||
--Ignore
|
||||
else
|
||||
local preproxy_node = uci:get_all(appname, node.preproxy_node)
|
||||
@@ -846,7 +846,7 @@ function gen_config(var)
|
||||
return "blackhole", nil
|
||||
elseif _node_id == "_default" then
|
||||
return "default", nil
|
||||
elseif _node_id:find("Socks_") then
|
||||
elseif _node_id and _node_id:find("Socks_") then
|
||||
local socks_id = _node_id:sub(1 + #"Socks_")
|
||||
local socks_node = uci:get_all(appname, socks_id) or nil
|
||||
local socks_tag
|
||||
@@ -1396,7 +1396,7 @@ function gen_config(var)
|
||||
end
|
||||
|
||||
for index, value in ipairs(config.outbounds) do
|
||||
if (not value["_flag_proxy_tag"] or value["_flag_proxy_tag"] == "nil") and value["_id"] and value.server and value.server_port then
|
||||
if not value["_flag_proxy_tag"] and value["_id"] and value.server and value.server_port then
|
||||
sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list"))
|
||||
end
|
||||
for k, v in pairs(config.outbounds[index]) do
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<div id="cbi-<%=self.config.."-"..section.."-"..self.option%>" data-index="<%=self.index%>" data-depends="<%=pcdata(self:deplist2json(section))%>" style="display: none !important">
|
||||
<input type="hidden" id="<%=cbid%>" value="<%=pcdata(self:cfgvalue(section) or self.default or "")%>" />
|
||||
</div>
|
||||
@@ -53,13 +53,13 @@ local api = require "luci.passwall.api"
|
||||
var dom_id = dom.id.split(cbi_id).join(cbi_id.split("-").join(".")).split("cbi.").join("cbid.")
|
||||
var node_select = document.getElementsByName(dom_id)[0];
|
||||
var node_select_value = node_select.value;
|
||||
if (node_select_value && node_select_value != "nil" && node_select_value.indexOf("_default") != 0 && node_select_value.indexOf("_direct") != 0 && node_select_value.indexOf("_blackhole") != 0) {
|
||||
if (node_select_value && node_select_value != "" && node_select_value.indexOf("_default") != 0 && node_select_value.indexOf("_direct") != 0 && node_select_value.indexOf("_blackhole") != 0) {
|
||||
if (global_id != null && node_select_value.indexOf("tcp") == 0) {
|
||||
var d = global_id + "-tcp_node";
|
||||
d = d.replace("cbi-", "cbid-").replace(new RegExp("-", 'g'), ".");
|
||||
var dom = document.getElementsByName(d)[0];
|
||||
var _node_select_value = dom.value;
|
||||
if (_node_select_value && _node_select_value != "nil") {
|
||||
if (_node_select_value && _node_select_value != "") {
|
||||
node_select_value = _node_select_value;
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ local api = require "luci.passwall.api"
|
||||
var dom_id = dom_id.replace("cbi-", "cbid-").replace(new RegExp("-", 'g'), ".");
|
||||
var node_select = document.getElementsByName(dom_id)[0];
|
||||
var node_select_value = node_select.value;
|
||||
if (node_select_value && node_select_value != "nil") {
|
||||
if (node_select_value && node_select_value != "") {
|
||||
var v = document.getElementById(dom_id + "-" + node_select_value);
|
||||
if (v) {
|
||||
node_select.title = v.text;
|
||||
|
||||
@@ -673,17 +673,32 @@ msgstr "单位:秒"
|
||||
msgid "Units:minutes"
|
||||
msgstr "单位:分钟"
|
||||
|
||||
msgid "Open and close automatically"
|
||||
msgstr "定时自动开关"
|
||||
msgid "stop automatically mode"
|
||||
msgstr "定时关闭模式"
|
||||
|
||||
msgid "Automatically turn off time"
|
||||
msgstr "自动关闭时间"
|
||||
msgid "stop Time(Every day)"
|
||||
msgstr "关闭时间(每天)"
|
||||
|
||||
msgid "Automatically turn on time"
|
||||
msgstr "自动开启时间"
|
||||
msgid "stop Interval(Hour)"
|
||||
msgstr "关闭间隔(小时)"
|
||||
|
||||
msgid "Automatically restart time"
|
||||
msgstr "自动重启时间"
|
||||
msgid "start automatically mode"
|
||||
msgstr "定时开启模式"
|
||||
|
||||
msgid "start Time(Every day)"
|
||||
msgstr "开启时间(每天)"
|
||||
|
||||
msgid "start Interval(Hour)"
|
||||
msgstr "开启间隔(小时)"
|
||||
|
||||
msgid "restart automatically mode"
|
||||
msgstr "定时重启模式"
|
||||
|
||||
msgid "restart Time(Every day)"
|
||||
msgstr "重启时间(每天)"
|
||||
|
||||
msgid "restart Interval(Hour)"
|
||||
msgstr "重启间隔(小时)"
|
||||
|
||||
msgid "Forwarding Settings"
|
||||
msgstr "转发配置"
|
||||
@@ -925,6 +940,9 @@ msgstr "每周日"
|
||||
msgid "hour"
|
||||
msgstr "小时"
|
||||
|
||||
msgid "Hour"
|
||||
msgstr "小时"
|
||||
|
||||
msgid "Location of V2ray/Xray asset"
|
||||
msgstr "V2ray/Xray 资源文件目录"
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
config global
|
||||
option enabled '0'
|
||||
option socks_enabled '0'
|
||||
option tcp_node 'nil'
|
||||
option udp_node 'nil'
|
||||
option tcp_node_socks_port '1070'
|
||||
option filter_proxy_ipv6 '1'
|
||||
option dns_shunt 'chinadns-ng'
|
||||
@@ -32,7 +30,6 @@ config global_haproxy
|
||||
option balancing_enable '0'
|
||||
|
||||
config global_delay
|
||||
option auto_on '0'
|
||||
option start_daemon '1'
|
||||
option start_delay '60'
|
||||
|
||||
@@ -102,7 +99,7 @@ config nodes 'myshunt'
|
||||
option Streaming '_default'
|
||||
option Proxy '_default'
|
||||
option Direct '_direct'
|
||||
option default_node 'nil'
|
||||
option default_node '_direct'
|
||||
option domainStrategy 'IPOnDemand'
|
||||
|
||||
config shunt_rules 'DirectGame'
|
||||
|
||||
@@ -707,7 +707,7 @@ run_socks() {
|
||||
;;
|
||||
esac
|
||||
|
||||
eval node_${node}_socks_port=$socks_port
|
||||
set_cache_var "node_${node}_socks_port" "${socks_port}"
|
||||
|
||||
# http to socks
|
||||
[ -z "$http_flag" ] && [ "$http_port" != "0" ] && [ -n "$http_config_file" ] && [ "$type" != "sing-box" ] && [ "$type" != "xray" ] && [ "$type" != "socks" ] && {
|
||||
@@ -755,7 +755,7 @@ run_redir() {
|
||||
}
|
||||
}
|
||||
[ "$bind" != "127.0.0.1" ] && echolog "${PROTO}节点:[$remarks],监听端口:$local_port"
|
||||
eval ${PROTO}_NODE_PORT=$port
|
||||
set_cache_var "${PROTO}_NODE_PORT" "${port}"
|
||||
|
||||
case "$PROTO" in
|
||||
UDP)
|
||||
@@ -856,7 +856,7 @@ run_redir() {
|
||||
}
|
||||
[ "$TCP_UDP" = "1" ] && {
|
||||
UDP_REDIR_PORT=$local_port
|
||||
UDP_NODE="nil"
|
||||
unset UDP_NODE
|
||||
_flag="TCP_UDP"
|
||||
_args="${_args} udp_redir_port=${UDP_REDIR_PORT}"
|
||||
config_file=$(echo $config_file | sed "s/TCP/TCP_UDP/g")
|
||||
@@ -932,7 +932,7 @@ run_redir() {
|
||||
}
|
||||
[ "$TCP_UDP" = "1" ] && {
|
||||
UDP_REDIR_PORT=$local_port
|
||||
UDP_NODE="nil"
|
||||
unset UDP_NODE
|
||||
_flag="TCP_UDP"
|
||||
_args="${_args} udp_redir_port=${UDP_REDIR_PORT}"
|
||||
config_file=$(echo $config_file | sed "s/TCP/TCP_UDP/g")
|
||||
@@ -974,7 +974,7 @@ run_redir() {
|
||||
[ "$TCP_UDP" = "1" ] && {
|
||||
config_file=$(echo $config_file | sed "s/TCP/TCP_UDP/g")
|
||||
UDP_REDIR_PORT=$TCP_REDIR_PORT
|
||||
UDP_NODE="nil"
|
||||
unset UDP_NODE
|
||||
}
|
||||
local loglevel=$(config_t_get global trojan_loglevel "2")
|
||||
lua $UTIL_TROJAN gen_config -node $node -run_type nat -local_addr "0.0.0.0" -local_port $local_port -loglevel $loglevel $lua_tproxy_arg > $config_file
|
||||
@@ -989,7 +989,7 @@ run_redir() {
|
||||
[ "$TCP_UDP" = "1" ] && {
|
||||
config_file=$(echo $config_file | sed "s/TCP/TCP_UDP/g")
|
||||
UDP_REDIR_PORT=$TCP_REDIR_PORT
|
||||
UDP_NODE="nil"
|
||||
unset UDP_NODE
|
||||
_extra_param="-u"
|
||||
}
|
||||
lua $UTIL_SS gen_config -node $node -local_addr "0.0.0.0" -local_port $local_port $lua_tproxy_arg > $config_file
|
||||
@@ -1001,7 +1001,7 @@ run_redir() {
|
||||
[ "$TCP_UDP" = "1" ] && {
|
||||
config_file=$(echo $config_file | sed "s/TCP/TCP_UDP/g")
|
||||
UDP_REDIR_PORT=$TCP_REDIR_PORT
|
||||
UDP_NODE="nil"
|
||||
unset UDP_NODE
|
||||
lua_mode_arg="-mode tcp_and_udp"
|
||||
}
|
||||
lua $UTIL_SS gen_config -node $node -local_addr "0.0.0.0" -local_port $local_port $lua_mode_arg $lua_tproxy_arg > $config_file
|
||||
@@ -1023,7 +1023,7 @@ run_redir() {
|
||||
[ "$TCP_UDP" = "1" ] && {
|
||||
config_file=$(echo $config_file | sed "s/TCP/TCP_UDP/g")
|
||||
UDP_REDIR_PORT=$TCP_REDIR_PORT
|
||||
UDP_NODE="nil"
|
||||
unset UDP_NODE
|
||||
_extra_param="${_extra_param} -local_udp_redir_port $local_port"
|
||||
}
|
||||
lua $UTIL_SS gen_config -node $node ${_extra_param} > $config_file
|
||||
@@ -1044,7 +1044,7 @@ run_redir() {
|
||||
[ "$TCP_UDP" = "1" ] && {
|
||||
config_file=$(echo $config_file | sed "s/TCP/TCP_UDP/g")
|
||||
UDP_REDIR_PORT=$TCP_REDIR_PORT
|
||||
UDP_NODE="nil"
|
||||
unset UDP_NODE
|
||||
_extra_param="${_extra_param} -local_udp_redir_port $local_port"
|
||||
}
|
||||
_extra_param="${_extra_param} -tcp_proxy_way $tcp_proxy_way"
|
||||
@@ -1057,7 +1057,7 @@ run_redir() {
|
||||
[ "$TCP_UDP" = "1" ] && {
|
||||
_flag="TCP_UDP"
|
||||
UDP_REDIR_PORT=$TCP_REDIR_PORT
|
||||
UDP_NODE="nil"
|
||||
unset UDP_NODE
|
||||
}
|
||||
local _socks_tproxy=""
|
||||
[ "$tcp_proxy_way" = "tproxy" ] && _socks_tproxy="1"
|
||||
@@ -1085,13 +1085,13 @@ run_redir() {
|
||||
esac
|
||||
unset tcp_node_socks_flag tcp_node_http_flag
|
||||
[ "$type" != "sing-box" ] && [ "$type" != "xray" ] && echo "${node}" >> $TMP_PATH/direct_node_list
|
||||
return 0
|
||||
[ -n "${redir_port}" ] && set_cache_var "node_${node}_${PROTO}_redir_port" "${local_port}"
|
||||
}
|
||||
|
||||
start_redir() {
|
||||
local proto=${1}
|
||||
eval node=\$${proto}_NODE
|
||||
if [ "$node" != "nil" ]; then
|
||||
if [ -n "$node" ]; then
|
||||
TYPE=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
|
||||
local config_file="${proto}.json"
|
||||
local log_file="${proto}.log"
|
||||
@@ -1099,7 +1099,12 @@ start_redir() {
|
||||
local port=$(echo $(get_new_port $current_port $proto))
|
||||
eval ${proto}_REDIR=$port
|
||||
run_redir node=$node proto=${proto} bind=0.0.0.0 local_port=$port config_file=$config_file log_file=$log_file
|
||||
set_cache_var "GLOBAL_${proto}_node" "$node"
|
||||
set_cache_var "ACL_GLOBAL_${proto}_node" "${node}"
|
||||
set_cache_var "ACL_GLOBAL_${proto}_redir_port" "${port}"
|
||||
[ "$TCP_UDP" = "1" ] && {
|
||||
set_cache_var "ACL_GLOBAL_UDP_node" "${node}"
|
||||
set_cache_var "ACL_GLOBAL_UDP_redir_port" "${port}"
|
||||
}
|
||||
else
|
||||
[ "${proto}" = "UDP" ] && [ "$TCP_UDP" = "1" ] && return
|
||||
echolog "${proto}节点没有选择或为空,不代理${proto}。"
|
||||
@@ -1114,8 +1119,8 @@ start_socks() {
|
||||
for id in $ids; do
|
||||
local enabled=$(config_n_get $id enabled 0)
|
||||
[ "$enabled" == "0" ] && continue
|
||||
local node=$(config_n_get $id node nil)
|
||||
[ "$node" == "nil" ] && continue
|
||||
local node=$(config_n_get $id node)
|
||||
[ -z "$node" ] && continue
|
||||
local bind_local=$(config_n_get $id bind_local 0)
|
||||
local bind="0.0.0.0"
|
||||
[ "$bind_local" = "1" ] && bind="127.0.0.1"
|
||||
@@ -1206,23 +1211,41 @@ start_crontab() {
|
||||
return
|
||||
}
|
||||
|
||||
auto_on=$(config_t_get global_delay auto_on 0)
|
||||
if [ "$auto_on" = "1" ]; then
|
||||
time_off=$(config_t_get global_delay time_off)
|
||||
time_on=$(config_t_get global_delay time_on)
|
||||
time_restart=$(config_t_get global_delay time_restart)
|
||||
[ -z "$time_off" -o "$time_off" != "nil" ] && {
|
||||
echo "0 $time_off * * * /etc/init.d/$CONFIG stop" >>/etc/crontabs/root
|
||||
echolog "配置定时任务:每天 $time_off 点关闭服务。"
|
||||
}
|
||||
[ -z "$time_on" -o "$time_on" != "nil" ] && {
|
||||
echo "0 $time_on * * * /etc/init.d/$CONFIG start" >>/etc/crontabs/root
|
||||
echolog "配置定时任务:每天 $time_on 点开启服务。"
|
||||
}
|
||||
[ -z "$time_restart" -o "$time_restart" != "nil" ] && {
|
||||
echo "0 $time_restart * * * /etc/init.d/$CONFIG restart" >>/etc/crontabs/root
|
||||
echolog "配置定时任务:每天 $time_restart 点重启服务。"
|
||||
}
|
||||
stop_week_mode=$(config_t_get global_delay stop_week_mode)
|
||||
stop_time_mode=$(config_t_get global_delay stop_time_mode)
|
||||
if [ -n "$stop_week_mode" ]; then
|
||||
local t="0 $stop_time_mode * * $stop_week_mode"
|
||||
[ "$stop_week_mode" = "7" ] && t="0 $stop_time_mode * * *"
|
||||
if [ "$stop_week_mode" = "8" ]; then
|
||||
update_loop=1
|
||||
else
|
||||
echo "$t /etc/init.d/$CONFIG stop > /dev/null 2>&1 &" >>/etc/crontabs/root
|
||||
fi
|
||||
echolog "配置定时任务:自动关闭服务。"
|
||||
fi
|
||||
start_week_mode=$(config_t_get global_delay start_week_mode)
|
||||
start_time_mode=$(config_t_get global_delay start_time_mode)
|
||||
if [ -n "$start_week_mode" ]; then
|
||||
local t="0 $start_time_mode * * $start_week_mode"
|
||||
[ "$start_week_mode" = "7" ] && t="0 $start_time_mode * * *"
|
||||
if [ "$start_week_mode" = "8" ]; then
|
||||
update_loop=1
|
||||
else
|
||||
echo "$t /etc/init.d/$CONFIG start > /dev/null 2>&1 &" >>/etc/crontabs/root
|
||||
fi
|
||||
echolog "配置定时任务:自动开启服务。"
|
||||
fi
|
||||
restart_week_mode=$(config_t_get global_delay restart_week_mode)
|
||||
restart_time_mode=$(config_t_get global_delay restart_time_mode)
|
||||
if [ -n "$restart_week_mode" ]; then
|
||||
local t="0 $restart_time_mode * * $restart_week_mode"
|
||||
[ "$restart_week_mode" = "7" ] && t="0 $restart_time_mode * * *"
|
||||
if [ "$restart_week_mode" = "8" ]; then
|
||||
update_loop=1
|
||||
else
|
||||
echo "$t /etc/init.d/$CONFIG restart > /dev/null 2>&1 &" >>/etc/crontabs/root
|
||||
fi
|
||||
echolog "配置定时任务:自动重启服务。"
|
||||
fi
|
||||
|
||||
autoupdate=$(config_t_get global_rules auto_update)
|
||||
@@ -1695,198 +1718,221 @@ acl_app() {
|
||||
[ ! -z "${source_list}" ] && echo -e "${source_list}" | sed '/^$/d' > ${acl_path}/source_list
|
||||
|
||||
use_global_config=${use_global_config:-0}
|
||||
tcp_node=${tcp_node:-nil}
|
||||
udp_node=${udp_node:-nil}
|
||||
use_direct_list=${use_direct_list:-1}
|
||||
use_proxy_list=${use_proxy_list:-1}
|
||||
use_block_list=${use_block_list:-1}
|
||||
use_gfw_list=${use_gfw_list:-1}
|
||||
chn_list=${chn_list:-direct}
|
||||
tcp_proxy_mode=${tcp_proxy_mode:-proxy}
|
||||
udp_proxy_mode=${udp_proxy_mode:-proxy}
|
||||
filter_proxy_ipv6=${filter_proxy_ipv6:-0}
|
||||
dnsmasq_filter_proxy_ipv6=${filter_proxy_ipv6}
|
||||
dns_shunt=${dns_shunt:-dnsmasq}
|
||||
dns_mode=${dns_mode:-dns2socks}
|
||||
remote_dns=${remote_dns:-1.1.1.1}
|
||||
use_default_dns=${use_default_dns:-direct}
|
||||
[ "$dns_mode" = "sing-box" ] && {
|
||||
[ "$v2ray_dns_mode" = "doh" ] && remote_dns=${remote_dns_doh:-https://1.1.1.1/dns-query}
|
||||
}
|
||||
|
||||
[ "${use_global_config}" = "1" ] && {
|
||||
tcp_node="default"
|
||||
udp_node="default"
|
||||
}
|
||||
tcp_no_redir_ports=${tcp_no_redir_ports:-${TCP_NO_REDIR_PORTS}}
|
||||
udp_no_redir_ports=${udp_no_redir_ports:-${UDP_NO_REDIR_PORTS}}
|
||||
if [ "$tcp_no_redir_ports" == "1:65535" ] && [ "$udp_no_redir_ports" == "1:65535" ]; then
|
||||
unset use_global_config
|
||||
unset tcp_node
|
||||
unset udp_node
|
||||
else
|
||||
use_direct_list=${use_direct_list:-1}
|
||||
use_proxy_list=${use_proxy_list:-1}
|
||||
use_block_list=${use_block_list:-1}
|
||||
use_gfw_list=${use_gfw_list:-1}
|
||||
chn_list=${chn_list:-direct}
|
||||
tcp_proxy_mode=${tcp_proxy_mode:-proxy}
|
||||
udp_proxy_mode=${udp_proxy_mode:-proxy}
|
||||
filter_proxy_ipv6=${filter_proxy_ipv6:-0}
|
||||
dnsmasq_filter_proxy_ipv6=${filter_proxy_ipv6}
|
||||
dns_shunt=${dns_shunt:-dnsmasq}
|
||||
dns_mode=${dns_mode:-dns2socks}
|
||||
remote_dns=${remote_dns:-1.1.1.1}
|
||||
use_default_dns=${use_default_dns:-direct}
|
||||
[ "$dns_mode" = "sing-box" ] && {
|
||||
[ "$v2ray_dns_mode" = "doh" ] && remote_dns=${remote_dns_doh:-https://1.1.1.1/dns-query}
|
||||
}
|
||||
fi
|
||||
|
||||
[ "$tcp_node" != "nil" ] && {
|
||||
[ -n "$tcp_node" ] && {
|
||||
local GLOBAL_TCP_NODE=$(get_cache_var "ACL_GLOBAL_TCP_node")
|
||||
echolog "${GLOBAL_TCP_NODE}"
|
||||
[ -n "${GLOBAL_TCP_NODE}" ] && GLOBAL_TCP_redir_port=$(get_cache_var "ACL_GLOBAL_TCP_redir_port")
|
||||
if [ "$tcp_node" = "default" ]; then
|
||||
tcp_node=$TCP_NODE
|
||||
tcp_port=$TCP_REDIR_PORT
|
||||
if [ -n "${GLOBAL_TCP_NODE}" ]; then
|
||||
set_cache_var "ACL_${sid}_tcp_node" "${GLOBAL_TCP_NODE}"
|
||||
set_cache_var "ACL_${sid}_tcp_redir_port" "${GLOBAL_TCP_redir_port}"
|
||||
set_cache_var "ACL_${sid}_dns_port" "${GLOBAL_DNSMASQ_PORT}"
|
||||
set_cache_var "ACL_${sid}_tcp_default" "1"
|
||||
else
|
||||
echolog " - 全局节点未启用,跳过【${remarks}】"
|
||||
fi
|
||||
else
|
||||
[ "$(config_get_type $tcp_node nil)" = "nodes" ] && {
|
||||
run_dns() {
|
||||
local _dns_port
|
||||
[ -n $1 ] && _dns_port=$1
|
||||
[ -z ${_dns_port} ] && {
|
||||
dns_port=$(get_new_port $(expr $dns_port + 1))
|
||||
_dns_port=$dns_port
|
||||
if [ "$dns_mode" = "dns2socks" ]; then
|
||||
run_dns2socks flag=acl_${sid} socks_address=127.0.0.1 socks_port=$socks_port listen_address=0.0.0.0 listen_port=${_dns_port} dns=$remote_dns cache=1
|
||||
elif [ "$dns_mode" = "sing-box" -o "$dns_mode" = "xray" ]; then
|
||||
config_file=$TMP_ACL_PATH/${tcp_node}_SOCKS_${socks_port}_DNS.json
|
||||
[ "$dns_mode" = "xray" ] && [ "$v2ray_dns_mode" = "tcp+doh" ] && remote_dns_doh=${remote_dns_doh:-https://1.1.1.1/dns-query}
|
||||
local type=${dns_mode}
|
||||
[ "${dns_mode}" = "sing-box" ] && type="singbox"
|
||||
dnsmasq_filter_proxy_ipv6=0
|
||||
run_${type} flag=acl_${sid} type=$dns_mode dns_socks_address=127.0.0.1 dns_socks_port=$socks_port dns_listen_port=${_dns_port} remote_dns_protocol=${v2ray_dns_mode} remote_dns_tcp_server=${remote_dns} remote_dns_doh="${remote_dns_doh}" remote_dns_query_strategy=${DNS_QUERY_STRATEGY} dns_client_ip=${dns_client_ip} dns_query_strategy=${DNS_QUERY_STRATEGY} config_file=$config_file
|
||||
fi
|
||||
eval node_${tcp_node}_$(echo -n "${remote_dns}" | md5sum | cut -d " " -f1)=${_dns_port}
|
||||
}
|
||||
|
||||
[ "$dns_shunt" = "chinadns-ng" ] && [ -n "$(first_type chinadns-ng)" ] && {
|
||||
chinadns_ng_min=2024.04.13
|
||||
chinadns_ng_now=$(chinadns-ng -V | grep -i "ChinaDNS-NG " | awk '{print $2}')
|
||||
if [ $(check_ver "$chinadns_ng_now" "$chinadns_ng_min") = 1 ]; then
|
||||
echolog " * 注意:当前 ChinaDNS-NG 版本为[ $chinadns_ng_now ],请更新到[ $chinadns_ng_min ]或以上版本,否则 DNS 有可能无法正常工作!"
|
||||
fi
|
||||
|
||||
[ "$filter_proxy_ipv6" = "1" ] && dnsmasq_filter_proxy_ipv6=0
|
||||
chinadns_port=$(expr $chinadns_port + 1)
|
||||
_china_ng_listen="127.0.0.1#${chinadns_port}"
|
||||
|
||||
_chinadns_local_dns=$(IFS=','; set -- $LOCAL_DNS; [ "${1%%[#:]*}" = "127.0.0.1" ] && echo "$1" || ([ -n "$2" ] && echo "$1,$2" || echo "$1"))
|
||||
_direct_dns_mode=$(config_t_get global direct_dns_mode "auto")
|
||||
case "${_direct_dns_mode}" in
|
||||
udp)
|
||||
_chinadns_local_dns=$(config_t_get global direct_dns_udp 223.5.5.5 | sed 's/:/#/g')
|
||||
;;
|
||||
tcp)
|
||||
_chinadns_local_dns="tcp://$(config_t_get global direct_dns_tcp 223.5.5.5 | sed 's/:/#/g')"
|
||||
;;
|
||||
dot)
|
||||
if [ "$(chinadns-ng -V | grep -i wolfssl)" != "nil" ]; then
|
||||
_chinadns_local_dns=$(config_t_get global direct_dns_dot "tls://dot.pub@1.12.12.12")
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
run_chinadns_ng \
|
||||
_flag="$sid" \
|
||||
_listen_port=${chinadns_port} \
|
||||
_dns_local=${_chinadns_local_dns} \
|
||||
_dns_trust=127.0.0.1#${_dns_port} \
|
||||
_no_ipv6_trust=${filter_proxy_ipv6} \
|
||||
_use_direct_list=${use_direct_list} \
|
||||
_use_proxy_list=${use_proxy_list} \
|
||||
_use_block_list=${use_block_list} \
|
||||
_gfwlist=${use_gfw_list} \
|
||||
_chnlist=${chn_list} \
|
||||
_default_mode=${tcp_proxy_mode} \
|
||||
_default_tag=${chinadns_ng_default_tag:-smart} \
|
||||
_no_logic_log=1 \
|
||||
_tcp_node=${tcp_node}
|
||||
|
||||
use_default_dns="chinadns_ng"
|
||||
}
|
||||
|
||||
dnsmasq_port=$(get_new_port $(expr $dnsmasq_port + 1))
|
||||
local dnsmasq_conf=${acl_path}/dnsmasq.conf
|
||||
local dnsmasq_conf_path=${acl_path}/dnsmasq.d
|
||||
lua $APP_PATH/helper_dnsmasq.lua add_rule -FLAG ${sid} -TMP_DNSMASQ_PATH ${dnsmasq_conf_path} -DNSMASQ_CONF_FILE ${dnsmasq_conf} \
|
||||
-LISTEN_PORT ${dnsmasq_port} -DEFAULT_DNS $DEFAULT_DNS -LOCAL_DNS $LOCAL_DNS \
|
||||
-USE_DIRECT_LIST "${use_direct_list}" -USE_PROXY_LIST "${use_proxy_list}" -USE_BLOCK_LIST "${use_block_list}" -USE_GFW_LIST "${use_gfw_list}" -CHN_LIST "${chn_list}" \
|
||||
-TUN_DNS "127.0.0.1#${_dns_port}" -REMOTE_FAKEDNS 0 -USE_DEFAULT_DNS "${use_default_dns:-direct}" -CHINADNS_DNS ${_china_ng_listen:-0} \
|
||||
-TCP_NODE $tcp_node -DEFAULT_PROXY_MODE ${tcp_proxy_mode} -NO_PROXY_IPV6 ${dnsmasq_filter_proxy_ipv6:-0} -NFTFLAG ${nftflag:-0} \
|
||||
-NO_LOGIC_LOG 1
|
||||
ln_run "$(first_type dnsmasq)" "dnsmasq_${sid}" "/dev/null" -C ${dnsmasq_conf} -x ${acl_path}/dnsmasq.pid
|
||||
set_cache_var "ACL_${sid}_dns_port" "${dnsmasq_port}"
|
||||
eval node_${tcp_node}_$(echo -n "${tcp_proxy_mode}${remote_dns}" | md5sum | cut -d " " -f1)=${dnsmasq_port}
|
||||
}
|
||||
_redir_port=$(eval echo \${node_${tcp_node}_redir_port})
|
||||
_socks_port=$(eval echo \${node_${tcp_node}_socks_port})
|
||||
if [ -n "${_socks_port}" ] && [ -n "${_redir_port}" ]; then
|
||||
socks_port=${_socks_port}
|
||||
tcp_port=${_redir_port}
|
||||
_dnsmasq_port=$(eval echo \${node_${tcp_node}_$(echo -n "${tcp_proxy_mode}${remote_dns}" | md5sum | cut -d " " -f1)})
|
||||
if [ -z "${_dnsmasq_port}" ]; then
|
||||
_dns_port=$(eval echo \${node_${tcp_node}_$(echo -n "${remote_dns}" | md5sum | cut -d " " -f1)})
|
||||
run_dns ${_dns_port}
|
||||
else
|
||||
[ -n "${_dnsmasq_port}" ] && set_cache_var "ACL_${sid}_dns_port" "${_dnsmasq_port}"
|
||||
fi
|
||||
[ "$(config_get_type $tcp_node)" = "nodes" ] && {
|
||||
if [ -n "${GLOBAL_TCP_NODE}" ] && [ "$tcp_node" = "${GLOBAL_TCP_NODE}" ]; then
|
||||
set_cache_var "ACL_${sid}_tcp_node" "${GLOBAL_TCP_NODE}"
|
||||
set_cache_var "ACL_${sid}_tcp_redir_port" "${GLOBAL_TCP_redir_port}"
|
||||
set_cache_var "ACL_${sid}_dns_port" "${GLOBAL_DNSMASQ_PORT}"
|
||||
set_cache_var "ACL_${sid}_tcp_default" "1"
|
||||
else
|
||||
socks_port=$(get_new_port $(expr $socks_port + 1))
|
||||
eval node_${tcp_node}_socks_port=$socks_port
|
||||
redir_port=$(get_new_port $(expr $redir_port + 1))
|
||||
eval node_${tcp_node}_redir_port=$redir_port
|
||||
tcp_port=$redir_port
|
||||
|
||||
local type=$(echo $(config_n_get $tcp_node type) | tr 'A-Z' 'a-z')
|
||||
if [ -n "${type}" ] && ([ "${type}" = "sing-box" ] || [ "${type}" = "xray" ]); then
|
||||
config_file="acl/${tcp_node}_TCP_${redir_port}.json"
|
||||
_extra_param="socks_address=127.0.0.1 socks_port=$socks_port"
|
||||
if [ "$dns_mode" = "sing-box" ] || [ "$dns_mode" = "xray" ]; then
|
||||
run_dns() {
|
||||
local _dns_port
|
||||
[ -n $1 ] && _dns_port=$1
|
||||
[ -z ${_dns_port} ] && {
|
||||
dns_port=$(get_new_port $(expr $dns_port + 1))
|
||||
_dns_port=$dns_port
|
||||
config_file=$(echo $config_file | sed "s/TCP_/DNS_${_dns_port}_TCP_/g")
|
||||
remote_dns_doh=${remote_dns}
|
||||
dnsmasq_filter_proxy_ipv6=0
|
||||
[ "$dns_mode" = "xray" ] && [ "$v2ray_dns_mode" = "tcp+doh" ] && remote_dns_doh=${remote_dns_doh:-https://1.1.1.1/dns-query}
|
||||
_extra_param="dns_listen_port=${_dns_port} remote_dns_protocol=${v2ray_dns_mode} remote_dns_tcp_server=${remote_dns} remote_dns_doh=${remote_dns_doh} remote_dns_query_strategy=${DNS_QUERY_STRATEGY} dns_client_ip=${dns_client_ip} dns_query_strategy=${DNS_QUERY_STRATEGY}"
|
||||
fi
|
||||
[ "$udp_node" != "nil" ] && ([ "$udp_node" = "tcp" ] || [ "$udp_node" = "$tcp_node" ]) && {
|
||||
config_file=$(echo $config_file | sed "s/TCP_/TCP_UDP_/g")
|
||||
_extra_param="${_extra_param} udp_redir_port=$redir_port"
|
||||
if [ "$dns_mode" = "dns2socks" ]; then
|
||||
run_dns2socks flag=acl_${sid} socks_address=127.0.0.1 socks_port=$socks_port listen_address=0.0.0.0 listen_port=${_dns_port} dns=$remote_dns cache=1
|
||||
elif [ "$dns_mode" = "sing-box" -o "$dns_mode" = "xray" ]; then
|
||||
config_file=$TMP_ACL_PATH/${tcp_node}_SOCKS_${socks_port}_DNS.json
|
||||
[ "$dns_mode" = "xray" ] && [ "$v2ray_dns_mode" = "tcp+doh" ] && remote_dns_doh=${remote_dns_doh:-https://1.1.1.1/dns-query}
|
||||
local type=${dns_mode}
|
||||
[ "${dns_mode}" = "sing-box" ] && type="singbox"
|
||||
dnsmasq_filter_proxy_ipv6=0
|
||||
run_${type} flag=acl_${sid} type=$dns_mode dns_socks_address=127.0.0.1 dns_socks_port=$socks_port dns_listen_port=${_dns_port} remote_dns_protocol=${v2ray_dns_mode} remote_dns_tcp_server=${remote_dns} remote_dns_doh="${remote_dns_doh}" remote_dns_query_strategy=${DNS_QUERY_STRATEGY} dns_client_ip=${dns_client_ip} dns_query_strategy=${DNS_QUERY_STRATEGY} config_file=$config_file
|
||||
fi
|
||||
set_cache_var "node_${tcp_node}_$(echo -n "${remote_dns}" | md5sum | cut -d " " -f1)" "${_dns_port}"
|
||||
}
|
||||
config_file="$TMP_PATH/$config_file"
|
||||
[ "${type}" = "sing-box" ] && type="singbox"
|
||||
run_${type} flag=$tcp_node node=$tcp_node tcp_redir_port=$redir_port ${_extra_param} config_file=$config_file
|
||||
|
||||
[ "$dns_shunt" = "chinadns-ng" ] && [ -n "$(first_type chinadns-ng)" ] && {
|
||||
chinadns_ng_min=2024.04.13
|
||||
chinadns_ng_now=$(chinadns-ng -V | grep -i "ChinaDNS-NG " | awk '{print $2}')
|
||||
if [ $(check_ver "$chinadns_ng_now" "$chinadns_ng_min") = 1 ]; then
|
||||
echolog " * 注意:当前 ChinaDNS-NG 版本为[ $chinadns_ng_now ],请更新到[ $chinadns_ng_min ]或以上版本,否则 DNS 有可能无法正常工作!"
|
||||
fi
|
||||
|
||||
[ "$filter_proxy_ipv6" = "1" ] && dnsmasq_filter_proxy_ipv6=0
|
||||
chinadns_port=$(expr $chinadns_port + 1)
|
||||
_china_ng_listen="127.0.0.1#${chinadns_port}"
|
||||
|
||||
_chinadns_local_dns=$(IFS=','; set -- $LOCAL_DNS; [ "${1%%[#:]*}" = "127.0.0.1" ] && echo "$1" || ([ -n "$2" ] && echo "$1,$2" || echo "$1"))
|
||||
_direct_dns_mode=$(config_t_get global direct_dns_mode "auto")
|
||||
case "${_direct_dns_mode}" in
|
||||
udp)
|
||||
_chinadns_local_dns=$(config_t_get global direct_dns_udp 223.5.5.5 | sed 's/:/#/g')
|
||||
;;
|
||||
tcp)
|
||||
_chinadns_local_dns="tcp://$(config_t_get global direct_dns_tcp 223.5.5.5 | sed 's/:/#/g')"
|
||||
;;
|
||||
dot)
|
||||
if [ "$(chinadns-ng -V | grep -i wolfssl)" != "nil" ]; then
|
||||
_chinadns_local_dns=$(config_t_get global direct_dns_dot "tls://dot.pub@1.12.12.12")
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
run_chinadns_ng \
|
||||
_flag="$sid" \
|
||||
_listen_port=${chinadns_port} \
|
||||
_dns_local=${_chinadns_local_dns} \
|
||||
_dns_trust=127.0.0.1#${_dns_port} \
|
||||
_no_ipv6_trust=${filter_proxy_ipv6} \
|
||||
_use_direct_list=${use_direct_list} \
|
||||
_use_proxy_list=${use_proxy_list} \
|
||||
_use_block_list=${use_block_list} \
|
||||
_gfwlist=${use_gfw_list} \
|
||||
_chnlist=${chn_list} \
|
||||
_default_mode=${tcp_proxy_mode} \
|
||||
_default_tag=${chinadns_ng_default_tag:-smart} \
|
||||
_no_logic_log=1 \
|
||||
_tcp_node=${tcp_node}
|
||||
|
||||
use_default_dns="chinadns_ng"
|
||||
}
|
||||
|
||||
dnsmasq_port=$(get_new_port $(expr $dnsmasq_port + 1))
|
||||
local dnsmasq_conf=${acl_path}/dnsmasq.conf
|
||||
local dnsmasq_conf_path=${acl_path}/dnsmasq.d
|
||||
lua $APP_PATH/helper_dnsmasq.lua add_rule -FLAG ${sid} -TMP_DNSMASQ_PATH ${dnsmasq_conf_path} -DNSMASQ_CONF_FILE ${dnsmasq_conf} \
|
||||
-LISTEN_PORT ${dnsmasq_port} -DEFAULT_DNS $DEFAULT_DNS -LOCAL_DNS $LOCAL_DNS \
|
||||
-USE_DIRECT_LIST "${use_direct_list}" -USE_PROXY_LIST "${use_proxy_list}" -USE_BLOCK_LIST "${use_block_list}" -USE_GFW_LIST "${use_gfw_list}" -CHN_LIST "${chn_list}" \
|
||||
-TUN_DNS "127.0.0.1#${_dns_port}" -REMOTE_FAKEDNS 0 -USE_DEFAULT_DNS "${use_default_dns:-direct}" -CHINADNS_DNS ${_china_ng_listen:-0} \
|
||||
-TCP_NODE $tcp_node -DEFAULT_PROXY_MODE ${tcp_proxy_mode} -NO_PROXY_IPV6 ${dnsmasq_filter_proxy_ipv6:-0} -NFTFLAG ${nftflag:-0} \
|
||||
-NO_LOGIC_LOG 1
|
||||
ln_run "$(first_type dnsmasq)" "dnsmasq_${sid}" "/dev/null" -C ${dnsmasq_conf} -x ${acl_path}/dnsmasq.pid
|
||||
set_cache_var "ACL_${sid}_dns_port" "${dnsmasq_port}"
|
||||
set_cache_var "node_${tcp_node}_$(echo -n "${tcp_proxy_mode}${remote_dns}" | md5sum | cut -d " " -f1)" "${dnsmasq_port}"
|
||||
}
|
||||
_redir_port=$(get_cache_var "node_${tcp_node}_redir_port")
|
||||
_socks_port=$(get_cache_var "node_${tcp_node}_socks_port")
|
||||
if [ -n "${_socks_port}" ] && [ -n "${_redir_port}" ]; then
|
||||
socks_port=${_socks_port}
|
||||
tcp_port=${_redir_port}
|
||||
_dnsmasq_port=$(get_cache_var "node_${tcp_node}_$(echo -n "${tcp_proxy_mode}${remote_dns}" | md5sum | cut -d " " -f1)")
|
||||
if [ -z "${_dnsmasq_port}" ]; then
|
||||
_dns_port=$(get_cache_var "node_${tcp_node}_$(echo -n "${remote_dns}" | md5sum | cut -d " " -f1)")
|
||||
run_dns ${_dns_port}
|
||||
else
|
||||
[ -n "${_dnsmasq_port}" ] && set_cache_var "ACL_${sid}_dns_port" "${_dnsmasq_port}"
|
||||
fi
|
||||
else
|
||||
config_file="acl/${tcp_node}_SOCKS_${socks_port}.json"
|
||||
run_socks flag=$tcp_node node=$tcp_node bind=127.0.0.1 socks_port=$socks_port config_file=$config_file
|
||||
local log_file=$TMP_ACL_PATH/ipt2socks_${tcp_node}_${redir_port}.log
|
||||
log_file="/dev/null"
|
||||
run_ipt2socks flag=acl_${tcp_node} tcp_tproxy=${is_tproxy} local_port=$redir_port socks_address=127.0.0.1 socks_port=$socks_port log_file=$log_file
|
||||
socks_port=$(get_new_port $(expr $socks_port + 1))
|
||||
set_cache_var "node_${tcp_node}_socks_port" "${socks_port}"
|
||||
redir_port=$(get_new_port $(expr $redir_port + 1))
|
||||
set_cache_var "node_${tcp_node}_redir_port" "${redir_port}"
|
||||
tcp_port=$redir_port
|
||||
|
||||
local type=$(echo $(config_n_get $tcp_node type) | tr 'A-Z' 'a-z')
|
||||
if [ -n "${type}" ] && ([ "${type}" = "sing-box" ] || [ "${type}" = "xray" ]); then
|
||||
config_file="acl/${tcp_node}_TCP_${redir_port}.json"
|
||||
_extra_param="socks_address=127.0.0.1 socks_port=$socks_port"
|
||||
if [ "$dns_mode" = "sing-box" ] || [ "$dns_mode" = "xray" ]; then
|
||||
dns_port=$(get_new_port $(expr $dns_port + 1))
|
||||
_dns_port=$dns_port
|
||||
config_file=$(echo $config_file | sed "s/TCP_/DNS_${_dns_port}_TCP_/g")
|
||||
remote_dns_doh=${remote_dns}
|
||||
dnsmasq_filter_proxy_ipv6=0
|
||||
[ "$dns_mode" = "xray" ] && [ "$v2ray_dns_mode" = "tcp+doh" ] && remote_dns_doh=${remote_dns_doh:-https://1.1.1.1/dns-query}
|
||||
_extra_param="dns_listen_port=${_dns_port} remote_dns_protocol=${v2ray_dns_mode} remote_dns_tcp_server=${remote_dns} remote_dns_doh=${remote_dns_doh} remote_dns_query_strategy=${DNS_QUERY_STRATEGY} dns_client_ip=${dns_client_ip} dns_query_strategy=${DNS_QUERY_STRATEGY}"
|
||||
fi
|
||||
[ -n "$udp_node" ] && ([ "$udp_node" = "tcp" ] || [ "$udp_node" = "$tcp_node" ]) && {
|
||||
config_file=$(echo $config_file | sed "s/TCP_/TCP_UDP_/g")
|
||||
_extra_param="${_extra_param} udp_redir_port=$redir_port"
|
||||
}
|
||||
config_file="$TMP_PATH/$config_file"
|
||||
[ "${type}" = "sing-box" ] && type="singbox"
|
||||
run_${type} flag=$tcp_node node=$tcp_node tcp_redir_port=$redir_port ${_extra_param} config_file=$config_file
|
||||
else
|
||||
config_file="acl/${tcp_node}_SOCKS_${socks_port}.json"
|
||||
run_socks flag=$tcp_node node=$tcp_node bind=127.0.0.1 socks_port=$socks_port config_file=$config_file
|
||||
local log_file=$TMP_ACL_PATH/ipt2socks_${tcp_node}_${redir_port}.log
|
||||
log_file="/dev/null"
|
||||
run_ipt2socks flag=acl_${tcp_node} tcp_tproxy=${is_tproxy} local_port=$redir_port socks_address=127.0.0.1 socks_port=$socks_port log_file=$log_file
|
||||
fi
|
||||
run_dns ${_dns_port}
|
||||
fi
|
||||
run_dns ${_dns_port}
|
||||
set_cache_var "ACL_${sid}_tcp_node" "${tcp_node}"
|
||||
set_cache_var "ACL_${sid}_tcp_redir_port" "${redir_port}"
|
||||
fi
|
||||
set_cache_var "ACL_${sid}_tcp_node" "${tcp_node}"
|
||||
}
|
||||
fi
|
||||
set_cache_var "ACL_${sid}_tcp_port" "${tcp_port}"
|
||||
}
|
||||
[ "$udp_node" != "nil" ] && {
|
||||
[ "$udp_node" = "tcp" ] && udp_node=$tcp_node
|
||||
[ -n "$udp_node" ] && {
|
||||
if [ "$udp_node" = "default" ]; then
|
||||
if [ "$TCP_UDP" = "0" ] && [ "$UDP_NODE" = "nil" ]; then
|
||||
udp_node="nil"
|
||||
unset udp_port
|
||||
elif [ "$TCP_UDP" = "1" ] && [ "$udp_node" = "nil" ]; then
|
||||
udp_node=$TCP_NODE
|
||||
udp_port=$TCP_REDIR_PORT
|
||||
local GLOBAL_UDP_NODE=$(get_cache_var "ACL_GLOBAL_UDP_node")
|
||||
[ -n "${GLOBAL_UDP_NODE}" ] && GLOBAL_UDP_redir_port=$(get_cache_var "ACL_GLOBAL_UDP_redir_port")
|
||||
if [ -n "${GLOBAL_UDP_NODE}" ]; then
|
||||
set_cache_var "ACL_${sid}_udp_node" "${GLOBAL_UDP_NODE}"
|
||||
set_cache_var "ACL_${sid}_udp_redir_port" "${GLOBAL_UDP_redir_port}"
|
||||
set_cache_var "ACL_${sid}_udp_default" "1"
|
||||
else
|
||||
udp_node=$UDP_NODE
|
||||
udp_port=$UDP_REDIR_PORT
|
||||
echolog " - 全局节点未启用,跳过【${remarks}】"
|
||||
fi
|
||||
elif [ "$udp_node" = "$tcp_node" ]; then
|
||||
udp_node=$tcp_node
|
||||
udp_port=$tcp_port
|
||||
elif [ "$udp_node" = "tcp" ]; then
|
||||
udp_node=$(get_cache_var "ACL_${sid}_tcp_node")
|
||||
udp_port=$(get_cache_var "ACL_${sid}_tcp_port")
|
||||
set_cache_var "ACL_${sid}_udp_node" "${udp_node}"
|
||||
set_cache_var "ACL_${sid}_udp_redir_port" "${udp_port}"
|
||||
else
|
||||
[ "$(config_get_type $udp_node nil)" = "nodes" ] && {
|
||||
if [ "$udp_node" = "$UDP_NODE" ]; then
|
||||
udp_port=$UDP_REDIR_PORT
|
||||
[ "$(config_get_type $udp_node)" = "nodes" ] && {
|
||||
if [ -n "${GLOBAL_UDP_NODE}" ] && [ "$udp_node" = "${GLOBAL_UDP_NODE}" ]; then
|
||||
set_cache_var "ACL_${sid}_udp_node" "${GLOBAL_UDP_NODE}"
|
||||
set_cache_var "ACL_${sid}_udp_redir_port" "${GLOBAL_UDP_redir_port}"
|
||||
set_cache_var "ACL_${sid}_udp_default" "1"
|
||||
else
|
||||
_redir_port=$(eval echo \${node_${udp_node}_redir_port})
|
||||
_socks_port=$(eval echo \${node_${udp_node}_socks_port})
|
||||
_redir_port=$(get_cache_var "node_${udp_node}_redir_port")
|
||||
_socks_port=$(get_cache_var "node_${udp_node}_socks_port")
|
||||
if [ -n "${_socks_port}" ] && [ -n "${_redir_port}" ]; then
|
||||
socks_port=${_socks_port}
|
||||
udp_port=${_redir_port}
|
||||
else
|
||||
socks_port=$(get_new_port $(expr $socks_port + 1))
|
||||
eval node_${udp_node}_socks_port=$socks_port
|
||||
set_cache_var "node_${udp_node}_socks_port" "${socks_port}"
|
||||
redir_port=$(get_new_port $(expr $redir_port + 1))
|
||||
eval node_${udp_node}_redir_port=$redir_port
|
||||
set_cache_var "node_${udp_node}_redir_port" "${redir_port}"
|
||||
udp_port=$redir_port
|
||||
|
||||
local type=$(echo $(config_n_get $udp_node type) | tr 'A-Z' 'a-z')
|
||||
@@ -1904,12 +1950,12 @@ acl_app() {
|
||||
fi
|
||||
fi
|
||||
set_cache_var "ACL_${sid}_udp_node" "${udp_node}"
|
||||
set_cache_var "ACL_${sid}_udp_redir_port" "${redir_port}"
|
||||
fi
|
||||
}
|
||||
fi
|
||||
set_cache_var "ACL_${sid}_udp_port" "${udp_port}"
|
||||
}
|
||||
unset enabled sid remarks sources interface use_global_config tcp_node udp_node use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode filter_proxy_ipv6 dns_mode remote_dns v2ray_dns_mode remote_dns_doh dns_client_ip
|
||||
unset enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports use_global_config tcp_node udp_node use_direct_list use_proxy_list use_block_list use_gfw_list chn_list tcp_proxy_mode udp_proxy_mode filter_proxy_ipv6 dns_mode remote_dns v2ray_dns_mode remote_dns_doh dns_client_ip
|
||||
unset _ip _mac _iprange _ipset _ip_or_mac source_list tcp_port udp_port config_file _extra_param
|
||||
unset _china_ng_listen _chinadns_local_dns _direct_dns_mode chinadns_ng_default_tag dnsmasq_filter_proxy_ipv6
|
||||
done
|
||||
@@ -2013,9 +2059,9 @@ stop() {
|
||||
ENABLED=$(config_t_get global enabled 0)
|
||||
SOCKS_ENABLED=$(config_t_get global socks_enabled 0)
|
||||
TCP_REDIR_PORT=1041
|
||||
TCP_NODE=$(config_t_get global tcp_node nil)
|
||||
TCP_NODE=$(config_t_get global tcp_node)
|
||||
UDP_REDIR_PORT=1051
|
||||
UDP_NODE=$(config_t_get global udp_node nil)
|
||||
UDP_NODE=$(config_t_get global udp_node)
|
||||
TCP_UDP=0
|
||||
if [ "$UDP_NODE" == "tcp" ]; then
|
||||
UDP_NODE=$TCP_NODE
|
||||
@@ -2024,8 +2070,8 @@ elif [ "$UDP_NODE" == "$TCP_NODE" ]; then
|
||||
TCP_UDP=1
|
||||
fi
|
||||
[ "$ENABLED" == 1 ] && {
|
||||
[ "$TCP_NODE" != "nil" ] && [ "$(config_get_type $TCP_NODE nil)" != "nil" ] && ENABLED_DEFAULT_ACL=1
|
||||
[ "$UDP_NODE" != "nil" ] && [ "$(config_get_type $UDP_NODE nil)" != "nil" ] && ENABLED_DEFAULT_ACL=1
|
||||
[ -n "$TCP_NODE" ] && [ "$(config_get_type $TCP_NODE)" == "nodes" ] && ENABLED_DEFAULT_ACL=1
|
||||
[ -n "$UDP_NODE" ] && [ "$(config_get_type $UDP_NODE)" == "nodes" ] && ENABLED_DEFAULT_ACL=1
|
||||
}
|
||||
ENABLED_ACLS=$(config_t_get global acl_enable 0)
|
||||
[ "$ENABLED_ACLS" == 1 ] && {
|
||||
|
||||
@@ -307,8 +307,8 @@ if uci:get(appname, TCP_NODE, "protocol") == "_shunt" then
|
||||
local t = uci:get_all(appname, TCP_NODE)
|
||||
local default_node_id = t["default_node"] or "_direct"
|
||||
uci:foreach(appname, "shunt_rules", function(s)
|
||||
local _node_id = t[s[".name"]] or "nil"
|
||||
if _node_id ~= "nil" and _node_id ~= "_blackhole" then
|
||||
local _node_id = t[s[".name"]]
|
||||
if _node_id and _node_id ~= "_blackhole" then
|
||||
if _node_id == "_default" then
|
||||
_node_id = default_node_id
|
||||
end
|
||||
|
||||
@@ -119,7 +119,6 @@ end
|
||||
|
||||
function copy_instance(var)
|
||||
local LISTEN_PORT = var["-LISTEN_PORT"]
|
||||
local DNSMASQ_CONF = var["-DNSMASQ_CONF"]
|
||||
local conf_lines = {}
|
||||
local DEFAULT_DNSMASQ_CFGID = sys.exec("echo -n $(uci -q show dhcp.@dnsmasq[0] | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')")
|
||||
for line in io.lines("/tmp/etc/dnsmasq.conf." .. DEFAULT_DNSMASQ_CFGID) do
|
||||
@@ -127,14 +126,19 @@ function copy_instance(var)
|
||||
if line:find("passwall") then filter = true end
|
||||
if line:find("ubus") then filter = true end
|
||||
if line:find("dhcp") then filter = true end
|
||||
if line:find("server") then filter = true end
|
||||
if line:find("port") then filter = true end
|
||||
if line:find("server=") == 1 then filter = true end
|
||||
if line:find("port=") == 1 then filter = true end
|
||||
if line:find("address=") == 1 or (line:find("server=") == 1 and line:find("/")) then filter = nil end
|
||||
if not filter then
|
||||
tinsert(conf_lines, line)
|
||||
end
|
||||
end
|
||||
tinsert(conf_lines, "port=" .. LISTEN_PORT)
|
||||
if var["-return_table"] == "1" then
|
||||
return conf_lines
|
||||
end
|
||||
if #conf_lines > 0 then
|
||||
local DNSMASQ_CONF = var["-DNSMASQ_CONF"]
|
||||
local conf_out = io.open(DNSMASQ_CONF, "a")
|
||||
conf_out:write(table.concat(conf_lines, "\n"))
|
||||
conf_out:close()
|
||||
@@ -498,8 +502,8 @@ function add_rule(var)
|
||||
local t = uci:get_all(appname, TCP_NODE)
|
||||
local default_node_id = t["default_node"] or "_direct"
|
||||
uci:foreach(appname, "shunt_rules", function(s)
|
||||
local _node_id = t[s[".name"]] or "nil"
|
||||
if _node_id ~= "nil" and _node_id ~= "_blackhole" then
|
||||
local _node_id = t[s[".name"]]
|
||||
if _node_id and _node_id ~= "_blackhole" then
|
||||
if _node_id == "_default" then
|
||||
_node_id = default_node_id
|
||||
end
|
||||
@@ -615,19 +619,7 @@ function add_rule(var)
|
||||
local conf_lines = {}
|
||||
if LISTEN_PORT then
|
||||
--Copy dnsmasq instance
|
||||
local DEFAULT_DNSMASQ_CFGID = sys.exec("echo -n $(uci -q show dhcp.@dnsmasq[0] | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')")
|
||||
for line in io.lines("/tmp/etc/dnsmasq.conf." .. DEFAULT_DNSMASQ_CFGID) do
|
||||
local filter
|
||||
if line:find("passwall") then filter = true end
|
||||
if line:find("ubus") then filter = true end
|
||||
if line:find("dhcp") then filter = true end
|
||||
if line:find("server") then filter = true end
|
||||
if line:find("port") then filter = true end
|
||||
if not filter then
|
||||
tinsert(conf_lines, line)
|
||||
end
|
||||
end
|
||||
tinsert(conf_lines, "port=" .. LISTEN_PORT)
|
||||
conf_lines = copy_instance({["-LISTEN_PORT"] = LISTEN_PORT, ["-return_table"] = "1"})
|
||||
else
|
||||
--Modify the default dnsmasq service
|
||||
end
|
||||
|
||||
@@ -450,8 +450,8 @@ if uci:get(appname, TCP_NODE, "protocol") == "_shunt" then
|
||||
local t = uci:get_all(appname, TCP_NODE)
|
||||
local default_node_id = t["default_node"] or "_direct"
|
||||
uci:foreach(appname, "shunt_rules", function(s)
|
||||
local _node_id = t[s[".name"]] or "nil"
|
||||
if _node_id ~= "nil" and _node_id ~= "_blackhole" then
|
||||
local _node_id = t[s[".name"]]
|
||||
if _node_id and _node_id ~= "_blackhole" then
|
||||
if _node_id == "_default" then
|
||||
_node_id = default_node_id
|
||||
end
|
||||
|
||||
@@ -198,8 +198,6 @@ load_acl() {
|
||||
udp_proxy_drop_ports=${udp_proxy_drop_ports:-default}
|
||||
tcp_redir_ports=${tcp_redir_ports:-default}
|
||||
udp_redir_ports=${udp_redir_ports:-default}
|
||||
tcp_node=${tcp_node:-nil}
|
||||
udp_node=${udp_node:-nil}
|
||||
use_direct_list=${use_direct_list:-1}
|
||||
use_proxy_list=${use_proxy_list:-1}
|
||||
use_block_list=${use_block_list:-1}
|
||||
@@ -215,25 +213,17 @@ load_acl() {
|
||||
[ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS
|
||||
|
||||
[ -n "$(get_cache_var "ACL_${sid}_tcp_node")" ] && tcp_node=$(get_cache_var "ACL_${sid}_tcp_node")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_tcp_redir_port")" ] && tcp_port=$(get_cache_var "ACL_${sid}_tcp_redir_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_udp_node")" ] && udp_node=$(get_cache_var "ACL_${sid}_udp_node")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_tcp_port")" ] && tcp_port=$(get_cache_var "ACL_${sid}_tcp_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_udp_port")" ] && udp_port=$(get_cache_var "ACL_${sid}_udp_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_udp_redir_port")" ] && udp_port=$(get_cache_var "ACL_${sid}_udp_redir_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_dns_port")" ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
|
||||
[ -n "$tcp_node" ] && tcp_node_remark=$(config_n_get $tcp_node remarks)
|
||||
[ -n "$udp_node" ] && udp_node_remark=$(config_n_get $udp_node remarks)
|
||||
|
||||
use_shunt_tcp=0
|
||||
use_shunt_udp=0
|
||||
[ "$tcp_node" != "nil" ] && {
|
||||
tcp_node_remark=$(config_n_get $tcp_node remarks)
|
||||
[ "$(config_n_get $tcp_node protocol)" = "_shunt" ] && use_shunt_tcp=1
|
||||
}
|
||||
[ "$udp_node" != "nil" ] && {
|
||||
udp_node_remark=$(config_n_get $udp_node remarks)
|
||||
[ "$(config_n_get $udp_node protocol)" = "_shunt" ] && use_shunt_udp=1
|
||||
}
|
||||
[ "$udp_node" == "tcp" ] && {
|
||||
udp_node_remark=$tcp_node_remark
|
||||
use_shunt_udp=$use_shunt_tcp
|
||||
}
|
||||
[ -n "$tcp_node" ] && [ "$(config_n_get $tcp_node protocol)" = "_shunt" ] && use_shunt_tcp=1
|
||||
[ -n "$udp_node" ] && [ "$(config_n_get $udp_node protocol)" = "_shunt" ] && use_shunt_udp=1
|
||||
|
||||
[ "${use_global_config}" = "1" ] && {
|
||||
tcp_node_remark=$(config_n_get $TCP_NODE remarks)
|
||||
@@ -503,7 +493,7 @@ load_acl() {
|
||||
|
||||
local DNS_REDIRECT
|
||||
[ $(config_t_get global dns_redirect "1") = "1" ] && DNS_REDIRECT=53
|
||||
if ([ "$TCP_NODE" != "nil" ] && [ -n "${TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${UDP_PROXY_MODE}" ]); then
|
||||
if ([ -n "$TCP_NODE" ] && [ -n "${TCP_PROXY_MODE}" ]) || ([ -n "$UDP_NODE" ] && [ -n "${UDP_PROXY_MODE}" ]); then
|
||||
[ -n "${DNS_REDIRECT_PORT}" ] && DNS_REDIRECT=${DNS_REDIRECT_PORT}
|
||||
else
|
||||
[ -n "${DIRECT_DNSMASQ_PORT}" ] && DNS_REDIRECT=${DIRECT_DNSMASQ_PORT}
|
||||
@@ -566,7 +556,7 @@ load_acl() {
|
||||
|
||||
# 加载TCP默认代理模式
|
||||
if [ -n "${TCP_PROXY_MODE}" ]; then
|
||||
[ "$TCP_NODE" != "nil" ] && {
|
||||
[ -n "$TCP_NODE" ] && {
|
||||
msg2="${msg}使用 TCP 节点[$(config_n_get $TCP_NODE remarks)]"
|
||||
if [ -n "${is_tproxy}" ]; then
|
||||
msg2="${msg2}(TPROXY:${TCP_REDIR_PORT})"
|
||||
@@ -619,7 +609,7 @@ load_acl() {
|
||||
|
||||
# 加载UDP默认代理模式
|
||||
if [ -n "${UDP_PROXY_MODE}" ]; then
|
||||
[ "$UDP_NODE" != "nil" -o "$TCP_UDP" = "1" ] && {
|
||||
[ -n "$UDP_NODE" -o "$TCP_UDP" = "1" ] && {
|
||||
msg2="${msg}使用 UDP 节点[$(config_n_get $UDP_NODE remarks)](TPROXY:${UDP_REDIR_PORT})"
|
||||
|
||||
$ipt_m -A PSW $(comment "默认") -p udp -d $FAKE_IP -j PSW_RULE
|
||||
@@ -686,7 +676,7 @@ filter_server_port() {
|
||||
filter_node() {
|
||||
local node=${1}
|
||||
local stream=${2}
|
||||
if [ -n "$node" ] && [ "$node" != "nil" ]; then
|
||||
if [ -n "$node" ]; then
|
||||
local address=$(config_n_get $node address)
|
||||
local port=$(config_n_get $node port)
|
||||
[ -z "$address" ] && [ -z "$port" ] && {
|
||||
@@ -736,12 +726,12 @@ add_firewall_rule() {
|
||||
local USE_PROXY_LIST_ALL=${USE_PROXY_LIST}
|
||||
local USE_DIRECT_LIST_ALL=${USE_DIRECT_LIST}
|
||||
local USE_BLOCK_LIST_ALL=${USE_BLOCK_LIST}
|
||||
local _TCP_NODE=$(config_t_get global tcp_node nil)
|
||||
local _UDP_NODE=$(config_t_get global udp_node nil)
|
||||
local _TCP_NODE=$(config_t_get global tcp_node)
|
||||
local _UDP_NODE=$(config_t_get global udp_node)
|
||||
local USE_GEOVIEW=$(config_t_get global_rules enable_geoview)
|
||||
|
||||
[ "$_TCP_NODE" != "nil" ] && [ "$(config_n_get $_TCP_NODE protocol)" = "_shunt" ] && USE_SHUNT_TCP=1 && USE_SHUNT_NODE=1
|
||||
[ "$_UDP_NODE" != "nil" ] && [ "$(config_n_get $_UDP_NODE protocol)" = "_shunt" ] && USE_SHUNT_UDP=1 && USE_SHUNT_NODE=1
|
||||
[ -n "$_TCP_NODE" ] && [ "$(config_n_get $_TCP_NODE protocol)" = "_shunt" ] && USE_SHUNT_TCP=1 && USE_SHUNT_NODE=1
|
||||
[ -n "$_UDP_NODE" ] && [ "$(config_n_get $_UDP_NODE protocol)" = "_shunt" ] && USE_SHUNT_UDP=1 && USE_SHUNT_NODE=1
|
||||
[ "$_UDP_NODE" = "tcp" ] && USE_SHUNT_UDP=$USE_SHUNT_TCP
|
||||
|
||||
for acl_section in $(uci show ${CONFIG} | grep "=acl_rule" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
|
||||
@@ -1012,7 +1002,7 @@ add_firewall_rule() {
|
||||
ip -6 rule add fwmark 1 table 100
|
||||
ip -6 route add local ::/0 dev lo table 100
|
||||
|
||||
[ "$TCP_UDP" = "1" ] && [ "$UDP_NODE" = "nil" ] && UDP_NODE=$TCP_NODE
|
||||
[ "$TCP_UDP" = "1" ] && [ -z "$UDP_NODE" ] && UDP_NODE=$TCP_NODE
|
||||
|
||||
[ "$ENABLED_DEFAULT_ACL" == 1 ] && {
|
||||
local ipt_tmp=$ipt_n
|
||||
@@ -1046,7 +1036,7 @@ add_firewall_rule() {
|
||||
fi
|
||||
}
|
||||
|
||||
if ([ "$TCP_NODE" != "nil" ] && [ -n "${LOCALHOST_TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then
|
||||
if ([ -n "$TCP_NODE" ] && [ -n "${LOCALHOST_TCP_PROXY_MODE}" ]) || ([ -n "$UDP_NODE" ] && [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then
|
||||
[ -n "$DNS_REDIRECT_PORT" ] && {
|
||||
$ipt_n -A OUTPUT $(comment "PSW") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
|
||||
$ip6t_n -A OUTPUT $(comment "PSW") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
|
||||
@@ -1078,7 +1068,7 @@ add_firewall_rule() {
|
||||
}
|
||||
|
||||
# 加载路由器自身代理 TCP
|
||||
if [ "$TCP_NODE" != "nil" ]; then
|
||||
if [ -n "$TCP_NODE" ]; then
|
||||
_proxy_tcp_access() {
|
||||
[ -n "${2}" ] || return 0
|
||||
if echo "${2}" | grep -q -v ':'; then
|
||||
@@ -1156,7 +1146,7 @@ add_firewall_rule() {
|
||||
fi
|
||||
|
||||
# 加载路由器自身代理 UDP
|
||||
if [ "$UDP_NODE" != "nil" -o "$TCP_UDP" = "1" ]; then
|
||||
if [ -n "$UDP_NODE" -o "$TCP_UDP" = "1" ]; then
|
||||
_proxy_udp_access() {
|
||||
[ -n "${2}" ] || return 0
|
||||
if echo "${2}" | grep -q -v ':'; then
|
||||
|
||||
@@ -258,8 +258,6 @@ load_acl() {
|
||||
udp_proxy_drop_ports=${udp_proxy_drop_ports:-default}
|
||||
tcp_redir_ports=${tcp_redir_ports:-default}
|
||||
udp_redir_ports=${udp_redir_ports:-default}
|
||||
tcp_node=${tcp_node:-nil}
|
||||
udp_node=${udp_node:-nil}
|
||||
use_direct_list=${use_direct_list:-1}
|
||||
use_proxy_list=${use_proxy_list:-1}
|
||||
use_block_list=${use_block_list:-1}
|
||||
@@ -275,25 +273,17 @@ load_acl() {
|
||||
[ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS
|
||||
|
||||
[ -n "$(get_cache_var "ACL_${sid}_tcp_node")" ] && tcp_node=$(get_cache_var "ACL_${sid}_tcp_node")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_tcp_redir_port")" ] && tcp_port=$(get_cache_var "ACL_${sid}_tcp_redir_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_udp_node")" ] && udp_node=$(get_cache_var "ACL_${sid}_udp_node")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_tcp_port")" ] && tcp_port=$(get_cache_var "ACL_${sid}_tcp_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_udp_port")" ] && udp_port=$(get_cache_var "ACL_${sid}_udp_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_udp_redir_port")" ] && udp_port=$(get_cache_var "ACL_${sid}_udp_redir_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_dns_port")" ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
|
||||
[ -n "$tcp_node" ] && tcp_node_remark=$(config_n_get $tcp_node remarks)
|
||||
[ -n "$udp_node" ] && udp_node_remark=$(config_n_get $udp_node remarks)
|
||||
|
||||
use_shunt_tcp=0
|
||||
use_shunt_udp=0
|
||||
[ "$tcp_node" != "nil" ] && {
|
||||
tcp_node_remark=$(config_n_get $tcp_node remarks)
|
||||
[ "$(config_n_get $tcp_node protocol)" = "_shunt" ] && use_shunt_tcp=1
|
||||
}
|
||||
[ "$udp_node" != "nil" ] && {
|
||||
udp_node_remark=$(config_n_get $udp_node remarks)
|
||||
[ "$(config_n_get $udp_node protocol)" = "_shunt" ] && use_shunt_udp=1
|
||||
}
|
||||
[ "$udp_node" == "tcp" ] && {
|
||||
udp_node_remark=$tcp_node_remark
|
||||
use_shunt_udp=$use_shunt_tcp
|
||||
}
|
||||
[ -n "$tcp_node" ] && [ "$(config_n_get $tcp_node protocol)" = "_shunt" ] && use_shunt_tcp=1
|
||||
[ -n "$udp_node" ] && [ "$(config_n_get $udp_node protocol)" = "_shunt" ] && use_shunt_udp=1
|
||||
|
||||
[ "${use_global_config}" = "1" ] && {
|
||||
tcp_node_remark=$(config_n_get $TCP_NODE remarks)
|
||||
@@ -556,7 +546,7 @@ load_acl() {
|
||||
|
||||
local DNS_REDIRECT
|
||||
[ $(config_t_get global dns_redirect "1") = "1" ] && DNS_REDIRECT=53
|
||||
if ([ "$TCP_NODE" != "nil" ] && [ -n "${TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${UDP_PROXY_MODE}" ]); then
|
||||
if ([ -n "$TCP_NODE" ] && [ -n "${TCP_PROXY_MODE}" ]) || ([ -n "$UDP_NODE" ] && [ -n "${UDP_PROXY_MODE}" ]); then
|
||||
[ -n "${DNS_REDIRECT_PORT}" ] && DNS_REDIRECT=${DNS_REDIRECT_PORT}
|
||||
else
|
||||
[ -n "${DIRECT_DNSMASQ_PORT}" ] && DNS_REDIRECT=${DIRECT_DNSMASQ_PORT}
|
||||
@@ -621,7 +611,7 @@ load_acl() {
|
||||
|
||||
# 加载TCP默认代理模式
|
||||
if [ -n "${TCP_PROXY_MODE}" ]; then
|
||||
[ "$TCP_NODE" != "nil" ] && {
|
||||
[ -n "$TCP_NODE" ] && {
|
||||
msg2="${msg}使用 TCP 节点[$(config_n_get $TCP_NODE remarks)]"
|
||||
if [ -n "${is_tproxy}" ]; then
|
||||
msg2="${msg2}(TPROXY:${TCP_REDIR_PORT})"
|
||||
@@ -679,7 +669,7 @@ load_acl() {
|
||||
|
||||
# 加载UDP默认代理模式
|
||||
if [ -n "${UDP_PROXY_MODE}" ]; then
|
||||
[ "$UDP_NODE" != "nil" -o "$TCP_UDP" = "1" ] && {
|
||||
[ -n "$UDP_NODE" -o "$TCP_UDP" = "1" ] && {
|
||||
msg2="${msg}使用 UDP 节点[$(config_n_get $UDP_NODE remarks)](TPROXY:${UDP_REDIR_PORT})"
|
||||
|
||||
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW_RULE comment \"默认\""
|
||||
@@ -753,7 +743,7 @@ filter_server_port() {
|
||||
filter_node() {
|
||||
local node=${1}
|
||||
local stream=${2}
|
||||
if [ -n "$node" ] && [ "$node" != "nil" ]; then
|
||||
if [ -n "$node" ]; then
|
||||
local address=$(config_n_get $node address)
|
||||
local port=$(config_n_get $node port)
|
||||
[ -z "$address" ] && [ -z "$port" ] && {
|
||||
@@ -811,12 +801,12 @@ add_firewall_rule() {
|
||||
local USE_PROXY_LIST_ALL=${USE_PROXY_LIST}
|
||||
local USE_DIRECT_LIST_ALL=${USE_DIRECT_LIST}
|
||||
local USE_BLOCK_LIST_ALL=${USE_BLOCK_LIST}
|
||||
local _TCP_NODE=$(config_t_get global tcp_node nil)
|
||||
local _UDP_NODE=$(config_t_get global udp_node nil)
|
||||
local _TCP_NODE=$(config_t_get global tcp_node)
|
||||
local _UDP_NODE=$(config_t_get global udp_node)
|
||||
local USE_GEOVIEW=$(config_t_get global_rules enable_geoview)
|
||||
|
||||
[ "$_TCP_NODE" != "nil" ] && [ "$(config_n_get $_TCP_NODE protocol)" = "_shunt" ] && USE_SHUNT_TCP=1 && USE_SHUNT_NODE=1
|
||||
[ "$_UDP_NODE" != "nil" ] && [ "$(config_n_get $_UDP_NODE protocol)" = "_shunt" ] && USE_SHUNT_UDP=1 && USE_SHUNT_NODE=1
|
||||
[ -n "$_TCP_NODE" ] && [ "$(config_n_get $_TCP_NODE protocol)" = "_shunt" ] && USE_SHUNT_TCP=1 && USE_SHUNT_NODE=1
|
||||
[ -n "$_UDP_NODE" ] && [ "$(config_n_get $_UDP_NODE protocol)" = "_shunt" ] && USE_SHUNT_UDP=1 && USE_SHUNT_NODE=1
|
||||
[ "$_UDP_NODE" = "tcp" ] && USE_SHUNT_UDP=$USE_SHUNT_TCP
|
||||
|
||||
for acl_section in $(uci show ${CONFIG} | grep "=acl_rule" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
|
||||
@@ -1077,7 +1067,7 @@ add_firewall_rule() {
|
||||
ip -6 route add local ::/0 dev lo table 100
|
||||
}
|
||||
|
||||
[ "$TCP_UDP" = "1" ] && [ "$UDP_NODE" = "nil" ] && UDP_NODE=$TCP_NODE
|
||||
[ "$TCP_UDP" = "1" ] && [ -z "$UDP_NODE" ] && UDP_NODE=$TCP_NODE
|
||||
|
||||
[ "$ENABLED_DEFAULT_ACL" == 1 ] && {
|
||||
msg="【路由器本机】,"
|
||||
@@ -1104,7 +1094,7 @@ add_firewall_rule() {
|
||||
fi
|
||||
}
|
||||
|
||||
if ([ "$TCP_NODE" != "nil" ] && [ -n "${LOCALHOST_TCP_PROXY_MODE}" ]) || ([ "$UDP_NODE" != "nil" ] && [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then
|
||||
if ([ -n "$TCP_NODE" ] && [ -n "${LOCALHOST_TCP_PROXY_MODE}" ]) || ([ -n "$UDP_NODE" ] && [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then
|
||||
[ -n "$DNS_REDIRECT_PORT" ] && {
|
||||
nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW\""
|
||||
nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW\""
|
||||
@@ -1136,7 +1126,7 @@ add_firewall_rule() {
|
||||
}
|
||||
|
||||
# 加载路由器自身代理 TCP
|
||||
if [ "$TCP_NODE" != "nil" ]; then
|
||||
if [ -n "$TCP_NODE" ]; then
|
||||
_proxy_tcp_access() {
|
||||
[ -n "${2}" ] || return 0
|
||||
if echo "${2}" | grep -q -v ':'; then
|
||||
@@ -1219,7 +1209,7 @@ add_firewall_rule() {
|
||||
fi
|
||||
|
||||
# 加载路由器自身代理 UDP
|
||||
if [ "$UDP_NODE" != "nil" -o "$TCP_UDP" = "1" ]; then
|
||||
if [ -n "$UDP_NODE" -o "$TCP_UDP" = "1" ]; then
|
||||
_proxy_udp_access() {
|
||||
[ -n "${2}" ] || return 0
|
||||
if echo "${2}" | grep -q -v ':'; then
|
||||
|
||||
@@ -61,8 +61,8 @@ test_proxy() {
|
||||
|
||||
test_node() {
|
||||
local node_id=$1
|
||||
local _type=$(echo $(config_n_get ${node_id} type nil) | tr 'A-Z' 'a-z')
|
||||
[ "${_type}" != "nil" ] && {
|
||||
local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z')
|
||||
[ -n "${_type}" ] && {
|
||||
local _tmp_port=$(/usr/share/${CONFIG}/app.sh get_new_port 61080 tcp,udp)
|
||||
/usr/share/${CONFIG}/app.sh run_socks flag="test_node_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=test_node_${node_id}.json
|
||||
local curlx="socks5h://127.0.0.1:${_tmp_port}"
|
||||
@@ -101,7 +101,7 @@ test_auto_switch() {
|
||||
fi
|
||||
|
||||
#检测主节点是否能使用
|
||||
if [ "$restore_switch" == "1" ] && [ "$main_node" != "nil" ] && [ "$now_node" != "$main_node" ]; then
|
||||
if [ "$restore_switch" == "1" ] && [ -n "$main_node" ] && [ "$now_node" != "$main_node" ]; then
|
||||
test_node ${main_node}
|
||||
[ $? -eq 0 ] && {
|
||||
#主节点正常,切换到主节点
|
||||
@@ -159,7 +159,7 @@ start() {
|
||||
LOCK_FILE=${LOCK_FILE_DIR}/${CONFIG}_socks_auto_switch_${id}.lock
|
||||
LOG_EVENT_FILTER=$(uci -q get "${CONFIG}.global[0].log_event_filter" 2>/dev/null)
|
||||
LOG_EVENT_CMD=$(uci -q get "${CONFIG}.global[0].log_event_cmd" 2>/dev/null)
|
||||
main_node=$(config_n_get $id node nil)
|
||||
main_node=$(config_n_get $id node)
|
||||
socks_port=$(config_n_get $id port 0)
|
||||
delay=$(config_n_get $id autoswitch_testing_time 30)
|
||||
sleep 5s
|
||||
@@ -167,8 +167,8 @@ start() {
|
||||
retry_num=$(config_n_get $id autoswitch_retry_num 1)
|
||||
restore_switch=$(config_n_get $id autoswitch_restore_switch 0)
|
||||
probe_url=$(config_n_get $id autoswitch_probe_url "https://www.google.com/generate_204")
|
||||
backup_node=$(config_n_get $id autoswitch_backup_node nil)
|
||||
while [ -n "$backup_node" -a "$backup_node" != "nil" ]; do
|
||||
backup_node=$(config_n_get $id autoswitch_backup_node)
|
||||
while [ -n "$backup_node" ]; do
|
||||
[ -f "$LOCK_FILE" ] && {
|
||||
sleep 6s
|
||||
continue
|
||||
|
||||
@@ -264,7 +264,7 @@ do
|
||||
currentNode = _node_id and uci:get_all(appname, _node_id) or nil,
|
||||
remarks = "分流" .. e.remarks .. "节点",
|
||||
set = function(o, server)
|
||||
if not server then server = "nil" end
|
||||
if not server then server = "" end
|
||||
uci:set(appname, node_id, e[".name"], server)
|
||||
o.newNodeId = server
|
||||
end
|
||||
@@ -1263,10 +1263,10 @@ local function truncate_nodes(add_from)
|
||||
if config.currentNode and config.currentNode.add_mode == "2" then
|
||||
if add_from then
|
||||
if config.currentNode.add_from and config.currentNode.add_from == add_from then
|
||||
config.set(config, "nil")
|
||||
config.set(config, "")
|
||||
end
|
||||
else
|
||||
config.set(config, "nil")
|
||||
config.set(config, "")
|
||||
end
|
||||
if config.id then
|
||||
uci:delete(appname, config.id)
|
||||
@@ -1400,7 +1400,7 @@ local function select_node(nodes, config)
|
||||
config.set(config, server)
|
||||
end
|
||||
else
|
||||
config.set(config, "nil")
|
||||
config.set(config, "")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -30,6 +30,33 @@ do
|
||||
|
||||
if [ "$CFG_UPDATE_INT" -ne 0 ]; then
|
||||
|
||||
stop_week_mode=$(config_t_get global_delay stop_week_mode)
|
||||
stop_interval_mode=$(config_t_get global_delay stop_interval_mode)
|
||||
stop_interval_mode=$(expr "$stop_interval_mode" \* 60)
|
||||
if [ -n "$stop_week_mode" ]; then
|
||||
[ "$stop_week_mode" = "8" ] && {
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$stop_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG stop > /dev/null 2>&1 &
|
||||
}
|
||||
fi
|
||||
|
||||
start_week_mode=$(config_t_get global_delay start_week_mode)
|
||||
start_interval_mode=$(config_t_get global_delay start_interval_mode)
|
||||
start_interval_mode=$(expr "$start_interval_mode" \* 60)
|
||||
if [ -n "$start_week_mode" ]; then
|
||||
[ "$start_week_mode" = "8" ] && {
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$start_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG start > /dev/null 2>&1 &
|
||||
}
|
||||
fi
|
||||
|
||||
restart_week_mode=$(config_t_get global_delay restart_week_mode)
|
||||
restart_interval_mode=$(config_t_get global_delay restart_interval_mode)
|
||||
restart_interval_mode=$(expr "$restart_interval_mode" \* 60)
|
||||
if [ -n "$restart_week_mode" ]; then
|
||||
[ "$restart_week_mode" = "8" ] && {
|
||||
[ "$(expr "$CFG_UPDATE_INT" % "$restart_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG restart > /dev/null 2>&1 &
|
||||
}
|
||||
fi
|
||||
|
||||
autoupdate=$(config_t_get global_rules auto_update)
|
||||
weekupdate=$(config_t_get global_rules week_update)
|
||||
hourupdate=$(config_t_get global_rules interval_update)
|
||||
|
||||
@@ -56,8 +56,8 @@ test_proxy() {
|
||||
url_test_node() {
|
||||
result=0
|
||||
local node_id=$1
|
||||
local _type=$(echo $(config_n_get ${node_id} type nil) | tr 'A-Z' 'a-z')
|
||||
[ "${_type}" != "nil" ] && {
|
||||
local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z')
|
||||
[ -n "${_type}" ] && {
|
||||
if [ "${_type}" == "socks" ]; then
|
||||
local _address=$(config_n_get ${node_id} address)
|
||||
local _port=$(config_n_get ${node_id} port)
|
||||
@@ -85,8 +85,8 @@ url_test_node() {
|
||||
|
||||
test_node() {
|
||||
local node_id=$1
|
||||
local _type=$(echo $(config_n_get ${node_id} type nil) | tr 'A-Z' 'a-z')
|
||||
[ "${_type}" != "nil" ] && {
|
||||
local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z')
|
||||
[ -n "${_type}" ] && {
|
||||
if [ "${_type}" == "socks" ]; then
|
||||
local _address=$(config_n_get ${node_id} address)
|
||||
local _port=$(config_n_get ${node_id} port)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall2
|
||||
PKG_VERSION:=24.12.16
|
||||
PKG_VERSION:=24.12.19
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -94,6 +94,11 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
m:set(shunt_node_id, option, value)
|
||||
end
|
||||
end
|
||||
local function get_remove(shunt_node_id, option)
|
||||
return function(self, section)
|
||||
m:del(shunt_node_id, option)
|
||||
end
|
||||
end
|
||||
if #normal_list > 0 then
|
||||
for k, v in pairs(shunt_list) do
|
||||
local vid = v.id
|
||||
@@ -148,8 +153,8 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
o = s:taboption("Main", ListValue, node_option, string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", id), e.remarks))
|
||||
o.cfgvalue = get_cfgvalue(v.id, id)
|
||||
o.write = get_write(v.id, id)
|
||||
o.remove = get_remove(v.id, id)
|
||||
o:depends("node", v.id)
|
||||
o.default = ""
|
||||
o:value("", translate("Close"))
|
||||
o:value("_default", translate("Default"))
|
||||
o:value("_direct", translate("Direct Connection"))
|
||||
@@ -158,7 +163,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
local pt = s:taboption("Main", ListValue, vid .. "-".. id .. "_proxy_tag", string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
|
||||
pt.cfgvalue = get_cfgvalue(v.id, id .. "_proxy_tag")
|
||||
pt.write = get_write(v.id, id .. "_proxy_tag")
|
||||
pt.default = ""
|
||||
pt.remove = get_remove(v.id, id .. "_proxy_tag")
|
||||
pt:value("", translate("Close"))
|
||||
pt:value("main", translate("Preproxy Node"))
|
||||
for k1, v1 in pairs(socks_list) do
|
||||
@@ -181,6 +186,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
o = s:taboption("Main", ListValue, vid .. "-" .. id, string.format('* <a style="color:red">%s</a>', translate("Default")))
|
||||
o.cfgvalue = get_cfgvalue(v.id, id)
|
||||
o.write = get_write(v.id, id)
|
||||
o.remove = get_remove(v.id, id)
|
||||
o:depends("node", v.id)
|
||||
o.default = "_direct"
|
||||
o:value("_direct", translate("Direct Connection"))
|
||||
@@ -202,6 +208,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
o = s:taboption("Main", ListValue, vid .. "-" .. id, string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
|
||||
o.cfgvalue = get_cfgvalue(v.id, id)
|
||||
o.write = get_write(v.id, id)
|
||||
o.remove = get_remove(v.id, id)
|
||||
o:value("", translate("Close"))
|
||||
o:value("main", translate("Preproxy Node"))
|
||||
for k1, v1 in pairs(normal_list) do
|
||||
|
||||
@@ -207,6 +207,28 @@ function repeat_exist(table, value)
|
||||
return false
|
||||
end
|
||||
|
||||
function remove(...)
|
||||
for index, value in ipairs({...}) do
|
||||
if value and #value > 0 and value ~= "/" then
|
||||
sys.call(string.format("rm -rf %s", value))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function is_install(package)
|
||||
if package and #package > 0 then
|
||||
local file_path = "/usr/lib/opkg/info"
|
||||
local file_ext = ".control"
|
||||
local has = sys.call("[ -d " .. file_path .. " ]")
|
||||
if has == 0 then
|
||||
file_path = "/lib/apk/packages"
|
||||
file_ext = ".list"
|
||||
end
|
||||
return sys.call(string.format('[ -s "%s/%s%s" ]', file_path, package, file_ext)) == 0
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function get_args(arg)
|
||||
local var = {}
|
||||
for i, arg_k in pairs(arg) do
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user