mirror of
https://github.com/daeuniverse/dae.git
synced 2025-01-03 13:31:00 +07:00
feat: support ToS routing rule (#292)
This commit is contained in:
parent
c784ebaf53
commit
7273be6a06
15
cmd/honk.go
15
cmd/honk.go
@ -3,16 +3,16 @@
|
|||||||
* Copyright (c) 2022-2023, daeuniverse Organization <dae@v2raya.org>
|
* Copyright (c) 2022-2023, daeuniverse Organization <dae@v2raya.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
honkCmd = &cobra.Command{
|
honkCmd = &cobra.Command{
|
||||||
Use: "honk",
|
Use: "honk",
|
||||||
Short: "Let dae call for you.",
|
Short: "Let dae call for you.",
|
||||||
@ -21,9 +21,8 @@
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(honkCmd)
|
rootCmd.AddCommand(honkCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ const (
|
|||||||
MatchType_IpVersion
|
MatchType_IpVersion
|
||||||
MatchType_Mac
|
MatchType_Mac
|
||||||
MatchType_ProcessName
|
MatchType_ProcessName
|
||||||
|
MatchType_Tos
|
||||||
MatchType_Fallback
|
MatchType_Fallback
|
||||||
MatchType_MustRules
|
MatchType_MustRules
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ const (
|
|||||||
Function_IpVersion = "ipversion"
|
Function_IpVersion = "ipversion"
|
||||||
Function_Mac = "mac"
|
Function_Mac = "mac"
|
||||||
Function_ProcessName = "pname"
|
Function_ProcessName = "pname"
|
||||||
|
Function_Tos = "tos"
|
||||||
|
|
||||||
Function_QName = "qname"
|
Function_QName = "qname"
|
||||||
Function_QType = "qtype"
|
Function_QType = "qtype"
|
||||||
|
@ -6,13 +6,17 @@
|
|||||||
package routing
|
package routing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/daeuniverse/dae/common"
|
"github.com/daeuniverse/dae/common"
|
||||||
"github.com/daeuniverse/dae/common/consts"
|
"github.com/daeuniverse/dae/common/consts"
|
||||||
"github.com/daeuniverse/dae/pkg/config_parser"
|
"github.com/daeuniverse/dae/pkg/config_parser"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"net/netip"
|
"golang.org/x/exp/constraints"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type FunctionParser func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error)
|
type FunctionParser func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error)
|
||||||
@ -137,3 +141,18 @@ func toProcessName(processName string) (procName [consts.TaskCommLen]byte) {
|
|||||||
copy(procName[:], n)
|
copy(procName[:], n)
|
||||||
return procName
|
return procName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UintParserFactory[T constraints.Unsigned](callback func(f *config_parser.Function, values []T, overrideOutbound *Outbound) (err error)) FunctionParser {
|
||||||
|
size := binary.Size(new(T))
|
||||||
|
return func(log *logrus.Logger, f *config_parser.Function, key string, paramValueGroup []string, overrideOutbound *Outbound) (err error) {
|
||||||
|
var values []T
|
||||||
|
for _, v := range paramValueGroup {
|
||||||
|
val, err := strconv.ParseUint(v, 10, 8*size)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot parse %v: %w", v, err)
|
||||||
|
}
|
||||||
|
values = append(values, T(val))
|
||||||
|
}
|
||||||
|
return callback(f, values, overrideOutbound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -729,6 +729,7 @@ func (c *DnsController) dialSend(invokingDepth int, req *udpRequest, data []byte
|
|||||||
"_qname": qname,
|
"_qname": qname,
|
||||||
"qtype": qtype,
|
"qtype": qtype,
|
||||||
"pid": req.routingResult.Pid,
|
"pid": req.routingResult.Pid,
|
||||||
|
"tos": req.routingResult.Tos,
|
||||||
"pname": ProcessName2String(req.routingResult.Pname[:]),
|
"pname": ProcessName2String(req.routingResult.Pname[:]),
|
||||||
"mac": Mac2String(req.routingResult.Mac[:]),
|
"mac": Mac2String(req.routingResult.Mac[:]),
|
||||||
}
|
}
|
||||||
|
@ -140,6 +140,7 @@ struct routing_result {
|
|||||||
__u8 outbound;
|
__u8 outbound;
|
||||||
__u8 pname[TASK_COMM_LEN];
|
__u8 pname[TASK_COMM_LEN];
|
||||||
__u32 pid;
|
__u32 pid;
|
||||||
|
__u8 tos;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dst_routing_result {
|
struct dst_routing_result {
|
||||||
@ -155,6 +156,7 @@ struct tuples {
|
|||||||
__u16 sport;
|
__u16 sport;
|
||||||
__u16 dport;
|
__u16 dport;
|
||||||
__u8 l4proto;
|
__u8 l4proto;
|
||||||
|
__u8 tos;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -282,6 +284,7 @@ enum __attribute__((packed)) MatchType {
|
|||||||
MatchType_IpVersion,
|
MatchType_IpVersion,
|
||||||
MatchType_Mac,
|
MatchType_Mac,
|
||||||
MatchType_ProcessName,
|
MatchType_ProcessName,
|
||||||
|
MatchType_Tos,
|
||||||
MatchType_Fallback,
|
MatchType_Fallback,
|
||||||
};
|
};
|
||||||
enum L4ProtoType {
|
enum L4ProtoType {
|
||||||
@ -317,6 +320,7 @@ struct match_set {
|
|||||||
enum L4ProtoType l4proto_type;
|
enum L4ProtoType l4proto_type;
|
||||||
enum IpVersionType ip_version;
|
enum IpVersionType ip_version;
|
||||||
__u32 pname[TASK_COMM_LEN / 4];
|
__u32 pname[TASK_COMM_LEN / 4];
|
||||||
|
__u8 tos;
|
||||||
};
|
};
|
||||||
bool not ; // A subrule flag (this is not a match_set flag).
|
bool not ; // A subrule flag (this is not a match_set flag).
|
||||||
enum MatchType type;
|
enum MatchType type;
|
||||||
@ -380,9 +384,13 @@ get_tuples(const struct __sk_buff *skb, struct tuples *tuples,
|
|||||||
tuples->dip.u6_addr32[2] = bpf_htonl(0x0000ffff);
|
tuples->dip.u6_addr32[2] = bpf_htonl(0x0000ffff);
|
||||||
tuples->dip.u6_addr32[3] = iph->daddr;
|
tuples->dip.u6_addr32[3] = iph->daddr;
|
||||||
|
|
||||||
|
tuples->tos = iph->tos;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
__builtin_memcpy(&tuples->dip, &ipv6h->daddr, IPV6_BYTE_LENGTH);
|
__builtin_memcpy(&tuples->dip, &ipv6h->daddr, IPV6_BYTE_LENGTH);
|
||||||
__builtin_memcpy(&tuples->sip, &ipv6h->saddr, IPV6_BYTE_LENGTH);
|
__builtin_memcpy(&tuples->sip, &ipv6h->saddr, IPV6_BYTE_LENGTH);
|
||||||
|
|
||||||
|
tuples->tos = ipv6h->priority;
|
||||||
}
|
}
|
||||||
if (l4proto == IPPROTO_TCP) {
|
if (l4proto == IPPROTO_TCP) {
|
||||||
tuples->sport = tcph->source;
|
tuples->sport = tcph->source;
|
||||||
@ -969,6 +977,7 @@ route(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
|
|||||||
#define _ipversion_type flag[1]
|
#define _ipversion_type flag[1]
|
||||||
#define _pname &flag[2]
|
#define _pname &flag[2]
|
||||||
#define _is_wan flag[2]
|
#define _is_wan flag[2]
|
||||||
|
#define _tos flag[3]
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
struct lpm_key lpm_key_instance, *lpm_key;
|
struct lpm_key lpm_key_instance, *lpm_key;
|
||||||
@ -1123,6 +1132,11 @@ route(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
|
|||||||
isdns_must_goodsubrule_badrule |= 0b10;
|
isdns_must_goodsubrule_badrule |= 0b10;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MatchType_Tos:
|
||||||
|
if (_tos == match_set->tos) {
|
||||||
|
isdns_must_goodsubrule_badrule |= 0b10;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case MatchType_Fallback:
|
case MatchType_Fallback:
|
||||||
#ifdef __DEBUG_ROUTING
|
#ifdef __DEBUG_ROUTING
|
||||||
bpf_printk("CHECK: hit fallback");
|
bpf_printk("CHECK: hit fallback");
|
||||||
@ -1200,6 +1214,7 @@ route(const __u32 flag[6], const void *l4hdr, const __be32 saddr[4],
|
|||||||
#undef _ipversion_type
|
#undef _ipversion_type
|
||||||
#undef _pname
|
#undef _pname
|
||||||
#undef _is_wan
|
#undef _is_wan
|
||||||
|
#undef _tos
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __always_inline is_not_to_lan(void *_ori_src) {
|
static bool __always_inline is_not_to_lan(void *_ori_src) {
|
||||||
@ -1394,6 +1409,7 @@ new_connection:
|
|||||||
} else {
|
} else {
|
||||||
flag[1] = IpVersionType_6;
|
flag[1] = IpVersionType_6;
|
||||||
}
|
}
|
||||||
|
flag[3] = tuples.tos;
|
||||||
__be32 mac[4] = {
|
__be32 mac[4] = {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -1411,6 +1427,7 @@ new_connection:
|
|||||||
routing_result.outbound = s64_ret;
|
routing_result.outbound = s64_ret;
|
||||||
routing_result.mark = s64_ret >> 8;
|
routing_result.mark = s64_ret >> 8;
|
||||||
routing_result.must = (s64_ret >> 40) & 1;
|
routing_result.must = (s64_ret >> 40) & 1;
|
||||||
|
routing_result.tos = tuples.tos;
|
||||||
__builtin_memcpy(routing_result.mac, ethh.h_source,
|
__builtin_memcpy(routing_result.mac, ethh.h_source,
|
||||||
sizeof(routing_result.mac));
|
sizeof(routing_result.mac));
|
||||||
/// NOTICE: No pid pname info for LAN packet.
|
/// NOTICE: No pid pname info for LAN packet.
|
||||||
@ -1685,6 +1702,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
|
|||||||
} else {
|
} else {
|
||||||
flag[1] = IpVersionType_6;
|
flag[1] = IpVersionType_6;
|
||||||
}
|
}
|
||||||
|
flag[3] = tuples.tos;
|
||||||
if (pid_is_control_plane(skb, &pid_pname)) {
|
if (pid_is_control_plane(skb, &pid_pname)) {
|
||||||
// From control plane. Direct.
|
// From control plane. Direct.
|
||||||
return TC_ACT_OK;
|
return TC_ACT_OK;
|
||||||
@ -1706,7 +1724,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
|
|||||||
return TC_ACT_SHOT;
|
return TC_ACT_SHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
outbound = s64_ret;
|
outbound = s64_ret & 0xff;
|
||||||
mark = s64_ret >> 8;
|
mark = s64_ret >> 8;
|
||||||
must = (s64_ret >> 40) & 1;
|
must = (s64_ret >> 40) & 1;
|
||||||
|
|
||||||
@ -1763,6 +1781,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
|
|||||||
routing_info.routing_result.outbound = outbound;
|
routing_info.routing_result.outbound = outbound;
|
||||||
routing_info.routing_result.mark = mark;
|
routing_info.routing_result.mark = mark;
|
||||||
routing_info.routing_result.must = must;
|
routing_info.routing_result.must = must;
|
||||||
|
routing_info.routing_result.tos = tuples.tos;
|
||||||
__builtin_memcpy(routing_info.routing_result.mac, ethh.h_source,
|
__builtin_memcpy(routing_info.routing_result.mac, ethh.h_source,
|
||||||
sizeof(ethh.h_source));
|
sizeof(ethh.h_source));
|
||||||
if (pid_pname) {
|
if (pid_pname) {
|
||||||
@ -1796,6 +1815,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
|
|||||||
} else {
|
} else {
|
||||||
flag[1] = IpVersionType_6;
|
flag[1] = IpVersionType_6;
|
||||||
}
|
}
|
||||||
|
flag[3] = tuples.tos;
|
||||||
struct pid_pname *pid_pname;
|
struct pid_pname *pid_pname;
|
||||||
if (pid_is_control_plane(skb, &pid_pname)) {
|
if (pid_is_control_plane(skb, &pid_pname)) {
|
||||||
// From control plane. Direct.
|
// From control plane. Direct.
|
||||||
@ -1826,6 +1846,7 @@ int tproxy_wan_egress(struct __sk_buff *skb) {
|
|||||||
new_hdr.routing_result.outbound = s64_ret;
|
new_hdr.routing_result.outbound = s64_ret;
|
||||||
new_hdr.routing_result.mark = s64_ret >> 8;
|
new_hdr.routing_result.mark = s64_ret >> 8;
|
||||||
new_hdr.routing_result.must = (s64_ret >> 40) & 1;
|
new_hdr.routing_result.must = (s64_ret >> 40) & 1;
|
||||||
|
new_hdr.routing_result.tos = tuples.tos;
|
||||||
__builtin_memcpy(new_hdr.routing_result.mac, ethh.h_source,
|
__builtin_memcpy(new_hdr.routing_result.mac, ethh.h_source,
|
||||||
sizeof(ethh.h_source));
|
sizeof(ethh.h_source));
|
||||||
if (pid_pname) {
|
if (pid_pname) {
|
||||||
|
@ -8,10 +8,11 @@ package control
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/daeuniverse/dae/pkg/trie"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/daeuniverse/dae/pkg/trie"
|
||||||
|
|
||||||
"github.com/cilium/ebpf"
|
"github.com/cilium/ebpf"
|
||||||
"github.com/daeuniverse/dae/common"
|
"github.com/daeuniverse/dae/common"
|
||||||
"github.com/daeuniverse/dae/common/consts"
|
"github.com/daeuniverse/dae/common/consts"
|
||||||
@ -43,6 +44,7 @@ func NewRoutingMatcherBuilder(log *logrus.Logger, rules []*config_parser.Routing
|
|||||||
rulesBuilder.RegisterFunctionParser(consts.Function_L4Proto, routing.L4ProtoParserFactory(b.addL4Proto))
|
rulesBuilder.RegisterFunctionParser(consts.Function_L4Proto, routing.L4ProtoParserFactory(b.addL4Proto))
|
||||||
rulesBuilder.RegisterFunctionParser(consts.Function_Mac, routing.MacParserFactory(b.addSourceMac))
|
rulesBuilder.RegisterFunctionParser(consts.Function_Mac, routing.MacParserFactory(b.addSourceMac))
|
||||||
rulesBuilder.RegisterFunctionParser(consts.Function_ProcessName, routing.ProcessNameParserFactory(b.addProcessName))
|
rulesBuilder.RegisterFunctionParser(consts.Function_ProcessName, routing.ProcessNameParserFactory(b.addProcessName))
|
||||||
|
rulesBuilder.RegisterFunctionParser(consts.Function_Tos, routing.UintParserFactory(b.addTos))
|
||||||
rulesBuilder.RegisterFunctionParser(consts.Function_IpVersion, routing.IpVersionParserFactory(b.addIpVersion))
|
rulesBuilder.RegisterFunctionParser(consts.Function_IpVersion, routing.IpVersionParserFactory(b.addIpVersion))
|
||||||
if err = rulesBuilder.Apply(rules); err != nil {
|
if err = rulesBuilder.Apply(rules); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -274,6 +276,29 @@ func (b *RoutingMatcherBuilder) addProcessName(f *config_parser.Function, values
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *RoutingMatcherBuilder) addTos(f *config_parser.Function, values []uint8, outbound *routing.Outbound) (err error) {
|
||||||
|
for i, value := range values {
|
||||||
|
outboundName := consts.OutboundLogicalOr.String()
|
||||||
|
if i == len(values)-1 {
|
||||||
|
outboundName = outbound.Name
|
||||||
|
}
|
||||||
|
outboundId, err := b.outboundToId(outboundName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
matchSet := bpfMatchSet{
|
||||||
|
Type: uint8(consts.MatchType_Tos),
|
||||||
|
Not: f.Not,
|
||||||
|
Outbound: outboundId,
|
||||||
|
Mark: outbound.Mark,
|
||||||
|
Must: outbound.Must,
|
||||||
|
}
|
||||||
|
matchSet.Value[0] = value
|
||||||
|
b.rules = append(b.rules, matchSet)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *RoutingMatcherBuilder) addFallback(fallbackOutbound config.FunctionOrString) (err error) {
|
func (b *RoutingMatcherBuilder) addFallback(fallbackOutbound config.FunctionOrString) (err error) {
|
||||||
outbound, err := routing.ParseOutbound(config.FunctionOrStringToFunction(fallbackOutbound))
|
outbound, err := routing.ParseOutbound(config.FunctionOrStringToFunction(fallbackOutbound))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -8,12 +8,12 @@ package control
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/daeuniverse/dae/pkg/trie"
|
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/daeuniverse/dae/common/consts"
|
"github.com/daeuniverse/dae/common/consts"
|
||||||
"github.com/daeuniverse/dae/component/routing"
|
"github.com/daeuniverse/dae/component/routing"
|
||||||
|
"github.com/daeuniverse/dae/pkg/trie"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RoutingMatcher struct {
|
type RoutingMatcher struct {
|
||||||
@ -33,6 +33,7 @@ func (m *RoutingMatcher) Match(
|
|||||||
l4proto consts.L4ProtoType,
|
l4proto consts.L4ProtoType,
|
||||||
domain string,
|
domain string,
|
||||||
processName [16]uint8,
|
processName [16]uint8,
|
||||||
|
tos uint8,
|
||||||
mac []byte,
|
mac []byte,
|
||||||
) (outboundIndex consts.OutboundIndex, mark uint32, must bool, err error) {
|
) (outboundIndex consts.OutboundIndex, mark uint32, must bool, err error) {
|
||||||
if len(sourceAddr) != net.IPv6len || len(destAddr) != net.IPv6len || len(mac) != net.IPv6len {
|
if len(sourceAddr) != net.IPv6len || len(destAddr) != net.IPv6len || len(mac) != net.IPv6len {
|
||||||
@ -92,6 +93,10 @@ func (m *RoutingMatcher) Match(
|
|||||||
if processName[0] != 0 && match.Value == processName {
|
if processName[0] != 0 && match.Value == processName {
|
||||||
goodSubrule = true
|
goodSubrule = true
|
||||||
}
|
}
|
||||||
|
case consts.MatchType_Tos:
|
||||||
|
if tos == match.Value[0] {
|
||||||
|
goodSubrule = true
|
||||||
|
}
|
||||||
case consts.MatchType_Fallback:
|
case consts.MatchType_Fallback:
|
||||||
goodSubrule = true
|
goodSubrule = true
|
||||||
default:
|
default:
|
||||||
|
@ -182,6 +182,7 @@ func (c *ControlPlane) RouteDialTcp(p *RouteDialParam) (conn netproxy.Conn, err
|
|||||||
"sniffed": domain,
|
"sniffed": domain,
|
||||||
"ip": RefineAddrPortToShow(dst),
|
"ip": RefineAddrPortToShow(dst),
|
||||||
"pid": routingResult.Pid,
|
"pid": routingResult.Pid,
|
||||||
|
"tos": routingResult.Tos,
|
||||||
"pname": ProcessName2String(routingResult.Pname[:]),
|
"pname": ProcessName2String(routingResult.Pname[:]),
|
||||||
"mac": Mac2String(routingResult.Mac[:]),
|
"mac": Mac2String(routingResult.Mac[:]),
|
||||||
}).Infof("%v <-> %v", RefineSourceToShow(src, dst.Addr(), consts.LanWanFlag_NotApplicable), dialTarget)
|
}).Infof("%v <-> %v", RefineSourceToShow(src, dst.Addr(), consts.LanWanFlag_NotApplicable), dialTarget)
|
||||||
|
@ -274,6 +274,7 @@ getNew:
|
|||||||
"to": realDst.String(),
|
"to": realDst.String(),
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
"pid": routingResult.Pid,
|
"pid": routingResult.Pid,
|
||||||
|
"tos": routingResult.Tos,
|
||||||
"pname": ProcessName2String(routingResult.Pname[:]),
|
"pname": ProcessName2String(routingResult.Pname[:]),
|
||||||
"mac": Mac2String(routingResult.Mac[:]),
|
"mac": Mac2String(routingResult.Mac[:]),
|
||||||
"from": realSrc.String(),
|
"from": realSrc.String(),
|
||||||
@ -298,6 +299,7 @@ getNew:
|
|||||||
"domain": domain,
|
"domain": domain,
|
||||||
"ip": RefineAddrPortToShow(realDst),
|
"ip": RefineAddrPortToShow(realDst),
|
||||||
"pid": routingResult.Pid,
|
"pid": routingResult.Pid,
|
||||||
|
"tos": routingResult.Tos,
|
||||||
"pname": ProcessName2String(routingResult.Pname[:]),
|
"pname": ProcessName2String(routingResult.Pname[:]),
|
||||||
"mac": Mac2String(routingResult.Mac[:]),
|
"mac": Mac2String(routingResult.Mac[:]),
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ func (c *ControlPlane) Route(src, dst netip.AddrPort, domain string, l4proto con
|
|||||||
l4proto,
|
l4proto,
|
||||||
domain,
|
domain,
|
||||||
routingResult.Pname,
|
routingResult.Pname,
|
||||||
|
routingResult.Tos,
|
||||||
append([]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, routingResult.Mac[:]...),
|
append([]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, routingResult.Mac[:]...),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return 0, 0, false, err
|
return 0, 0, false, err
|
||||||
|
@ -55,6 +55,9 @@ mac('02:42:ac:11:00:02') -> direct
|
|||||||
### Process Name rule (only support localhost process when binding to WAN)
|
### Process Name rule (only support localhost process when binding to WAN)
|
||||||
pname(curl) -> direct
|
pname(curl) -> direct
|
||||||
|
|
||||||
|
### ToS rule (match ToS/DSCP; is useful for BT bypass)
|
||||||
|
tos(4) -> direct
|
||||||
|
|
||||||
### Multiple domains rule
|
### Multiple domains rule
|
||||||
domain(keyword: google, suffix: www.twitter.com, suffix: v2raya.org) -> my_group
|
domain(keyword: google, suffix: www.twitter.com, suffix: v2raya.org) -> my_group
|
||||||
### Multiple IP rule
|
### Multiple IP rule
|
||||||
|
@ -55,6 +55,9 @@ mac('02:42:ac:11:00:02') -> direct
|
|||||||
### 进程名称规则(绑定WAN时仅支持本机进程)
|
### 进程名称规则(绑定WAN时仅支持本机进程)
|
||||||
pname(curl) -> direct
|
pname(curl) -> direct
|
||||||
|
|
||||||
|
### ToS规则(匹配 ToS 和 DSCP,可用于绕过 BT)
|
||||||
|
tos(4) -> direct
|
||||||
|
|
||||||
### 多个域名规则
|
### 多个域名规则
|
||||||
domain(keyword: google, suffix: www.twitter.com, suffix: v2raya.org) -> my_group
|
domain(keyword: google, suffix: www.twitter.com, suffix: v2raya.org) -> my_group
|
||||||
### 多个IP规则
|
### 多个IP规则
|
||||||
|
Loading…
Reference in New Issue
Block a user