diff --git a/bpf/rtt_tracker.h b/bpf/rtt_tracker.h
index 4d62e98d34c384d14199a694d24d94a7a0512521..1176a520655ffd852939cdb9424762a7fffb3d28 100644
--- a/bpf/rtt_tracker.h
+++ b/bpf/rtt_tracker.h
@@ -157,4 +157,12 @@ int BPF_PROG(tcp_rcv_fentry, struct sock *sk, struct sk_buff *skb) {
 	return calculate_flow_rtt_tcp(sk, skb);
 }
 
+SEC("kprobe/tcp_rcv_established")
+int BPF_KPROBE(tcp_rcv_kprobe, struct sock *sk, struct sk_buff *skb) {
+    if (sk == NULL || skb == NULL) {
+        return 0;
+    }
+	return calculate_flow_rtt_tcp(sk, skb);
+}
+
 #endif /* __RTT_TRACKER_H__ */
diff --git a/pkg/ebpf/bpf_arm64_bpfel.go b/pkg/ebpf/bpf_arm64_bpfel.go
index bc204c62819ffb303f28c67b7db03df171e4135a..ad33b0b590cb6e237e2ad7b392867980f07b07ca 100644
--- a/pkg/ebpf/bpf_arm64_bpfel.go
+++ b/pkg/ebpf/bpf_arm64_bpfel.go
@@ -120,6 +120,7 @@ type BpfProgramSpecs struct {
 	IngressPcaParse  *ebpf.ProgramSpec `ebpf:"ingress_pca_parse"`
 	KfreeSkb         *ebpf.ProgramSpec `ebpf:"kfree_skb"`
 	TcpRcvFentry     *ebpf.ProgramSpec `ebpf:"tcp_rcv_fentry"`
+	TcpRcvKprobe     *ebpf.ProgramSpec `ebpf:"tcp_rcv_kprobe"`
 }
 
 // BpfMapSpecs contains maps before they are loaded into the kernel.
@@ -176,6 +177,7 @@ type BpfPrograms struct {
 	IngressPcaParse  *ebpf.Program `ebpf:"ingress_pca_parse"`
 	KfreeSkb         *ebpf.Program `ebpf:"kfree_skb"`
 	TcpRcvFentry     *ebpf.Program `ebpf:"tcp_rcv_fentry"`
+	TcpRcvKprobe     *ebpf.Program `ebpf:"tcp_rcv_kprobe"`
 }
 
 func (p *BpfPrograms) Close() error {
@@ -186,6 +188,7 @@ func (p *BpfPrograms) Close() error {
 		p.IngressPcaParse,
 		p.KfreeSkb,
 		p.TcpRcvFentry,
+		p.TcpRcvKprobe,
 	)
 }
 
diff --git a/pkg/ebpf/bpf_arm64_bpfel.o b/pkg/ebpf/bpf_arm64_bpfel.o
index da101f9d91d3b84b8a21527cf72452c3cda95ce6..546a70ad9e4f9fe66dff15ab54a6e344c73a246d 100644
Binary files a/pkg/ebpf/bpf_arm64_bpfel.o and b/pkg/ebpf/bpf_arm64_bpfel.o differ
diff --git a/pkg/ebpf/bpf_powerpc_bpfel.go b/pkg/ebpf/bpf_powerpc_bpfel.go
index e074d6d88d7e1734a9da0964199c2b0d2c065ccc..bacd97f2254bde89c865eef08f2f9eeebf28afab 100644
--- a/pkg/ebpf/bpf_powerpc_bpfel.go
+++ b/pkg/ebpf/bpf_powerpc_bpfel.go
@@ -120,6 +120,7 @@ type BpfProgramSpecs struct {
 	IngressPcaParse  *ebpf.ProgramSpec `ebpf:"ingress_pca_parse"`
 	KfreeSkb         *ebpf.ProgramSpec `ebpf:"kfree_skb"`
 	TcpRcvFentry     *ebpf.ProgramSpec `ebpf:"tcp_rcv_fentry"`
+	TcpRcvKprobe     *ebpf.ProgramSpec `ebpf:"tcp_rcv_kprobe"`
 }
 
 // BpfMapSpecs contains maps before they are loaded into the kernel.
@@ -176,6 +177,7 @@ type BpfPrograms struct {
 	IngressPcaParse  *ebpf.Program `ebpf:"ingress_pca_parse"`
 	KfreeSkb         *ebpf.Program `ebpf:"kfree_skb"`
 	TcpRcvFentry     *ebpf.Program `ebpf:"tcp_rcv_fentry"`
+	TcpRcvKprobe     *ebpf.Program `ebpf:"tcp_rcv_kprobe"`
 }
 
 func (p *BpfPrograms) Close() error {
@@ -186,6 +188,7 @@ func (p *BpfPrograms) Close() error {
 		p.IngressPcaParse,
 		p.KfreeSkb,
 		p.TcpRcvFentry,
+		p.TcpRcvKprobe,
 	)
 }
 
diff --git a/pkg/ebpf/bpf_powerpc_bpfel.o b/pkg/ebpf/bpf_powerpc_bpfel.o
index 1b33de675a1c5da94f1fe3acd27479ada68298be..515122a49ce0d1444ce7b70300199fb0f6b9f292 100644
Binary files a/pkg/ebpf/bpf_powerpc_bpfel.o and b/pkg/ebpf/bpf_powerpc_bpfel.o differ
diff --git a/pkg/ebpf/bpf_s390_bpfeb.go b/pkg/ebpf/bpf_s390_bpfeb.go
index f129c345ff0bbf4059f0e9dd652aa5c36da3d858..a4b5e44f91488004a839a00b62b509c2fca6cd23 100644
--- a/pkg/ebpf/bpf_s390_bpfeb.go
+++ b/pkg/ebpf/bpf_s390_bpfeb.go
@@ -120,6 +120,7 @@ type BpfProgramSpecs struct {
 	IngressPcaParse  *ebpf.ProgramSpec `ebpf:"ingress_pca_parse"`
 	KfreeSkb         *ebpf.ProgramSpec `ebpf:"kfree_skb"`
 	TcpRcvFentry     *ebpf.ProgramSpec `ebpf:"tcp_rcv_fentry"`
+	TcpRcvKprobe     *ebpf.ProgramSpec `ebpf:"tcp_rcv_kprobe"`
 }
 
 // BpfMapSpecs contains maps before they are loaded into the kernel.
@@ -176,6 +177,7 @@ type BpfPrograms struct {
 	IngressPcaParse  *ebpf.Program `ebpf:"ingress_pca_parse"`
 	KfreeSkb         *ebpf.Program `ebpf:"kfree_skb"`
 	TcpRcvFentry     *ebpf.Program `ebpf:"tcp_rcv_fentry"`
+	TcpRcvKprobe     *ebpf.Program `ebpf:"tcp_rcv_kprobe"`
 }
 
 func (p *BpfPrograms) Close() error {
@@ -186,6 +188,7 @@ func (p *BpfPrograms) Close() error {
 		p.IngressPcaParse,
 		p.KfreeSkb,
 		p.TcpRcvFentry,
+		p.TcpRcvKprobe,
 	)
 }
 
diff --git a/pkg/ebpf/bpf_s390_bpfeb.o b/pkg/ebpf/bpf_s390_bpfeb.o
index f1d6c7fbf11dbfd8b71ee356c8a76c6110103870..84587efd93cd62351a7838f6b2ccb5bc7703fa6e 100644
Binary files a/pkg/ebpf/bpf_s390_bpfeb.o and b/pkg/ebpf/bpf_s390_bpfeb.o differ
diff --git a/pkg/ebpf/bpf_x86_bpfel.go b/pkg/ebpf/bpf_x86_bpfel.go
index 5b39854730c7912d72928b06ccb5bdbd6eedb5ee..a06125656e6ef387bf6e0d5adda8ee2a0f91d465 100644
--- a/pkg/ebpf/bpf_x86_bpfel.go
+++ b/pkg/ebpf/bpf_x86_bpfel.go
@@ -120,6 +120,7 @@ type BpfProgramSpecs struct {
 	IngressPcaParse  *ebpf.ProgramSpec `ebpf:"ingress_pca_parse"`
 	KfreeSkb         *ebpf.ProgramSpec `ebpf:"kfree_skb"`
 	TcpRcvFentry     *ebpf.ProgramSpec `ebpf:"tcp_rcv_fentry"`
+	TcpRcvKprobe     *ebpf.ProgramSpec `ebpf:"tcp_rcv_kprobe"`
 }
 
 // BpfMapSpecs contains maps before they are loaded into the kernel.
@@ -176,6 +177,7 @@ type BpfPrograms struct {
 	IngressPcaParse  *ebpf.Program `ebpf:"ingress_pca_parse"`
 	KfreeSkb         *ebpf.Program `ebpf:"kfree_skb"`
 	TcpRcvFentry     *ebpf.Program `ebpf:"tcp_rcv_fentry"`
+	TcpRcvKprobe     *ebpf.Program `ebpf:"tcp_rcv_kprobe"`
 }
 
 func (p *BpfPrograms) Close() error {
@@ -186,6 +188,7 @@ func (p *BpfPrograms) Close() error {
 		p.IngressPcaParse,
 		p.KfreeSkb,
 		p.TcpRcvFentry,
+		p.TcpRcvKprobe,
 	)
 }
 
diff --git a/pkg/ebpf/bpf_x86_bpfel.o b/pkg/ebpf/bpf_x86_bpfel.o
index 9ebe3a2b72cf126d8bf508946ffde6bb9c9a2379..2929682616484946758b1d783165204cc84e8be2 100644
Binary files a/pkg/ebpf/bpf_x86_bpfel.o and b/pkg/ebpf/bpf_x86_bpfel.o differ
diff --git a/pkg/ebpf/tracer.go b/pkg/ebpf/tracer.go
index 7a4c4419467d6d3b1bbd350303d34eb5bc835114..7cdb4b574c0e58fb94e5251b494fed46e91e4113 100644
--- a/pkg/ebpf/tracer.go
+++ b/pkg/ebpf/tracer.go
@@ -62,6 +62,7 @@ type FlowFetcher struct {
 	enableEgress       bool
 	pktDropsTracePoint link.Link
 	rttFentryLink      link.Link
+	rttKprobeLink      link.Link
 }
 
 type FlowFetcherConfig struct {
@@ -141,13 +142,18 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) {
 		}
 	}
 
-	var rttFentryLink link.Link
+	var rttFentryLink, rttKprobeLink link.Link
 	if cfg.EnableRTT {
 		rttFentryLink, err = link.AttachTracing(link.TracingOptions{
 			Program: objects.BpfPrograms.TcpRcvFentry,
 		})
 		if err != nil {
-			return nil, fmt.Errorf("failed to attach the BPF program to tcpReceiveFentry: %w", err)
+			log.Warningf("failed to attach the BPF program to tcpReceiveFentry: %v fallback to use kprobe", err)
+			// try to use kprobe for older kernels
+			rttKprobeLink, err = link.Kprobe("tcp_rcv_established", objects.TcpRcvKprobe, nil)
+			if err != nil {
+				return nil, fmt.Errorf("failed to attach the BPF program to tcpReceiveKprobe: %w", err)
+			}
 		}
 	}
 
@@ -167,6 +173,7 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) {
 		enableEgress:       cfg.EnableEgress,
 		pktDropsTracePoint: pktDropsLink,
 		rttFentryLink:      rttFentryLink,
+		rttKprobeLink:      rttKprobeLink,
 	}, nil
 }
 
@@ -300,6 +307,11 @@ func (m *FlowFetcher) Close() error {
 			errs = append(errs, err)
 		}
 	}
+	if m.rttKprobeLink != nil {
+		if err := m.rttKprobeLink.Close(); err != nil {
+			errs = append(errs, err)
+		}
+	}
 	// m.ringbufReader.Read is a blocking operation, so we need to close the ring buffer
 	// from another goroutine to avoid the system not being able to exit if there
 	// isn't traffic in a given interface
@@ -460,6 +472,7 @@ func kernelSpecificLoadAndAssign(oldKernel bool, spec *ebpf.CollectionSpec) (Bpf
 			EgressFlowParse  *ebpf.Program `ebpf:"egress_flow_parse"`
 			IngressFlowParse *ebpf.Program `ebpf:"ingress_flow_parse"`
 			TCPRcvFentry     *ebpf.Program `ebpf:"tcp_rcv_fentry"`
+			TCPRcvKprobe     *ebpf.Program `ebpf:"tcp_rcv_kprobe"`
 		}
 		type NewBpfObjects struct {
 			NewBpfPrograms
@@ -485,6 +498,7 @@ func kernelSpecificLoadAndAssign(oldKernel bool, spec *ebpf.CollectionSpec) (Bpf
 		objects.EgressFlowParse = newObjects.EgressFlowParse
 		objects.IngressFlowParse = newObjects.IngressFlowParse
 		objects.TcpRcvFentry = newObjects.TCPRcvFentry
+		objects.TcpRcvKprobe = newObjects.TCPRcvKprobe
 		objects.KfreeSkb = nil
 	} else {
 		if err := spec.LoadAndAssign(&objects, nil); err != nil {