88
99 "github.com/rs/zerolog"
1010 "golang.org/x/net/icmp"
11+ "golang.org/x/net/ipv4"
12+ "golang.org/x/net/ipv6"
1113
1214 "github.com/cloudflare/cloudflared/packet"
1315)
@@ -32,8 +34,65 @@ type ICMPProxy interface {
3234 Request (pk * packet.ICMP , responder packet.FunnelUniPipe ) error
3335}
3436
35- func NewICMPProxy (listenIP netip.Addr , logger * zerolog.Logger ) (ICMPProxy , error ) {
36- return newICMPProxy (listenIP , logger , funnelIdleTimeout )
37+ type icmpRouter struct {
38+ ipv4Proxy ICMPProxy
39+ ipv6Proxy ICMPProxy
40+ }
41+
42+ // NewICMPProxy doesn't return an error if either ipv4 proxy or ipv6 proxy can be created. The machine might only
43+ // support one of them
44+ func NewICMPProxy (logger * zerolog.Logger ) (ICMPProxy , error ) {
45+ // TODO: TUN-6741: don't bind to all interface
46+ ipv4Proxy , ipv4Err := newICMPProxy (netip .IPv4Unspecified (), logger , funnelIdleTimeout )
47+ ipv6Proxy , ipv6Err := newICMPProxy (netip .IPv6Unspecified (), logger , funnelIdleTimeout )
48+ if ipv4Err != nil && ipv6Err != nil {
49+ return nil , fmt .Errorf ("cannot create ICMPv4 proxy: %v nor ICMPv6 proxy: %v" , ipv4Err , ipv6Err )
50+ }
51+ if ipv4Err != nil {
52+ logger .Warn ().Err (ipv4Err ).Msg ("failed to create ICMPv4 proxy, only ICMPv6 proxy is created" )
53+ ipv4Proxy = nil
54+ }
55+ if ipv6Err != nil {
56+ logger .Warn ().Err (ipv6Err ).Msg ("failed to create ICMPv6 proxy, only ICMPv4 proxy is created" )
57+ ipv6Proxy = nil
58+ }
59+ return & icmpRouter {
60+ ipv4Proxy : ipv4Proxy ,
61+ ipv6Proxy : ipv6Proxy ,
62+ }, nil
63+ }
64+
65+ func (ir * icmpRouter ) Serve (ctx context.Context ) error {
66+ if ir .ipv4Proxy != nil && ir .ipv6Proxy != nil {
67+ errC := make (chan error , 2 )
68+ go func () {
69+ errC <- ir .ipv4Proxy .Serve (ctx )
70+ }()
71+ go func () {
72+ errC <- ir .ipv6Proxy .Serve (ctx )
73+ }()
74+ return <- errC
75+ }
76+ if ir .ipv4Proxy != nil {
77+ return ir .ipv4Proxy .Serve (ctx )
78+ }
79+ if ir .ipv6Proxy != nil {
80+ return ir .ipv6Proxy .Serve (ctx )
81+ }
82+ return fmt .Errorf ("ICMPv4 proxy and ICMPv6 proxy are both nil" )
83+ }
84+
85+ func (ir * icmpRouter ) Request (pk * packet.ICMP , responder packet.FunnelUniPipe ) error {
86+ if pk .Dst .Is4 () {
87+ if ir .ipv4Proxy != nil {
88+ return ir .ipv4Proxy .Request (pk , responder )
89+ }
90+ return fmt .Errorf ("ICMPv4 proxy was not instantiated" )
91+ }
92+ if ir .ipv6Proxy != nil {
93+ return ir .ipv6Proxy .Request (pk , responder )
94+ }
95+ return fmt .Errorf ("ICMPv6 proxy was not instantiated" )
3796}
3897
3998func getICMPEcho (msg * icmp.Message ) (* icmp.Echo , error ) {
@@ -43,3 +102,7 @@ func getICMPEcho(msg *icmp.Message) (*icmp.Echo, error) {
43102 }
44103 return echo , nil
45104}
105+
106+ func isEchoReply (msg * icmp.Message ) bool {
107+ return msg .Type == ipv4 .ICMPTypeEchoReply || msg .Type == ipv6 .ICMPTypeEchoReply
108+ }
0 commit comments