mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 14:14:02 +03:00
Propagate DNS setting to configuration
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
|
||||
"github.com/9seconds/mtg/v2/mtglib"
|
||||
)
|
||||
@@ -56,6 +57,7 @@ type Config struct {
|
||||
Idle TypeDuration `json:"idle"`
|
||||
} `json:"timeout"`
|
||||
DOHIP TypeIP `json:"dohIp"`
|
||||
DNS TypeDNSURI `json:"dns"`
|
||||
Proxies []TypeProxyURL `json:"proxies"`
|
||||
} `json:"network"`
|
||||
Stats struct {
|
||||
@@ -76,6 +78,16 @@ type Config struct {
|
||||
} `json:"stats"`
|
||||
}
|
||||
|
||||
func (c *Config) GetDNS() *url.URL {
|
||||
var dohURL *url.URL
|
||||
|
||||
if dohIP := c.Network.DOHIP.Get(nil); dohIP != nil {
|
||||
dohURL, _ = url.Parse("https://" + dohIP.String())
|
||||
}
|
||||
|
||||
return c.Network.DNS.Get(dohURL)
|
||||
}
|
||||
|
||||
func (c *Config) GetDomainFrontingPort(defaultValue uint) uint {
|
||||
if port := c.DomainFronting.Port.Get(0); port != 0 {
|
||||
return port
|
||||
|
||||
@@ -52,6 +52,7 @@ type tomlConfig struct {
|
||||
Idle string `toml:"idle" json:"idle,omitempty"`
|
||||
} `toml:"timeout" json:"timeout,omitempty"`
|
||||
DOHIP string `toml:"doh-ip" json:"dohIp,omitempty"`
|
||||
DNS string `toml:"dns" json:"dns,omitempty"`
|
||||
Proxies []string `toml:"proxies" json:"proxies,omitempty"`
|
||||
} `toml:"network" json:"network,omitempty"`
|
||||
Stats struct {
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type TypeDNSURI struct {
|
||||
Value *url.URL
|
||||
}
|
||||
|
||||
func (t *TypeDNSURI) Set(value string) error {
|
||||
parsed, err := url.Parse(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("value is not URI: %w", err)
|
||||
}
|
||||
|
||||
if parsed.Host == "" {
|
||||
parsed.Host = parsed.Path
|
||||
parsed.Path = ""
|
||||
parsed.Scheme = "udp"
|
||||
}
|
||||
|
||||
switch parsed.Scheme {
|
||||
case "https", "tls":
|
||||
case "udp":
|
||||
if ip := net.ParseIP(parsed.Hostname()); ip == nil {
|
||||
return fmt.Errorf("simple DNS must IP address: %s", parsed.Hostname())
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unsupported DNS type %s", parsed.Scheme)
|
||||
}
|
||||
|
||||
if parsed.Scheme != "https" && parsed.Path != "" {
|
||||
return fmt.Errorf("path is supported only for DoH: %s", parsed)
|
||||
}
|
||||
|
||||
if parsed.User != nil {
|
||||
return fmt.Errorf("used info is not supported: %s", parsed.User.String())
|
||||
}
|
||||
|
||||
t.Value = parsed
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TypeDNSURI) Get(defaultValue *url.URL) *url.URL {
|
||||
if t.Value != nil {
|
||||
return t.Value
|
||||
}
|
||||
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
func (t *TypeDNSURI) UnmarshalText(data []byte) error {
|
||||
return t.Set(string(data))
|
||||
}
|
||||
|
||||
func (t TypeDNSURI) MarshalText() ([]byte, error) {
|
||||
return []byte(t.String()), nil
|
||||
}
|
||||
|
||||
func (t TypeDNSURI) String() string {
|
||||
if t.Value == nil {
|
||||
return ""
|
||||
}
|
||||
return t.Value.String()
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package config_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/9seconds/mtg/v2/internal/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type typeDNSURITestStruct struct {
|
||||
Value config.TypeDNSURI `json:"value"`
|
||||
}
|
||||
|
||||
type TypeDNSURITestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func (suite *TypeDNSURITestSuite) TestUnmarshalFail() {
|
||||
testData := []string{
|
||||
"xx",
|
||||
"ppar",
|
||||
"",
|
||||
"dns://hahaha",
|
||||
"udp://xcxxcv",
|
||||
"udp://1.1.1.1/xcv",
|
||||
"1.1.1.1/xxx",
|
||||
"tls://dns/xx",
|
||||
"tls://1.1.1.1/xx",
|
||||
"https://user:password@1.1.1.1",
|
||||
"tls://user:password@1.1.1.1",
|
||||
"udp://user:password@1.1.1.1",
|
||||
}
|
||||
|
||||
for _, v := range testData {
|
||||
data, err := json.Marshal(map[string]string{
|
||||
"value": v,
|
||||
})
|
||||
suite.NoError(err)
|
||||
|
||||
suite.T().Run(v, func(t *testing.T) {
|
||||
assert.Error(t, json.Unmarshal(data, &typeDNSURITestStruct{}))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *TypeDNSURITestSuite) TestUnmarshalOk() {
|
||||
testData := []string{
|
||||
"1.1.1.1",
|
||||
"tls://1.1.1.1",
|
||||
"tls://dns.google",
|
||||
"https://1.1.1.1",
|
||||
"https://1.1.1.1/dns-query",
|
||||
"https://dns.google",
|
||||
"https://dns.google/dns-query",
|
||||
"udp://1.1.1.1",
|
||||
}
|
||||
|
||||
for _, v := range testData {
|
||||
data, err := json.Marshal(map[string]string{
|
||||
"value": v,
|
||||
})
|
||||
suite.NoError(err)
|
||||
|
||||
suite.T().Run(v, func(t *testing.T) {
|
||||
testStruct := &typeDNSURITestStruct{}
|
||||
assert.NoError(t, json.Unmarshal(data, testStruct))
|
||||
if v == "1.1.1.1" {
|
||||
v = "udp://" + v
|
||||
}
|
||||
assert.Equal(t, v, testStruct.Value.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *TypeDNSURITestSuite) TestMarshalOk() {
|
||||
testData := []string{
|
||||
"tls://1.1.1.1",
|
||||
"tls://dns.google",
|
||||
"https://1.1.1.1",
|
||||
"https://1.1.1.1/dns-query",
|
||||
}
|
||||
|
||||
for _, v := range testData {
|
||||
suite.T().Run(v, func(t *testing.T) {
|
||||
testStruct := &typePreferIPTestStruct{
|
||||
Value: config.TypePreferIP{
|
||||
Value: v,
|
||||
},
|
||||
}
|
||||
|
||||
encodedJSON, err := json.Marshal(testStruct)
|
||||
assert.NoError(t, err)
|
||||
|
||||
expectedJSON, err := json.Marshal(map[string]string{
|
||||
"value": v,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.JSONEq(t, string(expectedJSON), string(encodedJSON))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *TypeDNSURITestSuite) TestGet() {
|
||||
value := config.TypeDNSURI{}
|
||||
suite.Nil(value.Get(nil))
|
||||
|
||||
suite.NoError(value.Set("tls://1.1.1.1"))
|
||||
suite.NotNil(value.Get(nil))
|
||||
}
|
||||
|
||||
func TestDNSURI(t *testing.T) {
|
||||
t.Parallel()
|
||||
suite.Run(t, &TypeDNSURITestSuite{})
|
||||
}
|
||||
Reference in New Issue
Block a user