mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 19:19:57 +00:00
TUN-6530: Implement ICMPv4 proxy
This proxy uses unprivileged datagram-oriented endpoint and is shared by all quic connections
This commit is contained in:
@@ -75,9 +75,9 @@ func NewIPDecoder() *IPDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *IPDecoder) Decode(packet []byte) (*IP, error) {
|
||||
func (pd *IPDecoder) Decode(packet RawPacket) (*IP, error) {
|
||||
// Should decode to IP layer
|
||||
decoded, err := pd.decodeByVersion(packet)
|
||||
decoded, err := pd.decodeByVersion(packet.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -139,9 +139,9 @@ func NewICMPDecoder() *ICMPDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *ICMPDecoder) Decode(packet []byte) (*ICMP, error) {
|
||||
func (pd *ICMPDecoder) Decode(packet RawPacket) (*ICMP, error) {
|
||||
// Should decode to IP and optionally ICMP layer
|
||||
decoded, err := pd.decodeByVersion(packet)
|
||||
decoded, err := pd.decodeByVersion(packet.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -43,11 +43,11 @@ func TestDecodeIP(t *testing.T) {
|
||||
p, err := encoder.Encode(&udp)
|
||||
require.NoError(t, err)
|
||||
|
||||
ipPacket, err := ipDecoder.Decode(p.Data)
|
||||
ipPacket, err := ipDecoder.Decode(p)
|
||||
require.NoError(t, err)
|
||||
assertIPLayer(t, &udp.IP, ipPacket)
|
||||
|
||||
icmpPacket, err := icmpDecoder.Decode(p.Data)
|
||||
icmpPacket, err := icmpDecoder.Decode(p)
|
||||
require.Error(t, err)
|
||||
require.Nil(t, icmpPacket)
|
||||
}
|
||||
@@ -137,14 +137,14 @@ func TestDecodeICMP(t *testing.T) {
|
||||
p, err := encoder.Encode(test.packet)
|
||||
require.NoError(t, err)
|
||||
|
||||
ipPacket, err := ipDecoder.Decode(p.Data)
|
||||
ipPacket, err := ipDecoder.Decode(p)
|
||||
require.NoError(t, err)
|
||||
if ipPacket.Src.Is4() {
|
||||
assertIPLayer(t, &ipv4Packet, ipPacket)
|
||||
} else {
|
||||
assertIPLayer(t, &ipv6Packet, ipPacket)
|
||||
}
|
||||
icmpPacket, err := icmpDecoder.Decode(p.Data)
|
||||
icmpPacket, err := icmpDecoder.Decode(p)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, ipPacket, icmpPacket.IP)
|
||||
|
||||
@@ -202,11 +202,11 @@ func TestDecodeBadPackets(t *testing.T) {
|
||||
ipDecoder := NewIPDecoder()
|
||||
icmpDecoder := NewICMPDecoder()
|
||||
for _, test := range tests {
|
||||
ipPacket, err := ipDecoder.Decode(test.packet)
|
||||
ipPacket, err := ipDecoder.Decode(RawPacket{Data: test.packet})
|
||||
require.Error(t, err)
|
||||
require.Nil(t, ipPacket)
|
||||
|
||||
icmpPacket, err := icmpDecoder.Decode(test.packet)
|
||||
icmpPacket, err := icmpDecoder.Decode(RawPacket{Data: test.packet})
|
||||
require.Error(t, err)
|
||||
require.Nil(t, icmpPacket)
|
||||
}
|
||||
|
@@ -2,19 +2,17 @@ package packet
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"net/netip"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type flowID string
|
||||
|
||||
var (
|
||||
ErrFlowNotFound = errors.New("flow not found")
|
||||
)
|
||||
|
||||
func newFlowID(ip net.IP) flowID {
|
||||
return flowID(ip.String())
|
||||
// FlowID represents a key type that can be used by FlowTracker
|
||||
type FlowID interface {
|
||||
ID() string
|
||||
}
|
||||
|
||||
type Flow struct {
|
||||
@@ -37,32 +35,29 @@ type FlowResponder interface {
|
||||
SendPacket(pk RawPacket) error
|
||||
}
|
||||
|
||||
// SrcFlowTracker tracks flow from the perspective of eyeball to origin
|
||||
// flowID is the source IP
|
||||
type SrcFlowTracker struct {
|
||||
// FlowTracker tracks flow from the perspective of eyeball to origin
|
||||
type FlowTracker struct {
|
||||
lock sync.RWMutex
|
||||
flows map[flowID]*Flow
|
||||
flows map[FlowID]*Flow
|
||||
}
|
||||
|
||||
func NewSrcFlowTracker() *SrcFlowTracker {
|
||||
return &SrcFlowTracker{
|
||||
flows: make(map[flowID]*Flow),
|
||||
func NewFlowTracker() *FlowTracker {
|
||||
return &FlowTracker{
|
||||
flows: make(map[FlowID]*Flow),
|
||||
}
|
||||
}
|
||||
|
||||
func (sft *SrcFlowTracker) Get(srcIP net.IP) (*Flow, bool) {
|
||||
func (sft *FlowTracker) Get(id FlowID) (*Flow, bool) {
|
||||
sft.lock.RLock()
|
||||
defer sft.lock.RUnlock()
|
||||
id := newFlowID(srcIP)
|
||||
flow, ok := sft.flows[id]
|
||||
return flow, ok
|
||||
}
|
||||
|
||||
// Registers a flow. If shouldReplace = true, replace the current flow
|
||||
func (sft *SrcFlowTracker) Register(flow *Flow, shouldReplace bool) (replaced bool) {
|
||||
func (sft *FlowTracker) Register(id FlowID, flow *Flow, shouldReplace bool) (replaced bool) {
|
||||
sft.lock.Lock()
|
||||
defer sft.lock.Unlock()
|
||||
id := flowID(flow.Src.String())
|
||||
currentFlow, ok := sft.flows[id]
|
||||
if !ok {
|
||||
sft.flows[id] = flow
|
||||
@@ -77,10 +72,9 @@ func (sft *SrcFlowTracker) Register(flow *Flow, shouldReplace bool) (replaced bo
|
||||
}
|
||||
|
||||
// Unregisters a flow. If force = true, delete it even if it maps to a different flow
|
||||
func (sft *SrcFlowTracker) Unregister(flow *Flow, force bool) (forceDeleted bool) {
|
||||
func (sft *FlowTracker) Unregister(id FlowID, flow *Flow, force bool) (forceDeleted bool) {
|
||||
sft.lock.Lock()
|
||||
defer sft.lock.Unlock()
|
||||
id := flowID(flow.Src.String())
|
||||
currentFlow, ok := sft.flows[id]
|
||||
if !ok {
|
||||
return false
|
||||
|
Reference in New Issue
Block a user