xjasonlyu
3 years ago
10 changed files with 143 additions and 134 deletions
@ -1,22 +1,23 @@ |
|||
package stack |
|||
package core |
|||
|
|||
import ( |
|||
"github.com/xjasonlyu/tun2socks/v2/core/option" |
|||
|
|||
"gvisor.dev/gvisor/pkg/tcpip" |
|||
"gvisor.dev/gvisor/pkg/tcpip/header" |
|||
"gvisor.dev/gvisor/pkg/tcpip/stack" |
|||
) |
|||
|
|||
func withICMPHandler() Option { |
|||
return func(s *Stack) error { |
|||
// Add default route table for IPv4 and IPv6.
|
|||
// This will handle all incoming ICMP packets.
|
|||
func withRouteTable(nicID tcpip.NICID) option.Option { |
|||
return func(s *stack.Stack) error { |
|||
s.SetRouteTable([]tcpip.Route{ |
|||
{ |
|||
Destination: header.IPv4EmptySubnet, |
|||
NIC: s.nicID, |
|||
NIC: nicID, |
|||
}, |
|||
{ |
|||
Destination: header.IPv6EmptySubnet, |
|||
NIC: s.nicID, |
|||
NIC: nicID, |
|||
}, |
|||
}) |
|||
return nil |
@ -0,0 +1,75 @@ |
|||
package core |
|||
|
|||
import ( |
|||
"github.com/xjasonlyu/tun2socks/v2/core/adapter" |
|||
"github.com/xjasonlyu/tun2socks/v2/core/option" |
|||
|
|||
"gvisor.dev/gvisor/pkg/tcpip" |
|||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4" |
|||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6" |
|||
"gvisor.dev/gvisor/pkg/tcpip/stack" |
|||
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp" |
|||
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp" |
|||
"gvisor.dev/gvisor/pkg/tcpip/transport/udp" |
|||
) |
|||
|
|||
// CreateStackWithOptions creates *stack.Stack with given options.
|
|||
func CreateStackWithOptions(linkEP stack.LinkEndpoint, handler adapter.Handler, opts ...option.Option) (*stack.Stack, error) { |
|||
s := stack.New(stack.Options{ |
|||
NetworkProtocols: []stack.NetworkProtocolFactory{ |
|||
ipv4.NewProtocol, |
|||
ipv6.NewProtocol, |
|||
}, |
|||
TransportProtocols: []stack.TransportProtocolFactory{ |
|||
tcp.NewProtocol, |
|||
udp.NewProtocol, |
|||
icmp.NewProtocol4, |
|||
icmp.NewProtocol6, |
|||
}, |
|||
}) |
|||
|
|||
// Generate unique NIC id.
|
|||
nicID := tcpip.NICID(s.UniqueID()) |
|||
|
|||
opts = append(opts, |
|||
// Create stack NIC and then bind link endpoint to it.
|
|||
withCreatingNIC(nicID, linkEP), |
|||
|
|||
// In the past we did s.AddAddressRange to assign 0.0.0.0/0
|
|||
// onto the interface. We need that to be able to terminate
|
|||
// all the incoming connections - to any ip. AddressRange API
|
|||
// has been removed and the suggested workaround is to use
|
|||
// Promiscuous mode. https://github.com/google/gvisor/issues/3876
|
|||
//
|
|||
// Ref: https://github.com/cloudflare/slirpnetstack/blob/master/stack.go
|
|||
withPromiscuousMode(nicID, nicPromiscuousModeEnabled), |
|||
|
|||
// Enable spoofing if a stack may send packets from unowned
|
|||
// addresses. This change required changes to some netgophers
|
|||
// since previously, promiscuous mode was enough to let the
|
|||
// netstack respond to all incoming packets regardless of the
|
|||
// packet's destination address. Now that a stack.Route is not
|
|||
// held for each incoming packet, finding a route may fail with
|
|||
// local addresses we don't own but accepted packets for while
|
|||
// in promiscuous mode. Since we also want to be able to send
|
|||
// from any address (in response the received promiscuous mode
|
|||
// packets), we need to enable spoofing.
|
|||
//
|
|||
// Ref: https://github.com/google/gvisor/commit/8c0701462a84ff77e602f1626aec49479c308127
|
|||
withSpoofing(nicID, nicSpoofingEnabled), |
|||
|
|||
// Add default route table for IPv4 and IPv6. This will handle
|
|||
// all incoming ICMP packets.
|
|||
withRouteTable(nicID), |
|||
|
|||
// Initiate transport protocol (TCP/UDP) with given handler.
|
|||
withTCPHandler(handler.HandleTCP), withUDPHandler(handler.HandleUDP), |
|||
) |
|||
|
|||
for _, opt := range opts { |
|||
if err := opt(s); err != nil { |
|||
return nil, err |
|||
} |
|||
} |
|||
return s, nil |
|||
} |
@ -1,82 +0,0 @@ |
|||
// Package stack provides a thin wrapper around a gVisor's stack.
|
|||
package stack |
|||
|
|||
import ( |
|||
"github.com/xjasonlyu/tun2socks/v2/core/adapter" |
|||
|
|||
"gvisor.dev/gvisor/pkg/tcpip" |
|||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4" |
|||
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6" |
|||
"gvisor.dev/gvisor/pkg/tcpip/stack" |
|||
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp" |
|||
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp" |
|||
"gvisor.dev/gvisor/pkg/tcpip/transport/udp" |
|||
) |
|||
|
|||
type Stack struct { |
|||
*stack.Stack |
|||
|
|||
handler adapter.Handler |
|||
nicID tcpip.NICID |
|||
} |
|||
|
|||
// New allocates a new *Stack with given options.
|
|||
func New(ep stack.LinkEndpoint, handler adapter.Handler, opts ...Option) (*Stack, error) { |
|||
s := &Stack{ |
|||
Stack: stack.New(stack.Options{ |
|||
NetworkProtocols: []stack.NetworkProtocolFactory{ |
|||
ipv4.NewProtocol, |
|||
ipv6.NewProtocol, |
|||
}, |
|||
TransportProtocols: []stack.TransportProtocolFactory{ |
|||
tcp.NewProtocol, |
|||
udp.NewProtocol, |
|||
icmp.NewProtocol4, |
|||
icmp.NewProtocol6, |
|||
}, |
|||
}), |
|||
|
|||
handler: handler, |
|||
nicID: defaultNICID, |
|||
} |
|||
|
|||
opts = append(opts, |
|||
// Important: We must initiate transport protocol handlers
|
|||
// before creating NIC, otherwise NIC would dispatch packets
|
|||
// to stack and cause race condition.
|
|||
withICMPHandler(), withTCPHandler(), withUDPHandler(), |
|||
|
|||
// Create stack NIC and then bind link endpoint.
|
|||
withCreatingNIC(ep), |
|||
|
|||
// In the past we did s.AddAddressRange to assign 0.0.0.0/0
|
|||
// onto the interface. We need that to be able to terminate
|
|||
// all the incoming connections - to any ip. AddressRange API
|
|||
// has been removed and the suggested workaround is to use
|
|||
// Promiscuous mode. https://github.com/google/gvisor/issues/3876
|
|||
//
|
|||
// Ref: https://github.com/cloudflare/slirpnetstack/blob/master/stack.go
|
|||
withPromiscuousMode(nicPromiscuousModeEnabled), |
|||
|
|||
// Enable spoofing if a stack may send packets from unowned addresses.
|
|||
// This change required changes to some netgophers since previously,
|
|||
// promiscuous mode was enough to let the netstack respond to all
|
|||
// incoming packets regardless of the packet's destination address. Now
|
|||
// that a stack.Route is not held for each incoming packet, finding a route
|
|||
// may fail with local addresses we don't own but accepted packets for
|
|||
// while in promiscuous mode. Since we also want to be able to send from
|
|||
// any address (in response the received promiscuous mode packets), we need
|
|||
// to enable spoofing.
|
|||
//
|
|||
// Ref: https://github.com/google/gvisor/commit/8c0701462a84ff77e602f1626aec49479c308127
|
|||
withSpoofing(nicSpoofingEnabled), |
|||
) |
|||
|
|||
for _, opt := range opts { |
|||
if err := opt(s); err != nil { |
|||
return nil, err |
|||
} |
|||
} |
|||
|
|||
return s, nil |
|||
} |
Loading…
Reference in new issue