mirror of
https://github.com/wyx2685/V2bX.git
synced 2025-01-22 09:58:14 -05:00
feat: remote dns for sing
This commit is contained in:
parent
b85a78209a
commit
cecfffd081
@ -85,9 +85,10 @@ func serverHandle(_ *cobra.Command, _ []string) {
|
||||
return
|
||||
}
|
||||
log.Info("Nodes started")
|
||||
dns := os.Getenv("XRAY_DNS_PATH")
|
||||
xdns := os.Getenv("XRAY_DNS_PATH")
|
||||
sdns := os.Getenv("SING_DNS_PATH")
|
||||
if watch {
|
||||
err = c.Watch(config, dns, func() {
|
||||
err = c.Watch(config, xdns, sdns, func() {
|
||||
nodes.Close()
|
||||
err = vc.Close()
|
||||
if err != nil {
|
||||
|
@ -5,9 +5,10 @@ import (
|
||||
)
|
||||
|
||||
type SingConfig struct {
|
||||
LogConfig SingLogConfig `json:"Log"`
|
||||
NtpConfig SingNtpConfig `json:"NTP"`
|
||||
OriginalPath string `json:"OriginalPath"`
|
||||
LogConfig SingLogConfig `json:"Log"`
|
||||
NtpConfig SingNtpConfig `json:"NTP"`
|
||||
DnsConfigPath string `json:"DnsConfigPath"`
|
||||
OriginalPath string `json:"OriginalPath"`
|
||||
}
|
||||
|
||||
type SingLogConfig struct {
|
||||
@ -35,6 +36,7 @@ type SingOptions struct {
|
||||
EnableProxyProtocol bool `json:"EnableProxyProtocol"`
|
||||
TCPFastOpen bool `json:"EnableTFO"`
|
||||
SniffEnabled bool `json:"EnableSniff"`
|
||||
EnableDNS bool `json:"EnableDNS"`
|
||||
DomainStrategy option.DomainStrategy `json:"DomainStrategy"`
|
||||
SniffOverrideDestination bool `json:"SniffOverrideDestination"`
|
||||
FallBackConfigs *FallBackConfigForSing `json:"FallBackConfigs"`
|
||||
@ -59,6 +61,7 @@ type FallBack struct {
|
||||
|
||||
func NewSingOptions() *SingOptions {
|
||||
return &SingOptions{
|
||||
EnableDNS: false,
|
||||
EnableProxyProtocol: false,
|
||||
TCPFastOpen: false,
|
||||
SniffEnabled: true,
|
||||
|
@ -5,10 +5,12 @@ import (
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"log"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (p *Conf) Watch(filePath, dnsPath string, reload func()) error {
|
||||
func (p *Conf) Watch(filePath, xDnsPath string, sDnsPath string, reload func()) error {
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
return fmt.Errorf("new watcher error: %s", err)
|
||||
@ -28,9 +30,10 @@ func (p *Conf) Watch(filePath, dnsPath string, reload func()) error {
|
||||
pre = time.Now()
|
||||
go func() {
|
||||
time.Sleep(5 * time.Second)
|
||||
if e.Name == dnsPath {
|
||||
switch filepath.Base(strings.TrimSuffix(e.Name, "~")) {
|
||||
case filepath.Base(xDnsPath), filepath.Base(sDnsPath):
|
||||
log.Println("DNS file changed, reloading...")
|
||||
} else {
|
||||
default:
|
||||
log.Println("config dir changed, reloading...")
|
||||
}
|
||||
*p = *New()
|
||||
@ -52,8 +55,14 @@ func (p *Conf) Watch(filePath, dnsPath string, reload func()) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("watch file error: %s", err)
|
||||
}
|
||||
if dnsPath != "" {
|
||||
err = watcher.Add(path.Dir(dnsPath))
|
||||
if xDnsPath != "" {
|
||||
err = watcher.Add(path.Dir(xDnsPath))
|
||||
if err != nil {
|
||||
return fmt.Errorf("watch dns file error: %s", err)
|
||||
}
|
||||
}
|
||||
if sDnsPath != "" {
|
||||
err = watcher.Add(path.Dir(sDnsPath))
|
||||
if err != nil {
|
||||
return fmt.Errorf("watch dns file error: %s", err)
|
||||
}
|
||||
|
81
core/sing/dns.go
Normal file
81
core/sing/dns.go
Normal file
@ -0,0 +1,81 @@
|
||||
package sing
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/InazumaV/V2bX/api/panel"
|
||||
"github.com/goccy/go-json"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func updateDNSConfig(node *panel.NodeInfo) (err error) {
|
||||
dnsPath := os.Getenv("SING_DNS_PATH")
|
||||
if len(node.RawDNS.DNSJson) != 0 {
|
||||
err = saveDnsConfig(node.RawDNS.DNSJson, dnsPath)
|
||||
} else if len(node.RawDNS.DNSMap) != 0 {
|
||||
dnsConfig := DNSConfig{
|
||||
Servers: []map[string]interface{}{
|
||||
{
|
||||
"tag": "default",
|
||||
"address": "https://8.8.8.8/dns-query",
|
||||
"detour": "direct",
|
||||
},
|
||||
},
|
||||
}
|
||||
for id, value := range node.RawDNS.DNSMap {
|
||||
dnsConfig.Servers = append(dnsConfig.Servers,
|
||||
map[string]interface{}{
|
||||
"tag": id,
|
||||
"address": value["address"],
|
||||
"address_resolver": "default",
|
||||
"detour": "direct",
|
||||
},
|
||||
)
|
||||
rule := map[string]interface{}{
|
||||
"server": id,
|
||||
"disable_cache": true,
|
||||
}
|
||||
for _, ruleType := range []string{"domain_suffix", "domain_keyword", "domain_regex", "geosite"} {
|
||||
var domains []string
|
||||
for _, v := range value["domains"].([]string) {
|
||||
split := strings.SplitN(v, ":", 2)
|
||||
prefix := strings.ToLower(split[0])
|
||||
if prefix == ruleType || (prefix == "domain" && ruleType == "domain_suffix") {
|
||||
if len(split) > 1 {
|
||||
domains = append(domains, split[1])
|
||||
}
|
||||
if len(domains) > 0 {
|
||||
rule[ruleType] = domains
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dnsConfig.Rules = append(dnsConfig.Rules, rule)
|
||||
}
|
||||
dnsConfigJSON, err := json.MarshalIndent(dnsConfig, "", " ")
|
||||
if err != nil {
|
||||
log.WithField("err", err).Error("Error marshaling dnsConfig to JSON")
|
||||
return err
|
||||
}
|
||||
err = saveDnsConfig(dnsConfigJSON, dnsPath)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func saveDnsConfig(dns []byte, dnsPath string) (err error) {
|
||||
currentData, err := os.ReadFile(dnsPath)
|
||||
if err != nil {
|
||||
log.WithField("err", err).Error("Failed to read SING_DNS_PATH")
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(currentData, dns) {
|
||||
if err = os.Truncate(dnsPath, 0); err != nil {
|
||||
log.WithField("err", err).Error("Failed to clear SING DNS PATH file")
|
||||
}
|
||||
if err = os.WriteFile(dnsPath, dns, 0644); err != nil {
|
||||
log.WithField("err", err).Error("Failed to write DNS to SING DNS PATH file")
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
@ -30,6 +30,10 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
||||
if err != nil {
|
||||
return option.Inbound{}, fmt.Errorf("the listen ip not vail")
|
||||
}
|
||||
var domainStrategy option.DomainStrategy
|
||||
if c.SingOptions.EnableDNS {
|
||||
domainStrategy = c.SingOptions.DomainStrategy
|
||||
}
|
||||
listen := option.ListenOptions{
|
||||
Listen: (*option.ListenAddress)(&addr),
|
||||
ListenPort: uint16(info.Common.ServerPort),
|
||||
@ -38,7 +42,7 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
||||
InboundOptions: option.InboundOptions{
|
||||
SniffEnabled: c.SingOptions.SniffEnabled,
|
||||
SniffOverrideDestination: c.SingOptions.SniffOverrideDestination,
|
||||
DomainStrategy: c.SingOptions.DomainStrategy,
|
||||
DomainStrategy: domainStrategy,
|
||||
},
|
||||
}
|
||||
var tls option.InboundTLSOptions
|
||||
@ -203,6 +207,10 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
|
||||
}
|
||||
|
||||
func (b *Box) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
||||
err := updateDNSConfig(info)
|
||||
if err != nil {
|
||||
return fmt.Errorf("build dns error: %s", err)
|
||||
}
|
||||
c, err := getInboundOptions(tag, info, config)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -26,6 +26,11 @@ import (
|
||||
|
||||
var _ adapter.Service = (*Box)(nil)
|
||||
|
||||
type DNSConfig struct {
|
||||
Servers []map[string]interface{} `json:"servers"`
|
||||
Rules []map[string]interface{} `json:"rules"`
|
||||
}
|
||||
|
||||
type Box struct {
|
||||
createdAt time.Time
|
||||
router adapter.Router
|
||||
@ -68,6 +73,17 @@ func New(c *conf.CoreConfig) (vCore.Core, error) {
|
||||
ServerPort: c.SingConfig.NtpConfig.ServerPort,
|
||||
},
|
||||
}
|
||||
os.Setenv("SING_DNS_PATH", "")
|
||||
if c.SingConfig.DnsConfigPath != "" {
|
||||
if f, err := os.Open(c.SingConfig.DnsConfigPath); err != nil {
|
||||
log.Error("Failed to read DNS config file")
|
||||
} else {
|
||||
if err = json.NewDecoder(f).Decode(&option.DNSOptions{}); err != nil {
|
||||
log.Error("Failed to unmarshal DNS config")
|
||||
}
|
||||
}
|
||||
os.Setenv("SING_DNS_PATH", c.SingConfig.DnsConfigPath)
|
||||
}
|
||||
ctx := context.Background()
|
||||
ctx = service.ContextWithDefaultRegistry(ctx)
|
||||
ctx = pause.ContextWithDefaultManager(ctx)
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
coreConf "github.com/xtls/xray-core/infra/conf"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func updateDNSConfig(node *panel.NodeInfo) (err error) {
|
||||
@ -57,7 +56,5 @@ func saveDnsConfig(dns []byte, dnsPath string) (err error) {
|
||||
log.WithField("err", err).Error("Failed to write DNS to XRAY DNS PATH file")
|
||||
}
|
||||
}
|
||||
log.Println("reloading config")
|
||||
time.Sleep(5 * time.Second)
|
||||
return err
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
"Level": "error",
|
||||
"Timestamp": true
|
||||
},
|
||||
"DnsConfigPath": "/etc/V2bX/dns.json",
|
||||
"NTP": {
|
||||
"Enable": true,
|
||||
"Server": "time.apple.com",
|
||||
@ -28,6 +29,7 @@
|
||||
"ListenIP": "0.0.0.0",
|
||||
"SendIP": "0.0.0.0",
|
||||
"EnableProxyProtocol": false,
|
||||
"EnableDNS": true
|
||||
"DomainStrategy": "ipv4_only",
|
||||
"LimitConfig": {
|
||||
"EnableRealtime": false,
|
||||
|
@ -26,6 +26,7 @@
|
||||
"Server": "time.apple.com",
|
||||
"ServerPort": 0
|
||||
},
|
||||
"DnsConfigPath": "/etc/V2bX/dns.json",
|
||||
// SingBox源配置文件目录,用于引用标准SingBox配置文件
|
||||
"OriginalPath": "/etc/V2bX/sing_origin.json"
|
||||
},
|
||||
@ -113,7 +114,9 @@
|
||||
// 开启 TCP Fast Open
|
||||
"EnableTFO": true,
|
||||
|
||||
// 设置 Domain Strategy
|
||||
// 开启 DNS
|
||||
"EnableDNS" : true,
|
||||
// 设置 Domain Strategy 需要开启 DNS ,默认 AsIS
|
||||
// 可选 prefer_ipv4 / prefer_ipv6 / ipv4_only / ipv6_only
|
||||
"DomainStrategy": "ipv4_only",
|
||||
|
||||
|
@ -9,5 +9,5 @@
|
||||
"SendIP": "0.0.0.0",
|
||||
"EnableProxyProtocol": false,
|
||||
"EnableTFO": true,
|
||||
"DomainStrategy": "ipv4_only"
|
||||
"DNSType": "ipv4_only"
|
||||
}
|
Loading…
Reference in New Issue
Block a user