mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-25 18:11:28 +00:00
Add query_type DNS rule item
This commit is contained in:
parent
41ec2e7944
commit
687b4509df
|
@ -46,6 +46,10 @@ type InboundContext struct {
|
||||||
SourceGeoIPCode string
|
SourceGeoIPCode string
|
||||||
GeoIPCode string
|
GeoIPCode string
|
||||||
ProcessInfo *process.Info
|
ProcessInfo *process.Info
|
||||||
|
|
||||||
|
// dns cache
|
||||||
|
|
||||||
|
QueryType uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
type inboundContextKey struct{}
|
type inboundContextKey struct{}
|
||||||
|
|
|
@ -9,6 +9,11 @@
|
||||||
"mixed-in"
|
"mixed-in"
|
||||||
],
|
],
|
||||||
"ip_version": 6,
|
"ip_version": 6,
|
||||||
|
"query_type": [
|
||||||
|
"A",
|
||||||
|
"HTTPS",
|
||||||
|
32768
|
||||||
|
],
|
||||||
"network": "tcp",
|
"network": "tcp",
|
||||||
"auth_user": [
|
"auth_user": [
|
||||||
"usera",
|
"usera",
|
||||||
|
@ -119,6 +124,10 @@ Tags of [Inbound](/configuration/inbound).
|
||||||
|
|
||||||
Not limited if empty.
|
Not limited if empty.
|
||||||
|
|
||||||
|
#### query_type
|
||||||
|
|
||||||
|
DNS query type. Values can be integers or type name strings.
|
||||||
|
|
||||||
#### network
|
#### network
|
||||||
|
|
||||||
`tcp` or `udp`.
|
`tcp` or `udp`.
|
||||||
|
|
|
@ -9,6 +9,11 @@
|
||||||
"mixed-in"
|
"mixed-in"
|
||||||
],
|
],
|
||||||
"ip_version": 6,
|
"ip_version": 6,
|
||||||
|
"query_type": [
|
||||||
|
"A",
|
||||||
|
"HTTPS",
|
||||||
|
32768
|
||||||
|
],
|
||||||
"network": "tcp",
|
"network": "tcp",
|
||||||
"auth_user": [
|
"auth_user": [
|
||||||
"usera",
|
"usera",
|
||||||
|
@ -118,6 +123,10 @@
|
||||||
|
|
||||||
默认不限制。
|
默认不限制。
|
||||||
|
|
||||||
|
#### query_type
|
||||||
|
|
||||||
|
DNS 查询类型。值可以为整数或者类型名称字符串。
|
||||||
|
|
||||||
#### network
|
#### network
|
||||||
|
|
||||||
`tcp` 或 `udp`。
|
`tcp` 或 `udp`。
|
||||||
|
|
|
@ -77,32 +77,33 @@ func (r *DNSRule) UnmarshalJSON(bytes []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultDNSRule struct {
|
type DefaultDNSRule struct {
|
||||||
Inbound Listable[string] `json:"inbound,omitempty"`
|
Inbound Listable[string] `json:"inbound,omitempty"`
|
||||||
IPVersion int `json:"ip_version,omitempty"`
|
IPVersion int `json:"ip_version,omitempty"`
|
||||||
Network string `json:"network,omitempty"`
|
QueryType Listable[DNSQueryType] `json:"query_type,omitempty"`
|
||||||
AuthUser Listable[string] `json:"auth_user,omitempty"`
|
Network string `json:"network,omitempty"`
|
||||||
Protocol Listable[string] `json:"protocol,omitempty"`
|
AuthUser Listable[string] `json:"auth_user,omitempty"`
|
||||||
Domain Listable[string] `json:"domain,omitempty"`
|
Protocol Listable[string] `json:"protocol,omitempty"`
|
||||||
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
Domain Listable[string] `json:"domain,omitempty"`
|
||||||
DomainKeyword Listable[string] `json:"domain_keyword,omitempty"`
|
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
||||||
DomainRegex Listable[string] `json:"domain_regex,omitempty"`
|
DomainKeyword Listable[string] `json:"domain_keyword,omitempty"`
|
||||||
Geosite Listable[string] `json:"geosite,omitempty"`
|
DomainRegex Listable[string] `json:"domain_regex,omitempty"`
|
||||||
SourceGeoIP Listable[string] `json:"source_geoip,omitempty"`
|
Geosite Listable[string] `json:"geosite,omitempty"`
|
||||||
SourceIPCIDR Listable[string] `json:"source_ip_cidr,omitempty"`
|
SourceGeoIP Listable[string] `json:"source_geoip,omitempty"`
|
||||||
SourcePort Listable[uint16] `json:"source_port,omitempty"`
|
SourceIPCIDR Listable[string] `json:"source_ip_cidr,omitempty"`
|
||||||
SourcePortRange Listable[string] `json:"source_port_range,omitempty"`
|
SourcePort Listable[uint16] `json:"source_port,omitempty"`
|
||||||
Port Listable[uint16] `json:"port,omitempty"`
|
SourcePortRange Listable[string] `json:"source_port_range,omitempty"`
|
||||||
PortRange Listable[string] `json:"port_range,omitempty"`
|
Port Listable[uint16] `json:"port,omitempty"`
|
||||||
ProcessName Listable[string] `json:"process_name,omitempty"`
|
PortRange Listable[string] `json:"port_range,omitempty"`
|
||||||
ProcessPath Listable[string] `json:"process_path,omitempty"`
|
ProcessName Listable[string] `json:"process_name,omitempty"`
|
||||||
PackageName Listable[string] `json:"package_name,omitempty"`
|
ProcessPath Listable[string] `json:"process_path,omitempty"`
|
||||||
User Listable[string] `json:"user,omitempty"`
|
PackageName Listable[string] `json:"package_name,omitempty"`
|
||||||
UserID Listable[int32] `json:"user_id,omitempty"`
|
User Listable[string] `json:"user,omitempty"`
|
||||||
Outbound Listable[string] `json:"outbound,omitempty"`
|
UserID Listable[int32] `json:"user_id,omitempty"`
|
||||||
ClashMode string `json:"clash_mode,omitempty"`
|
Outbound Listable[string] `json:"outbound,omitempty"`
|
||||||
Invert bool `json:"invert,omitempty"`
|
ClashMode string `json:"clash_mode,omitempty"`
|
||||||
Server string `json:"server,omitempty"`
|
Invert bool `json:"invert,omitempty"`
|
||||||
DisableCache bool `json:"disable_cache,omitempty"`
|
Server string `json:"server,omitempty"`
|
||||||
|
DisableCache bool `json:"disable_cache,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r DefaultDNSRule) IsValid() bool {
|
func (r DefaultDNSRule) IsValid() bool {
|
||||||
|
|
|
@ -8,7 +8,10 @@ import (
|
||||||
"github.com/sagernet/sing-box/common/json"
|
"github.com/sagernet/sing-box/common/json"
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
F "github.com/sagernet/sing/common/format"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
|
mDNS "github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ListenAddress netip.Addr
|
type ListenAddress netip.Addr
|
||||||
|
@ -187,3 +190,40 @@ func (p *ListenPrefix) UnmarshalJSON(bytes []byte) error {
|
||||||
func (p ListenPrefix) Build() netip.Prefix {
|
func (p ListenPrefix) Build() netip.Prefix {
|
||||||
return netip.Prefix(p)
|
return netip.Prefix(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DNSQueryType uint16
|
||||||
|
|
||||||
|
func (t DNSQueryType) MarshalJSON() ([]byte, error) {
|
||||||
|
typeName, loaded := mDNS.TypeToString[uint16(t)]
|
||||||
|
if loaded {
|
||||||
|
return json.Marshal(typeName)
|
||||||
|
}
|
||||||
|
return json.Marshal(uint16(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *DNSQueryType) UnmarshalJSON(bytes []byte) error {
|
||||||
|
var valueNumber uint16
|
||||||
|
err := json.Unmarshal(bytes, &valueNumber)
|
||||||
|
if err == nil {
|
||||||
|
*t = DNSQueryType(valueNumber)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var valueString string
|
||||||
|
err = json.Unmarshal(bytes, &valueString)
|
||||||
|
if err == nil {
|
||||||
|
queryType, loaded := mDNS.StringToType[valueString]
|
||||||
|
if loaded {
|
||||||
|
*t = DNSQueryType(queryType)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return E.New("unknown DNS query type: ", string(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
func DNSQueryTypeToString(queryType uint16) string {
|
||||||
|
typeName, loaded := mDNS.TypeToString[queryType]
|
||||||
|
if loaded {
|
||||||
|
return typeName
|
||||||
|
}
|
||||||
|
return F.ToString(queryType)
|
||||||
|
}
|
||||||
|
|
|
@ -50,7 +50,8 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er
|
||||||
}
|
}
|
||||||
ctx, metadata := adapter.AppendContext(ctx)
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
if len(message.Question) > 0 {
|
if len(message.Question) > 0 {
|
||||||
switch message.Question[0].Qtype {
|
metadata.QueryType = message.Question[0].Qtype
|
||||||
|
switch metadata.QueryType {
|
||||||
case mDNS.TypeA:
|
case mDNS.TypeA:
|
||||||
metadata.IPVersion = 4
|
metadata.IPVersion = 4
|
||||||
case mDNS.TypeAAAA:
|
case mDNS.TypeAAAA:
|
||||||
|
|
|
@ -71,6 +71,11 @@ func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options
|
||||||
return nil, E.New("invalid ip version: ", options.IPVersion)
|
return nil, E.New("invalid ip version: ", options.IPVersion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(options.QueryType) > 0 {
|
||||||
|
item := NewQueryTypeItem(options.QueryType)
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
if options.Network != "" {
|
if options.Network != "" {
|
||||||
switch options.Network {
|
switch options.Network {
|
||||||
case N.NetworkTCP, N.NetworkUDP:
|
case N.NetworkTCP, N.NetworkUDP:
|
||||||
|
|
47
route/rule_query_type.go
Normal file
47
route/rule_query_type.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package route
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ RuleItem = (*QueryTypeItem)(nil)
|
||||||
|
|
||||||
|
type QueryTypeItem struct {
|
||||||
|
typeList []uint16
|
||||||
|
typeMap map[uint16]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewQueryTypeItem(typeList []option.DNSQueryType) *QueryTypeItem {
|
||||||
|
rule := &QueryTypeItem{
|
||||||
|
typeList: common.Map(typeList, func(it option.DNSQueryType) uint16 {
|
||||||
|
return uint16(it)
|
||||||
|
}),
|
||||||
|
typeMap: make(map[uint16]bool),
|
||||||
|
}
|
||||||
|
for _, userId := range rule.typeList {
|
||||||
|
rule.typeMap[userId] = true
|
||||||
|
}
|
||||||
|
return rule
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *QueryTypeItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
|
if metadata.QueryType == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return r.typeMap[metadata.QueryType]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *QueryTypeItem) String() string {
|
||||||
|
var description string
|
||||||
|
pLen := len(r.typeList)
|
||||||
|
if pLen == 1 {
|
||||||
|
description = "query_type=" + option.DNSQueryTypeToString(r.typeList[0])
|
||||||
|
} else {
|
||||||
|
description = "query_type=[" + strings.Join(common.Map(r.typeList, option.DNSQueryTypeToString), " ") + "]"
|
||||||
|
}
|
||||||
|
return description
|
||||||
|
}
|
Loading…
Reference in a new issue