рабочий вариант, но скороть 10 МБит
This commit is contained in:
@@ -18,6 +18,7 @@ type Gateway struct {
|
||||
Transport PacketTransport
|
||||
ClusterID string
|
||||
VPNConnectionID string
|
||||
ServiceTunnel FabricServiceTunnel
|
||||
InterfaceName string
|
||||
AddressCIDR string
|
||||
RouteCIDR string
|
||||
@@ -73,20 +74,6 @@ type packetTransportCloser interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
type BackendPacketTransport struct {
|
||||
API *client.Client
|
||||
ClusterID string
|
||||
VPNConnectionID string
|
||||
}
|
||||
|
||||
func (t BackendPacketTransport) SendGatewayPacketBatch(ctx context.Context, packets [][]byte) error {
|
||||
return t.API.SendVPNGatewayPacketBatch(ctx, t.ClusterID, t.VPNConnectionID, packets)
|
||||
}
|
||||
|
||||
func (t BackendPacketTransport) ReceiveGatewayPacketBatch(ctx context.Context, timeout time.Duration) ([][]byte, error) {
|
||||
return t.API.ReceiveVPNGatewayPacketBatch(ctx, t.ClusterID, t.VPNConnectionID, timeout)
|
||||
}
|
||||
|
||||
func (g *Gateway) EnsureStarted(ctx context.Context) error {
|
||||
g.mu.Lock()
|
||||
if g.running {
|
||||
@@ -120,7 +107,7 @@ func (g *Gateway) EnsureStarted(ctx context.Context) error {
|
||||
|
||||
go func() {
|
||||
if err := g.run(runCtx, tun); err != nil && runCtx.Err() == nil {
|
||||
log.Printf("vpn gateway runtime stopped: vpn_connection_id=%s error=%v", g.VPNConnectionID, err)
|
||||
log.Printf("vpn gateway runtime stopped: tunnel_id=%s error=%v", g.tunnelID(), err)
|
||||
g.setStopped(err)
|
||||
return
|
||||
}
|
||||
@@ -152,7 +139,8 @@ func (g *Gateway) Status() (bool, string) {
|
||||
func (g *Gateway) IsReadyForConnection(vpnConnectionID string) bool {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
return g.running && g.VPNConnectionID == vpnConnectionID && vpnConnectionID != ""
|
||||
tunnelID := g.tunnelIDLocked()
|
||||
return g.running && (g.VPNConnectionID == vpnConnectionID || tunnelID == vpnConnectionID) && vpnConnectionID != ""
|
||||
}
|
||||
|
||||
func (g *Gateway) Snapshot() map[string]any {
|
||||
@@ -169,8 +157,14 @@ func (g *Gateway) Snapshot() map[string]any {
|
||||
|
||||
out := map[string]any{
|
||||
"running": running,
|
||||
"service_role": "ipv4-egress",
|
||||
"service_class": "vpn_packets",
|
||||
"tunnel_id": g.ServiceTunnel.TunnelID,
|
||||
"pool_id": g.ServiceTunnel.PoolID,
|
||||
"service_id": g.ServiceTunnel.ServiceID,
|
||||
"local_service_id": g.ServiceTunnel.LocalServiceID,
|
||||
"remote_service_id": g.ServiceTunnel.RemoteServiceID,
|
||||
"service_kind": g.ServiceTunnel.ServiceKind,
|
||||
"service_role": firstNonEmptyTunnelString(g.ServiceTunnel.ServiceRole, DefaultFabricTunnelRole),
|
||||
"service_class": firstNonEmptyTunnelString(g.ServiceTunnel.ServiceClass, DefaultFabricTunnelClass),
|
||||
"adapter_contract": "fabric_channel_to_ipv4_nat",
|
||||
"transport": g.transportName(),
|
||||
"poll_timeout_ms": g.PollTimeout.Milliseconds(),
|
||||
@@ -196,6 +190,7 @@ func (g *Gateway) Snapshot() map[string]any {
|
||||
if !lastRuntimeActivityAt.IsZero() {
|
||||
out["last_runtime_activity_at"] = lastRuntimeActivityAt.UTC().Format(time.RFC3339Nano)
|
||||
}
|
||||
out["service_tunnel"] = g.ServiceTunnel.Snapshot()
|
||||
if platform := gatewayPlatformSnapshot(g.InterfaceName, g.RouteCIDR); len(platform) > 0 {
|
||||
out["platform"] = platform
|
||||
}
|
||||
@@ -216,9 +211,7 @@ func (g *Gateway) transportName() string {
|
||||
case *LocalPacketTransport:
|
||||
return "local_fabric_inbox"
|
||||
case *AdaptivePacketTransport:
|
||||
return "adaptive_fabric_backend"
|
||||
case BackendPacketTransport:
|
||||
return "backend_http_packet_relay"
|
||||
return "adaptive_fabric"
|
||||
default:
|
||||
if g.Transport == nil {
|
||||
return "none"
|
||||
@@ -237,10 +230,14 @@ func (g *Gateway) setStopped(err error) {
|
||||
|
||||
func (g *Gateway) normalize() error {
|
||||
if g.Transport == nil {
|
||||
return fmt.Errorf("fabric packet transport is required; backend packet relay fallback is disabled")
|
||||
return fmt.Errorf("fabric packet transport is required")
|
||||
}
|
||||
g.ServiceTunnel = NormalizeServiceTunnel(g.ServiceTunnel, g.VPNConnectionID)
|
||||
if g.VPNConnectionID == "" {
|
||||
g.VPNConnectionID = g.ServiceTunnel.TunnelID
|
||||
}
|
||||
if g.ClusterID == "" || g.VPNConnectionID == "" {
|
||||
return fmt.Errorf("cluster id and vpn connection id are required")
|
||||
return fmt.Errorf("cluster id and tunnel id are required")
|
||||
}
|
||||
if g.InterfaceName == "" {
|
||||
g.InterfaceName = "rapvpn0"
|
||||
@@ -257,6 +254,19 @@ func (g *Gateway) normalize() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateway) tunnelIDLocked() string {
|
||||
return firstNonEmptyTunnelString(g.ServiceTunnel.TunnelID, g.VPNConnectionID)
|
||||
}
|
||||
|
||||
func (g *Gateway) tunnelID() string {
|
||||
if g == nil {
|
||||
return ""
|
||||
}
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
return g.tunnelIDLocked()
|
||||
}
|
||||
|
||||
func (g *Gateway) run(ctx context.Context, tun readWriteCloser) error {
|
||||
defer tun.Close()
|
||||
if closer, ok := g.Transport.(packetTransportCloser); ok {
|
||||
@@ -279,11 +289,10 @@ func (g *Gateway) run(ctx context.Context, tun readWriteCloser) error {
|
||||
}
|
||||
|
||||
func (g *Gateway) copyGatewayToClient(ctx context.Context, tun io.Reader) error {
|
||||
priorityPackets := make(chan []byte, 1024)
|
||||
packets := make(chan []byte, 32768)
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
errCh <- g.uploadGatewayPackets(ctx, priorityPackets, packets)
|
||||
errCh <- g.uploadGatewayPackets(ctx, nil, packets)
|
||||
}()
|
||||
|
||||
buffer := make([]byte, 65535)
|
||||
@@ -307,25 +316,16 @@ func (g *Gateway) copyGatewayToClient(ctx context.Context, tun io.Reader) error
|
||||
packet := append([]byte(nil), buffer[:n]...)
|
||||
normalizeIPv4PacketChecksums(packet)
|
||||
g.recordTunRead(packet)
|
||||
if isTCPControlPacket(packet) {
|
||||
select {
|
||||
case priorityPackets <- packet:
|
||||
default:
|
||||
g.uploadQueueDrops.Add(1)
|
||||
log.Printf("vpn gateway priority packet upload queue full; dropping packet: vpn_connection_id=%s", g.VPNConnectionID)
|
||||
}
|
||||
continue
|
||||
}
|
||||
select {
|
||||
case packets <- packet:
|
||||
default:
|
||||
g.uploadQueueDrops.Add(1)
|
||||
log.Printf("vpn gateway packet upload queue full; dropping packet: vpn_connection_id=%s", g.VPNConnectionID)
|
||||
log.Printf("vpn gateway packet upload queue full; dropping packet: tunnel_id=%s", g.tunnelID())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gateway) uploadGatewayPackets(ctx context.Context, priorityPackets <-chan []byte, packets <-chan []byte) error {
|
||||
func (g *Gateway) uploadGatewayPackets(ctx context.Context, _ <-chan []byte, packets <-chan []byte) error {
|
||||
batch := make([][]byte, 0, vpnGatewayBatchMaxPackets)
|
||||
batchBytes := 0
|
||||
timer := time.NewTimer(time.Hour)
|
||||
@@ -341,7 +341,7 @@ func (g *Gateway) uploadGatewayPackets(ctx context.Context, priorityPackets <-ch
|
||||
byteCount := packetBytesTotal(batch)
|
||||
if err := g.Transport.SendGatewayPacketBatch(ctx, batch); err != nil {
|
||||
g.uploadErrors.Add(1)
|
||||
log.Printf("vpn gateway packet batch upload failed: vpn_connection_id=%s packets=%d error=%v", g.VPNConnectionID, len(batch), err)
|
||||
log.Printf("vpn gateway packet batch upload failed: tunnel_id=%s packets=%d error=%v", g.tunnelID(), len(batch), err)
|
||||
} else {
|
||||
g.recordGatewayToClientBatch(packetCount, byteCount, batch[0])
|
||||
}
|
||||
@@ -366,50 +366,6 @@ func (g *Gateway) uploadGatewayPackets(ctx context.Context, priorityPackets <-ch
|
||||
batchBytes += packetFrameSize
|
||||
return true
|
||||
}
|
||||
flushPriority := func(packet []byte) {
|
||||
pendingBatch := batch
|
||||
pendingBatchBytes := batchBytes
|
||||
batch = make([][]byte, 0, vpnGatewayBatchMaxPackets)
|
||||
batchBytes = 0
|
||||
if !addPacket(packet) {
|
||||
batch = pendingBatch
|
||||
batchBytes = pendingBatchBytes
|
||||
return
|
||||
}
|
||||
deadline := time.Now().Add(vpnGatewayPriorityBatchWait)
|
||||
for len(batch) < vpnGatewayBatchMaxPackets && batchBytes < vpnGatewayBatchMaxBytes {
|
||||
wait := time.Until(deadline)
|
||||
if wait <= 0 {
|
||||
break
|
||||
}
|
||||
timer := time.NewTimer(wait)
|
||||
select {
|
||||
case next := <-priorityPackets:
|
||||
if !timer.Stop() {
|
||||
select {
|
||||
case <-timer.C:
|
||||
default:
|
||||
}
|
||||
}
|
||||
if !addPacket(next) {
|
||||
flush()
|
||||
_ = addPacket(next)
|
||||
}
|
||||
case <-timer.C:
|
||||
flush()
|
||||
return
|
||||
}
|
||||
}
|
||||
flush()
|
||||
if len(pendingBatch) > 0 {
|
||||
batch = pendingBatch
|
||||
batchBytes = pendingBatchBytes
|
||||
if !timerActive {
|
||||
timer.Reset(vpnGatewayBatchFlushTimeout)
|
||||
timerActive = true
|
||||
}
|
||||
}
|
||||
}
|
||||
for {
|
||||
if len(batch) == 0 && timerActive {
|
||||
if !timer.Stop() {
|
||||
@@ -421,17 +377,9 @@ func (g *Gateway) uploadGatewayPackets(ctx context.Context, priorityPackets <-ch
|
||||
timerActive = false
|
||||
}
|
||||
select {
|
||||
case packet := <-priorityPackets:
|
||||
flushPriority(packet)
|
||||
continue
|
||||
default:
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
flush()
|
||||
return ctx.Err()
|
||||
case packet := <-priorityPackets:
|
||||
flushPriority(packet)
|
||||
case packet := <-packets:
|
||||
if !addPacket(packet) {
|
||||
continue
|
||||
@@ -451,23 +399,11 @@ func (g *Gateway) uploadGatewayPackets(ctx context.Context, priorityPackets <-ch
|
||||
}
|
||||
}
|
||||
|
||||
func isTCPControlPacket(packet []byte) bool {
|
||||
if len(packet) < 20 || packet[0]>>4 != 4 {
|
||||
return false
|
||||
}
|
||||
ihl := int(packet[0]&0x0f) * 4
|
||||
if ihl < 20 || len(packet) < ihl+20 || packet[9] != 6 {
|
||||
return false
|
||||
}
|
||||
flags := packet[ihl+13]
|
||||
return flags&0x17 != 0
|
||||
}
|
||||
|
||||
func (g *Gateway) copyClientToGateway(ctx context.Context, tun io.Writer) error {
|
||||
for {
|
||||
packets, err := g.Transport.ReceiveGatewayPacketBatch(ctx, g.PollTimeout)
|
||||
if err != nil {
|
||||
log.Printf("vpn gateway packet download failed: vpn_connection_id=%s error=%v", g.VPNConnectionID, err)
|
||||
log.Printf("vpn gateway packet download failed: tunnel_id=%s error=%v", g.tunnelID(), err)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
@@ -501,8 +437,8 @@ func (g *Gateway) recordClientToGatewayBatch(packetCount int, byteCount int, fir
|
||||
g.mu.Unlock()
|
||||
if next <= 5 {
|
||||
log.Printf(
|
||||
"vpn gateway client_to_gateway batch received: vpn_connection_id=%s batch=%d packets=%d bytes=%d first=%s",
|
||||
g.VPNConnectionID,
|
||||
"vpn gateway client_to_gateway batch received: tunnel_id=%s batch=%d packets=%d bytes=%d first=%s",
|
||||
g.tunnelID(),
|
||||
next,
|
||||
packetCount,
|
||||
byteCount,
|
||||
@@ -522,8 +458,8 @@ func (g *Gateway) recordGatewayToClientBatch(packetCount int, byteCount int, fir
|
||||
g.mu.Unlock()
|
||||
if next <= 5 {
|
||||
log.Printf(
|
||||
"vpn gateway gateway_to_client batch uploaded: vpn_connection_id=%s batch=%d packets=%d bytes=%d first=%s",
|
||||
g.VPNConnectionID,
|
||||
"vpn gateway gateway_to_client batch uploaded: tunnel_id=%s batch=%d packets=%d bytes=%d first=%s",
|
||||
g.tunnelID(),
|
||||
next,
|
||||
packetCount,
|
||||
byteCount,
|
||||
@@ -536,7 +472,7 @@ func (g *Gateway) recordTunWrite(packet []byte) {
|
||||
next := g.tunWritePackets.Add(1)
|
||||
g.tunWriteBytes.Add(uint64(len(packet)))
|
||||
if next <= 5 {
|
||||
log.Printf("vpn gateway packet written to tun: vpn_connection_id=%s packet=%d bytes=%d summary=%s", g.VPNConnectionID, next, len(packet), summarizePacket(packet))
|
||||
log.Printf("vpn gateway packet written to tun: tunnel_id=%s packet=%d bytes=%d summary=%s", g.tunnelID(), next, len(packet), summarizePacket(packet))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,7 +480,7 @@ func (g *Gateway) recordTunRead(packet []byte) {
|
||||
next := g.tunReadPackets.Add(1)
|
||||
g.tunReadBytes.Add(uint64(len(packet)))
|
||||
if next <= 5 {
|
||||
log.Printf("vpn gateway packet read from tun: vpn_connection_id=%s packet=%d bytes=%d summary=%s", g.VPNConnectionID, next, len(packet), summarizePacket(packet))
|
||||
log.Printf("vpn gateway packet read from tun: tunnel_id=%s packet=%d bytes=%d summary=%s", g.tunnelID(), next, len(packet), summarizePacket(packet))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user