mirror of
https://github.com/daeuniverse/dae.git
synced 2025-07-15 10:18:45 +07:00
Revert "optimize: no need for rule table for wan and reject TCP to tproxy"
This reverts commit 7452abb158
.
This commit is contained in:
@ -125,6 +125,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
TproxyMark uint32 = 0x8000000
|
||||||
LoopbackIfIndex = 1
|
LoopbackIfIndex = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -175,6 +175,9 @@ func NewControlPlane(
|
|||||||
}
|
}
|
||||||
// Bind to LAN
|
// Bind to LAN
|
||||||
if len(global.LanInterface) > 0 {
|
if len(global.LanInterface) > 0 {
|
||||||
|
if err = core.setupRoutingPolicy(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
for _, ifname := range global.LanInterface {
|
for _, ifname := range global.LanInterface {
|
||||||
if err = core.bindLan(ifname); err != nil {
|
if err = core.bindLan(ifname); err != nil {
|
||||||
return nil, fmt.Errorf("bindLan: %v: %w", ifname, err)
|
return nil, fmt.Errorf("bindLan: %v: %w", ifname, err)
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
internal "github.com/v2rayA/dae/pkg/ebpf_internal"
|
internal "github.com/v2rayA/dae/pkg/ebpf_internal"
|
||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
@ -115,6 +116,116 @@ func (c *ControlPlaneCore) delQdisc(ifname string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ControlPlaneCore) setupRoutingPolicy() (err error) {
|
||||||
|
/// Insert ip rule / ip route.
|
||||||
|
const table = 2023
|
||||||
|
|
||||||
|
/** ip table
|
||||||
|
ip route add local default dev lo table 2023
|
||||||
|
ip -6 route add local default dev lo table 2023
|
||||||
|
*/
|
||||||
|
routes := []netlink.Route{{
|
||||||
|
Scope: unix.RT_SCOPE_HOST,
|
||||||
|
LinkIndex: consts.LoopbackIfIndex,
|
||||||
|
Dst: &net.IPNet{
|
||||||
|
IP: []byte{0, 0, 0, 0},
|
||||||
|
Mask: net.CIDRMask(0, 32),
|
||||||
|
},
|
||||||
|
Table: table,
|
||||||
|
Type: unix.RTN_LOCAL,
|
||||||
|
}, {
|
||||||
|
Scope: unix.RT_SCOPE_HOST,
|
||||||
|
LinkIndex: consts.LoopbackIfIndex,
|
||||||
|
Dst: &net.IPNet{
|
||||||
|
IP: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||||
|
Mask: net.CIDRMask(0, 128),
|
||||||
|
},
|
||||||
|
Table: table,
|
||||||
|
Type: unix.RTN_LOCAL,
|
||||||
|
}}
|
||||||
|
cleanRoutes := func() error {
|
||||||
|
var errs error
|
||||||
|
for _, route := range routes {
|
||||||
|
if e := netlink.RouteDel(&route); e != nil {
|
||||||
|
if errs != nil {
|
||||||
|
errs = fmt.Errorf("%w; %v", errs, e)
|
||||||
|
} else {
|
||||||
|
errs = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if errs != nil {
|
||||||
|
return fmt.Errorf("IpRouteDel(lo): %w", errs)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
tryRouteAddAgain:
|
||||||
|
for _, route := range routes {
|
||||||
|
if err = netlink.RouteAdd(&route); err != nil {
|
||||||
|
if os.IsExist(err) {
|
||||||
|
_ = cleanRoutes()
|
||||||
|
goto tryRouteAddAgain
|
||||||
|
}
|
||||||
|
return fmt.Errorf("IpRouteAdd: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.deferFuncs = append(c.deferFuncs, cleanRoutes)
|
||||||
|
|
||||||
|
/** ip rule
|
||||||
|
ip rule add fwmark 0x8000000/0x8000000 table 2023
|
||||||
|
ip -6 rule add fwmark 0x8000000/0x8000000 table 2023
|
||||||
|
*/
|
||||||
|
rules := []netlink.Rule{{
|
||||||
|
SuppressIfgroup: -1,
|
||||||
|
SuppressPrefixlen: -1,
|
||||||
|
Priority: -1,
|
||||||
|
Goto: -1,
|
||||||
|
Flow: -1,
|
||||||
|
Family: unix.AF_INET,
|
||||||
|
Table: table,
|
||||||
|
Mark: int(consts.TproxyMark),
|
||||||
|
Mask: int(consts.TproxyMark),
|
||||||
|
}, {
|
||||||
|
SuppressIfgroup: -1,
|
||||||
|
SuppressPrefixlen: -1,
|
||||||
|
Priority: -1,
|
||||||
|
Goto: -1,
|
||||||
|
Flow: -1,
|
||||||
|
Family: unix.AF_INET6,
|
||||||
|
Table: table,
|
||||||
|
Mark: int(consts.TproxyMark),
|
||||||
|
Mask: int(consts.TproxyMark),
|
||||||
|
}}
|
||||||
|
cleanRules := func() error {
|
||||||
|
var errs error
|
||||||
|
for _, rule := range rules {
|
||||||
|
if e := netlink.RuleDel(&rule); e != nil {
|
||||||
|
if errs != nil {
|
||||||
|
errs = fmt.Errorf("%w; %v", errs, e)
|
||||||
|
} else {
|
||||||
|
errs = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if errs != nil {
|
||||||
|
return fmt.Errorf("IpRuleDel: %w", errs)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
tryRuleAddAgain:
|
||||||
|
for _, rule := range rules {
|
||||||
|
if err = netlink.RuleAdd(&rule); err != nil {
|
||||||
|
if os.IsExist(err) {
|
||||||
|
_ = cleanRules()
|
||||||
|
goto tryRuleAddAgain
|
||||||
|
}
|
||||||
|
return fmt.Errorf("IpRuleAdd: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.deferFuncs = append(c.deferFuncs, cleanRules)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ControlPlaneCore) bindLan(ifname string) error {
|
func (c *ControlPlaneCore) bindLan(ifname string) error {
|
||||||
c.log.Infof("Bind to LAN: %v", ifname)
|
c.log.Infof("Bind to LAN: %v", ifname)
|
||||||
|
|
||||||
|
@ -65,6 +65,8 @@
|
|||||||
#define IS_WAN 0
|
#define IS_WAN 0
|
||||||
#define IS_LAN 1
|
#define IS_LAN 1
|
||||||
|
|
||||||
|
#define TPROXY_MARK 0x8000000
|
||||||
|
|
||||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||||
|
|
||||||
enum { BPF_F_CURRENT_NETNS = -1 };
|
enum { BPF_F_CURRENT_NETNS = -1 };
|
||||||
@ -1218,8 +1220,8 @@ int tproxy_lan_egress(struct __sk_buff *skb) {
|
|||||||
ori_src.ip, false, true))) {
|
ori_src.ip, false, true))) {
|
||||||
return TC_ACT_SHOT;
|
return TC_ACT_SHOT;
|
||||||
}
|
}
|
||||||
if ((ret = rewrite_port(skb, l4proto, ihl, tuples.sport, ori_src.port, false,
|
if ((ret = rewrite_port(skb, l4proto, ihl, tuples.sport, ori_src.port,
|
||||||
true))) {
|
false, true))) {
|
||||||
return TC_ACT_SHOT;
|
return TC_ACT_SHOT;
|
||||||
}
|
}
|
||||||
disable_l4_checksum(skb, l4proto, ihl);
|
disable_l4_checksum(skb, l4proto, ihl);
|
||||||
@ -1326,8 +1328,8 @@ new_connection:
|
|||||||
bpf_htonl((ethh.h_source[2] << 24) + (ethh.h_source[3] << 16) +
|
bpf_htonl((ethh.h_source[2] << 24) + (ethh.h_source[3] << 16) +
|
||||||
(ethh.h_source[4] << 8) + (ethh.h_source[5])),
|
(ethh.h_source[4] << 8) + (ethh.h_source[5])),
|
||||||
};
|
};
|
||||||
if ((ret = routing(flag, l4hdr, tuples.sip.u6_addr32, tuples.dip.u6_addr32,
|
if ((ret = routing(flag, l4hdr, tuples.sip.u6_addr32,
|
||||||
mac)) < 0) {
|
tuples.dip.u6_addr32, mac)) < 0) {
|
||||||
bpf_printk("shot routing: %d", ret);
|
bpf_printk("shot routing: %d", ret);
|
||||||
return TC_ACT_SHOT;
|
return TC_ACT_SHOT;
|
||||||
}
|
}
|
||||||
@ -1394,10 +1396,7 @@ control_plane_tproxy:
|
|||||||
}
|
}
|
||||||
|
|
||||||
assign:
|
assign:
|
||||||
if ((ret = bpf_skb_change_type(skb, 0))) {
|
skb->mark = TPROXY_MARK;
|
||||||
bpf_printk("failed to change type");
|
|
||||||
goto sk_shot;
|
|
||||||
}
|
|
||||||
ret = bpf_sk_assign(skb, sk, 0);
|
ret = bpf_sk_assign(skb, sk, 0);
|
||||||
bpf_sk_release(sk);
|
bpf_sk_release(sk);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -1802,30 +1801,36 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
|
|||||||
__u16 tproxy_typ = bpf_ntohs(*(__u16 *)ðh.h_source[4]);
|
__u16 tproxy_typ = bpf_ntohs(*(__u16 *)ðh.h_source[4]);
|
||||||
if (*(__u32 *)ðh.h_source[0] != bpf_htonl(0x02000203) || tproxy_typ > 1) {
|
if (*(__u32 *)ðh.h_source[0] != bpf_htonl(0x02000203) || tproxy_typ > 1) {
|
||||||
// Check for security. Reject packets that is UDP and sent to tproxy port.
|
// Check for security. Reject packets that is UDP and sent to tproxy port.
|
||||||
__be16 *tproxy_port = bpf_map_lookup_elem(¶m_map, &tproxy_port_key);
|
if (l4proto == IPPROTO_UDP) {
|
||||||
if (!tproxy_port) {
|
__be16 *tproxy_port = bpf_map_lookup_elem(¶m_map, &tproxy_port_key);
|
||||||
goto accept;
|
if (!tproxy_port) {
|
||||||
}
|
goto accept;
|
||||||
if (unlikely(*tproxy_port == tuples.dport)) {
|
|
||||||
struct bpf_sock_tuple tuple = {0};
|
|
||||||
__u32 tuple_size;
|
|
||||||
|
|
||||||
if (ipversion == 4) {
|
|
||||||
tuple.ipv4.daddr = tuples.dip.u6_addr32[3];
|
|
||||||
tuple.ipv4.dport = tuples.dport;
|
|
||||||
tuple_size = sizeof(tuple.ipv4);
|
|
||||||
} else {
|
|
||||||
__builtin_memcpy(tuple.ipv6.daddr, &tuples.dip, IPV6_BYTE_LENGTH);
|
|
||||||
tuple.ipv6.dport = tuples.dport;
|
|
||||||
tuple_size = sizeof(tuple.ipv6);
|
|
||||||
}
|
}
|
||||||
|
if (unlikely(*tproxy_port == tuples.dport)) {
|
||||||
|
struct bpf_sock_tuple tuple = {0};
|
||||||
|
__u32 tuple_size;
|
||||||
|
|
||||||
struct bpf_sock *sk =
|
if (ipversion == 4) {
|
||||||
bpf_sk_lookup_udp(skb, &tuple, tuple_size, BPF_F_CURRENT_NETNS, 0);
|
tuple.ipv4.daddr = tuples.dip.u6_addr32[3];
|
||||||
if (sk) {
|
tuple.ipv4.saddr = tuples.sip.u6_addr32[3];
|
||||||
// Scope is host.
|
tuple.ipv4.dport = tuples.dport;
|
||||||
bpf_sk_release(sk);
|
tuple.ipv4.sport = tuples.sport;
|
||||||
return TC_ACT_SHOT;
|
tuple_size = sizeof(tuple.ipv4);
|
||||||
|
} else {
|
||||||
|
__builtin_memcpy(tuple.ipv6.daddr, &tuples.dip, IPV6_BYTE_LENGTH);
|
||||||
|
__builtin_memcpy(tuple.ipv6.saddr, &tuples.sip, IPV6_BYTE_LENGTH);
|
||||||
|
tuple.ipv6.dport = tuples.dport;
|
||||||
|
tuple.ipv6.sport = tuples.sport;
|
||||||
|
tuple_size = sizeof(tuple.ipv6);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bpf_sock *sk =
|
||||||
|
bpf_sk_lookup_udp(skb, &tuple, tuple_size, BPF_F_CURRENT_NETNS, 0);
|
||||||
|
if (sk) {
|
||||||
|
// Scope is host.
|
||||||
|
bpf_sk_release(sk);
|
||||||
|
return TC_ACT_SHOT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
accept:
|
accept:
|
||||||
@ -1900,15 +1905,16 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite udp src ip
|
// Rewrite udp src ip
|
||||||
if ((ret = rewrite_ip(skb, ipversion, IPPROTO_UDP, ihl,
|
if ((ret =
|
||||||
tuples.sip.u6_addr32, ori_src.ip, false, true))) {
|
rewrite_ip(skb, ipversion, IPPROTO_UDP, ihl,
|
||||||
|
tuples.sip.u6_addr32, ori_src.ip, false, true))) {
|
||||||
bpf_printk("Shot IP: %d", ret);
|
bpf_printk("Shot IP: %d", ret);
|
||||||
return TC_ACT_SHOT;
|
return TC_ACT_SHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite udp src port
|
// Rewrite udp src port
|
||||||
if ((ret = rewrite_port(skb, IPPROTO_UDP, ihl, tuples.sport, ori_src.port,
|
if ((ret = rewrite_port(skb, IPPROTO_UDP, ihl, tuples.sport,
|
||||||
false, true))) {
|
ori_src.port, false, true))) {
|
||||||
bpf_printk("Shot Port: %d", ret);
|
bpf_printk("Shot Port: %d", ret);
|
||||||
return TC_ACT_SHOT;
|
return TC_ACT_SHOT;
|
||||||
}
|
}
|
||||||
@ -1950,8 +1956,8 @@ int tproxy_wan_ingress(struct __sk_buff *skb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite dst port.
|
// Rewrite dst port.
|
||||||
if ((ret = rewrite_port(skb, l4proto, ihl, tuples.dport, *tproxy_port, true,
|
if ((ret = rewrite_port(skb, l4proto, ihl, tuples.dport, *tproxy_port,
|
||||||
true))) {
|
true, true))) {
|
||||||
bpf_printk("Shot Port: %d", ret);
|
bpf_printk("Shot Port: %d", ret);
|
||||||
return TC_ACT_SHOT;
|
return TC_ACT_SHOT;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user