mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-15 21:00:27 +00:00
Fix windows bridge forwarding to connected subnets
This commit is contained in:
+53
-23
@@ -73,8 +73,9 @@ type filterInst struct {
|
||||
//
|
||||
// Zero value = "reject all" (match nothing), suitable for send-only handles.
|
||||
type Filter struct {
|
||||
insts []filterInst
|
||||
flags uint64 // filter flags for STARTUP ioctl
|
||||
insts []filterInst
|
||||
anyInsts []filterInst // trailing OR block: any match accepts
|
||||
flags uint64 // filter flags for STARTUP ioctl
|
||||
}
|
||||
|
||||
// reject returns a filter that matches no packet. The empty insts slice
|
||||
@@ -116,28 +117,41 @@ func OutboundTCP(src, dst netip.AddrPort) (*Filter, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func inboundTo(destination netip.Addr) (*Filter, error) {
|
||||
if !destination.IsValid() {
|
||||
return nil, E.New("windivert: filter: invalid address")
|
||||
func inboundTo(destinations []netip.Addr) (*Filter, error) {
|
||||
if len(destinations) == 0 {
|
||||
return nil, E.New("windivert: filter: no destination address")
|
||||
}
|
||||
isV6 := destinations[0].Is6()
|
||||
for _, destination := range destinations {
|
||||
if !destination.IsValid() {
|
||||
return nil, E.New("windivert: filter: invalid address")
|
||||
}
|
||||
if destination.Is6() != isV6 {
|
||||
return nil, E.New("windivert: filter: mixed IPv4/IPv6")
|
||||
}
|
||||
}
|
||||
f := &Filter{
|
||||
flags: filterFlagInbound,
|
||||
}
|
||||
f.add(fieldInbound, testEQ, argUint32(1))
|
||||
if destination.Is4() {
|
||||
if !isV6 {
|
||||
f.flags |= filterFlagIP
|
||||
f.add(fieldIP, testEQ, argUint32(1))
|
||||
f.add(fieldIPDstAddr, testEQ, argIPv4(destination))
|
||||
for _, destination := range destinations {
|
||||
f.addAny(fieldIPDstAddr, testEQ, argIPv4(destination))
|
||||
}
|
||||
} else {
|
||||
f.flags |= filterFlagIPv6
|
||||
f.add(fieldIPv6, testEQ, argUint32(1))
|
||||
f.add(fieldIPv6DstAddr, testEQ, argIPv6(destination))
|
||||
for _, destination := range destinations {
|
||||
f.addAny(fieldIPv6DstAddr, testEQ, argIPv6(destination))
|
||||
}
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func InboundTCPPortRange(destination netip.Addr, portLow, portHigh uint16) (*Filter, error) {
|
||||
f, err := inboundTo(destination)
|
||||
func InboundTCPPortRange(destinations []netip.Addr, portLow, portHigh uint16) (*Filter, error) {
|
||||
f, err := inboundTo(destinations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -147,8 +161,8 @@ func InboundTCPPortRange(destination netip.Addr, portLow, portHigh uint16) (*Fil
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func InboundUDPPortRange(destination netip.Addr, portLow, portHigh uint16) (*Filter, error) {
|
||||
f, err := inboundTo(destination)
|
||||
func InboundUDPPortRange(destinations []netip.Addr, portLow, portHigh uint16) (*Filter, error) {
|
||||
f, err := inboundTo(destinations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -158,12 +172,12 @@ func InboundUDPPortRange(destination netip.Addr, portLow, portHigh uint16) (*Fil
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func InboundICMPEchoReply(destination netip.Addr) (*Filter, error) {
|
||||
f, err := inboundTo(destination)
|
||||
func InboundICMPEchoReply(destinations []netip.Addr) (*Filter, error) {
|
||||
f, err := inboundTo(destinations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if destination.Is4() {
|
||||
if destinations[0].Is4() {
|
||||
f.add(fieldICMP, testEQ, argUint32(1))
|
||||
f.add(fieldICMPType, testEQ, argUint32(0))
|
||||
} else {
|
||||
@@ -173,12 +187,12 @@ func InboundICMPEchoReply(destination netip.Addr) (*Filter, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func InboundICMPError(destination netip.Addr) (*Filter, error) {
|
||||
f, err := inboundTo(destination)
|
||||
func InboundICMPError(destinations []netip.Addr) (*Filter, error) {
|
||||
f, err := inboundTo(destinations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if destination.Is4() {
|
||||
if destinations[0].Is4() {
|
||||
f.add(fieldICMP, testEQ, argUint32(1))
|
||||
f.add(fieldICMPType, testGEQ, argUint32(3))
|
||||
f.add(fieldICMPType, testLEQ, argUint32(12))
|
||||
@@ -194,6 +208,10 @@ func (f *Filter) add(field uint16, test uint8, arg [4]uint32) {
|
||||
f.insts = append(f.insts, filterInst{field: field, test: test, arg: arg})
|
||||
}
|
||||
|
||||
func (f *Filter) addAny(field uint16, test uint8, arg [4]uint32) {
|
||||
f.anyInsts = append(f.anyInsts, filterInst{field: field, test: test, arg: arg})
|
||||
}
|
||||
|
||||
func argUint32(v uint32) [4]uint32 { return [4]uint32{v, 0, 0, 0} }
|
||||
|
||||
// argIPv4 encodes an IPv4 address for IP_SRCADDR/IP_DSTADDR. The driver
|
||||
@@ -222,9 +240,12 @@ func argIPv6(addr netip.Addr) [4]uint32 {
|
||||
}
|
||||
|
||||
// encode serializes the Filter to the on-wire WINDIVERT_FILTER[] format
|
||||
// plus the filter_flags for STARTUP ioctl.
|
||||
// plus the filter_flags for STARTUP ioctl. insts chain as AND (failure
|
||||
// rejects); anyInsts follow as an OR block (success accepts, failure falls
|
||||
// through to the next alternative).
|
||||
func (f *Filter) encode() ([]byte, uint64, error) {
|
||||
if len(f.insts) == 0 {
|
||||
total := len(f.insts) + len(f.anyInsts)
|
||||
if total == 0 {
|
||||
// "Reject all" — one instruction, ZERO == 0 is always true, but we
|
||||
// invert by setting both success and failure to REJECT.
|
||||
return encodeInst(filterInst{
|
||||
@@ -234,12 +255,12 @@ func (f *Filter) encode() ([]byte, uint64, error) {
|
||||
failure: resultReject,
|
||||
}), 0, nil
|
||||
}
|
||||
if len(f.insts) > filterMaxInsts-1 {
|
||||
if total > filterMaxInsts-1 {
|
||||
return nil, 0, E.New("windivert: filter too long")
|
||||
}
|
||||
buf := make([]byte, 0, filterInstBytes*len(f.insts))
|
||||
buf := make([]byte, 0, filterInstBytes*total)
|
||||
for i, inst := range f.insts {
|
||||
if i == len(f.insts)-1 {
|
||||
if i == total-1 {
|
||||
inst.success = resultAccept
|
||||
} else {
|
||||
inst.success = uint16(i + 1)
|
||||
@@ -247,6 +268,15 @@ func (f *Filter) encode() ([]byte, uint64, error) {
|
||||
inst.failure = resultReject
|
||||
buf = append(buf, encodeInst(inst)...)
|
||||
}
|
||||
for i, inst := range f.anyInsts {
|
||||
inst.success = resultAccept
|
||||
if len(f.insts)+i == total-1 {
|
||||
inst.failure = resultReject
|
||||
} else {
|
||||
inst.failure = uint16(len(f.insts) + i + 1)
|
||||
}
|
||||
buf = append(buf, encodeInst(inst)...)
|
||||
}
|
||||
return buf, f.flags, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user