mirror of
https://github.com/daeuniverse/dae.git
synced 2025-07-15 02:09:57 +07:00
fix: incorrectly throw error when 5.2<=kernel<5.5
This commit is contained in:
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
package consts
|
package consts
|
||||||
|
|
||||||
|
import internal "github.com/v2rayA/dae/pkg/ebpf_internal"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AppName = "dae"
|
AppName = "dae"
|
||||||
BpfPinRoot = "/sys/fs/bpf"
|
BpfPinRoot = "/sys/fs/bpf"
|
||||||
@ -93,3 +95,5 @@ const (
|
|||||||
IpVersion_6 IpVersion = 2
|
IpVersion_6 IpVersion = 2
|
||||||
IpVersion_X IpVersion = 3
|
IpVersion_X IpVersion = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var FtraceFeatureVersion = internal.Version{5, 5, 0}
|
||||||
|
@ -95,3 +95,37 @@ func BatchUpdate(m *ebpf.Map, keys interface{}, values interface{}, opts *ebpf.B
|
|||||||
return vKeys.Len(), nil
|
return vKeys.Len(), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type bpfObjectsLan struct {
|
||||||
|
// NOTICE: Consider to update me if any program added.
|
||||||
|
TproxyEgress *ebpf.Program `ebpf:"tproxy_egress"`
|
||||||
|
TproxyIngress *ebpf.Program `ebpf:"tproxy_ingress"`
|
||||||
|
|
||||||
|
bpfMaps
|
||||||
|
}
|
||||||
|
|
||||||
|
func AssignBpfPrograms(to *bpfObjects, from interface{}) {
|
||||||
|
vTo := reflect.Indirect(reflect.ValueOf(to))
|
||||||
|
vFrom := reflect.Indirect(reflect.ValueOf(from))
|
||||||
|
tFrom := vFrom.Type()
|
||||||
|
// programs
|
||||||
|
for i := 0; i < vFrom.NumField(); i++ {
|
||||||
|
fieldFrom := vFrom.Field(i)
|
||||||
|
structFieldFrom := tFrom.Field(i)
|
||||||
|
if structFieldFrom.Type != reflect.TypeOf(&ebpf.Program{}) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fieldTo := vTo.FieldByName(structFieldFrom.Name)
|
||||||
|
fieldTo.Set(fieldFrom)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bpfMaps
|
||||||
|
vFrom = vFrom.FieldByName("bpfMaps")
|
||||||
|
tFrom = vFrom.Type()
|
||||||
|
for i := 0; i < vFrom.NumField(); i++ {
|
||||||
|
fieldFrom := vFrom.Field(i)
|
||||||
|
structFieldFrom := tFrom.Field(i)
|
||||||
|
fieldTo := vTo.FieldByName(structFieldFrom.Name)
|
||||||
|
fieldTo.Set(fieldFrom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -38,6 +38,8 @@ import (
|
|||||||
type ControlPlane struct {
|
type ControlPlane struct {
|
||||||
log *logrus.Logger
|
log *logrus.Logger
|
||||||
|
|
||||||
|
kernelVersion *internal.Version
|
||||||
|
|
||||||
// TODO: add mutex?
|
// TODO: add mutex?
|
||||||
outbounds []*outbound.DialerGroup
|
outbounds []*outbound.DialerGroup
|
||||||
outboundName2Id map[string]uint8
|
outboundName2Id map[string]uint8
|
||||||
@ -64,6 +66,11 @@ func NewControlPlane(
|
|||||||
checkUrl string,
|
checkUrl string,
|
||||||
checkInterval time.Duration,
|
checkInterval time.Duration,
|
||||||
) (c *ControlPlane, err error) {
|
) (c *ControlPlane, err error) {
|
||||||
|
kernelVersion, e := internal.KernelVersion()
|
||||||
|
if e != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get kernel version: %w", e)
|
||||||
|
}
|
||||||
|
|
||||||
// Allow the current process to lock memory for eBPF resources.
|
// Allow the current process to lock memory for eBPF resources.
|
||||||
if err = rlimit.RemoveMemlock(); err != nil {
|
if err = rlimit.RemoveMemlock(); err != nil {
|
||||||
return nil, fmt.Errorf("rlimit.RemoveMemlock:%v", err)
|
return nil, fmt.Errorf("rlimit.RemoveMemlock:%v", err)
|
||||||
@ -73,14 +80,20 @@ func NewControlPlane(
|
|||||||
|
|
||||||
// Load pre-compiled programs and maps into the kernel.
|
// Load pre-compiled programs and maps into the kernel.
|
||||||
var bpf bpfObjects
|
var bpf bpfObjects
|
||||||
|
var bpfLan bpfObjectsLan
|
||||||
var ProgramOptions ebpf.ProgramOptions
|
var ProgramOptions ebpf.ProgramOptions
|
||||||
if log.IsLevelEnabled(logrus.TraceLevel) {
|
if log.IsLevelEnabled(logrus.TraceLevel) {
|
||||||
ProgramOptions = ebpf.ProgramOptions{
|
ProgramOptions = ebpf.ProgramOptions{
|
||||||
LogLevel: ebpf.LogLevelStats,
|
LogLevel: ebpf.LogLevelStats,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var obj interface{} = &bpf
|
||||||
|
if kernelVersion.Less(consts.FtraceFeatureVersion) {
|
||||||
|
// Trick. Replace the beams with rotten timbers.
|
||||||
|
obj = &bpfLan
|
||||||
|
}
|
||||||
retryLoadBpf:
|
retryLoadBpf:
|
||||||
if err = loadBpfObjects(&bpf, &ebpf.CollectionOptions{
|
if err = loadBpfObjects(obj, &ebpf.CollectionOptions{
|
||||||
Maps: ebpf.MapOptions{
|
Maps: ebpf.MapOptions{
|
||||||
PinPath: pinPath,
|
PinPath: pinPath,
|
||||||
},
|
},
|
||||||
@ -110,6 +123,11 @@ retryLoadBpf:
|
|||||||
}
|
}
|
||||||
return nil, fmt.Errorf("loading objects: %v", err)
|
return nil, fmt.Errorf("loading objects: %v", err)
|
||||||
}
|
}
|
||||||
|
if kernelVersion.Less(consts.FtraceFeatureVersion) {
|
||||||
|
// Reverse takeover.
|
||||||
|
AssignBpfPrograms(&bpf, &bpfLan)
|
||||||
|
}
|
||||||
|
|
||||||
// Write params.
|
// Write params.
|
||||||
if err = bpf.ParamMap.Update(consts.DisableL4TxChecksumKey, consts.DisableL4ChecksumPolicy_SetZero, ebpf.UpdateAny); err != nil {
|
if err = bpf.ParamMap.Update(consts.DisableL4TxChecksumKey, consts.DisableL4ChecksumPolicy_SetZero, ebpf.UpdateAny); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -235,6 +253,7 @@ retryLoadBpf:
|
|||||||
|
|
||||||
return &ControlPlane{
|
return &ControlPlane{
|
||||||
log: log,
|
log: log,
|
||||||
|
kernelVersion: &kernelVersion,
|
||||||
outbounds: outbounds,
|
outbounds: outbounds,
|
||||||
outboundName2Id: outboundName2Id,
|
outboundName2Id: outboundName2Id,
|
||||||
bpf: &bpf,
|
bpf: &bpf,
|
||||||
@ -369,22 +388,17 @@ func (c *ControlPlane) BindLan(ifname string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ControlPlane) BindWan(ifname string) error {
|
func (c *ControlPlane) BindWan(ifname string) error {
|
||||||
|
if c.kernelVersion.Less(consts.FtraceFeatureVersion) {
|
||||||
|
// Not support ftrace (fentry/fexit).
|
||||||
|
// PID bypass needs it.
|
||||||
|
return fmt.Errorf("your kernel version %v does not support bind to WAN; expect >=%v; remove wan_interface in config file and try again", c.kernelVersion.String(), consts.FtraceFeatureVersion.String())
|
||||||
|
}
|
||||||
|
|
||||||
link, err := netlink.LinkByName(ifname)
|
link, err := netlink.LinkByName(ifname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
version, e := internal.KernelVersion()
|
|
||||||
if e != nil {
|
|
||||||
return fmt.Errorf("BindWan: failed to get kernel version: %w", e)
|
|
||||||
}
|
|
||||||
ftraceFeatureVersion := internal.Version{5, 5, 0}
|
|
||||||
if version.Less(ftraceFeatureVersion) {
|
|
||||||
// Not support ftrace (fentry/fexit).
|
|
||||||
// PID bypass needs it.
|
|
||||||
return fmt.Errorf("your kernel version %v does not support bind to WAN; expect >=%v", version.String(), ftraceFeatureVersion.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set-up SrcPidMapper.
|
// Set-up SrcPidMapper.
|
||||||
// Attach programs to support pname routing.
|
// Attach programs to support pname routing.
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ func (b *RoutingMatcherBuilder) OutboundToId(outbound string) uint8 {
|
|||||||
var ok bool
|
var ok bool
|
||||||
outboundId, ok = b.outboundName2Id[outbound]
|
outboundId, ok = b.outboundName2Id[outbound]
|
||||||
if !ok {
|
if !ok {
|
||||||
b.err = fmt.Errorf("%v not in outboundName2Id", strconv.Quote(outbound))
|
b.err = fmt.Errorf("%v not defined in group", strconv.Quote(outbound))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return outboundId
|
return outboundId
|
||||||
|
Reference in New Issue
Block a user