mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2024-11-16 11:42:43 +08:00
feat: add DSCP rule for Tproxy UDP packets (#996)
* feat: add `DSCP` rule for Tproxy UDP packets * fix: fix compatibility issue with non_linux platform * chore: remove redundant lines for DSCP
This commit is contained in:
parent
90ea6ab278
commit
25d6ad220d
|
@ -63,3 +63,9 @@ func WithInAddr(addr net.Addr) Addition {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithDSCP(dscp uint8) Addition {
|
||||
return func(metadata *C.Metadata) {
|
||||
metadata.DSCP = dscp
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ type Metadata struct {
|
|||
SpecialProxy string `json:"specialProxy"`
|
||||
SpecialRules string `json:"specialRules"`
|
||||
RemoteDst string `json:"remoteDestination"`
|
||||
DSCP uint8 `json:"dscp"`
|
||||
|
||||
RawSrcAddr net.Addr `json:"-"`
|
||||
RawDstAddr net.Addr `json:"-"`
|
||||
|
|
|
@ -14,6 +14,7 @@ const (
|
|||
SrcPort
|
||||
DstPort
|
||||
InPort
|
||||
DSCP
|
||||
InUser
|
||||
InName
|
||||
InType
|
||||
|
@ -73,6 +74,8 @@ func (rt RuleType) String() string {
|
|||
return "RuleSet"
|
||||
case Network:
|
||||
return "Network"
|
||||
case DSCP:
|
||||
return "DSCP"
|
||||
case Uid:
|
||||
return "Uid"
|
||||
case SubRules:
|
||||
|
|
|
@ -34,6 +34,14 @@ func setsockopt(rc syscall.RawConn, addr string) error {
|
|||
if err == nil && isIPv6 {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, IPV6_RECVORIGDSTADDR, 1)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVTOS, 1)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, syscall.IPV6_RECVTCLASS, 1)
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
|
|
|
@ -79,6 +79,9 @@ func NewUDP(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*UDPLi
|
|||
continue
|
||||
}
|
||||
|
||||
dscp, _ := getDSCP(oob[:oobn])
|
||||
additions = append(additions, inbound.WithDSCP(dscp))
|
||||
|
||||
if rAddr.Addr().Is4() {
|
||||
// try to unmap 4in6 address
|
||||
lAddr = netip.AddrPortFrom(lAddr.Addr().Unmap(), lAddr.Port())
|
||||
|
|
|
@ -104,7 +104,7 @@ func getOrigDst(oob []byte) (netip.AddrPort, error) {
|
|||
}
|
||||
|
||||
// retrieve the destination address from the SCM.
|
||||
sa, err := unix.ParseOrigDstAddr(&scms[0])
|
||||
sa, err := unix.ParseOrigDstAddr(&scms[1])
|
||||
if err != nil {
|
||||
return netip.AddrPort{}, fmt.Errorf("retrieve destination: %w", err)
|
||||
}
|
||||
|
@ -122,3 +122,30 @@ func getOrigDst(oob []byte) (netip.AddrPort, error) {
|
|||
|
||||
return rAddr, nil
|
||||
}
|
||||
|
||||
func getDSCP (oob []byte) (uint8, error) {
|
||||
scms, err := unix.ParseSocketControlMessage(oob)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("parse control message: %w", err)
|
||||
}
|
||||
dscp, err := parseDSCP(&scms[0])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("retrieve DSCP: %w", err)
|
||||
}
|
||||
return dscp, nil
|
||||
}
|
||||
|
||||
func parseDSCP(m *unix.SocketControlMessage) (uint8, error) {
|
||||
switch {
|
||||
case m.Header.Level == unix.SOL_IP && m.Header.Type == unix.IP_TOS:
|
||||
dscp := uint8(m.Data[0] >> 2)
|
||||
return dscp, nil
|
||||
|
||||
case m.Header.Level == unix.SOL_IPV6 && m.Header.Type == unix.IPV6_TCLASS:
|
||||
dscp := uint8(m.Data[0] >> 2)
|
||||
return dscp, nil
|
||||
|
||||
default:
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@ func getOrigDst(oob []byte) (netip.AddrPort, error) {
|
|||
return netip.AddrPort{}, errors.New("UDP redir not supported on current platform")
|
||||
}
|
||||
|
||||
func getDSCP(oob []byte) (uint8, error) {
|
||||
return 0, errors.New("UDP redir not supported on current platform")
|
||||
}
|
||||
|
||||
func dialUDP(network string, lAddr, rAddr netip.AddrPort) (*net.UDPConn, error) {
|
||||
return nil, errors.New("UDP redir not supported on current platform")
|
||||
}
|
||||
|
|
47
rules/common/dscp.go
Normal file
47
rules/common/dscp.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
)
|
||||
|
||||
type DSCP struct {
|
||||
*Base
|
||||
dscp uint8
|
||||
payload string
|
||||
adapter string
|
||||
}
|
||||
|
||||
func (d *DSCP) RuleType() C.RuleType {
|
||||
return C.DSCP
|
||||
}
|
||||
|
||||
func (d *DSCP) Match(metadata *C.Metadata) (bool, string) {
|
||||
return metadata.DSCP == d.dscp, d.adapter
|
||||
}
|
||||
|
||||
func (d *DSCP) Adapter() string {
|
||||
return d.adapter
|
||||
}
|
||||
|
||||
func (d *DSCP) Payload() string {
|
||||
return d.payload
|
||||
}
|
||||
|
||||
func NewDSCP(dscp string, adapter string) (*DSCP, error) {
|
||||
dscpi, err := strconv.Atoi(dscp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse DSCP rule fail: %w", err)
|
||||
}
|
||||
if dscpi < 0 || dscpi > 63 {
|
||||
return nil, fmt.Errorf("DSCP couldn't be negative or exceed 63")
|
||||
}
|
||||
return &DSCP{
|
||||
Base: &Base{},
|
||||
payload: dscp,
|
||||
dscp: uint8(dscpi),
|
||||
adapter: adapter,
|
||||
}, nil
|
||||
}
|
|
@ -38,6 +38,8 @@ func ParseRule(tp, payload, target string, params []string, subRules map[string]
|
|||
parsed, parseErr = RC.NewPort(payload, target, C.DstPort)
|
||||
case "IN-PORT":
|
||||
parsed, parseErr = RC.NewPort(payload, target, C.InPort)
|
||||
case "DSCP":
|
||||
parsed, parseErr = RC.NewDSCP(payload, target)
|
||||
case "PROCESS-NAME":
|
||||
parsed, parseErr = RC.NewProcess(payload, target, true)
|
||||
case "PROCESS-PATH":
|
||||
|
|
Loading…
Reference in New Issue
Block a user