github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/nfqdatapath/datapath_udp.go (about) 1 package nfqdatapath 2 3 // Go libraries 4 import ( 5 "errors" 6 "fmt" 7 "strconv" 8 "time" 9 10 "go.aporeto.io/enforcerd/trireme-lib/collector" 11 "go.aporeto.io/enforcerd/trireme-lib/controller/constants" 12 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/claimsheader" 13 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/connection" 14 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/counters" 15 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/packet" 16 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/pucontext" 17 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/tokens" 18 markconstants "go.aporeto.io/enforcerd/trireme-lib/utils/constants" 19 "go.uber.org/zap" 20 ) 21 22 const ( 23 // Default retransmit delay for first packet 24 retransmitDelay = 200 25 // rentrasmitRetries is the number of times we will retry 26 retransmitRetries = 3 27 // ACLCheckMultipler is the multiplie on delay that is used to attempt and fallbackto acls 28 ACLCheckMultipler = retransmitDelay * 12 29 ) 30 31 // DropReason is used to indicate the drop reason for a packet 32 type DropReason string 33 34 // DropReason is the reason a packet is dropped and fin packets are generated 35 const ( 36 InvalidUDPState DropReason = "invalidUDPState" 37 PolicyDrop DropReason = "policyDrop" 38 ) 39 40 var errHandshakePacket = errors.New("handshake packet") 41 var errDropQueuedPacket = errors.New("dropping queued packet") 42 43 func calculatedelay(retransmitDelay uint32, multiplier uint32) time.Duration { 44 return time.Duration(retransmitDelay * (multiplier + 1)) 45 } 46 47 // ProcessNetworkUDPPacket processes packets arriving from network and are destined to the application. 48 func (d *Datapath) ProcessNetworkUDPPacket(p *packet.Packet) (conn *connection.UDPConnection, err error) { 49 50 if d.PacketLogsEnabled() { 51 zap.L().Debug("Processing network packet ", 52 zap.String("flow", p.L4FlowHash()), 53 ) 54 defer zap.L().Debug("Finished Processing network packet ", 55 zap.String("flow", p.L4FlowHash()), 56 zap.Error(err), 57 ) 58 } 59 udpPacketType := p.GetUDPType() 60 61 switch udpPacketType { 62 case packet.UDPSynMask: 63 conn, err = d.netSynUDPRetrieveState(p) 64 if err != nil { 65 if d.PacketLogsEnabled() { 66 zap.L().Debug("Packet rejected", 67 zap.String("flow", p.L4FlowHash()), 68 zap.Error(err), 69 ) 70 } 71 return nil, err 72 } 73 case packet.UDPSynAckMask, packet.UDPPolicyRejectMask: 74 conn, err = d.netSynAckUDPRetrieveState(p) 75 if err != nil { 76 if d.PacketLogsEnabled() { 77 zap.L().Debug("Syn ack Packet Rejected/ignored", 78 zap.String("flow", p.L4FlowHash()), 79 ) 80 } 81 return nil, err 82 } 83 84 case packet.UDPFinAckMask: 85 if err := d.processUDPFinPacket(p); err != nil { 86 zap.L().Debug("unable to process udp fin ack", 87 zap.String("flowhash", p.L4FlowHash()), zap.Error(err)) 88 return nil, err 89 } 90 // drop control packets 91 return conn, fmt.Errorf("dropping udp fin ack control packet") 92 93 default: 94 // Process packets that don't have the control header. These are data packets. 95 conn, err = d.netUDPAckRetrieveState(p) 96 if err != nil { 97 // Retrieve the context from the packet information. 98 context, err := d.contextFromIP(false, p.Mark, p.DestPort(), packet.IPProtocolUDP) 99 if err != nil { 100 return nil, counters.CounterError(counters.ErrNonPUUDPTraffic, errNonPUUDPTraffic) 101 } 102 // Check if a network acl allows this traffic traffic coming from external network 103 _, packetPolicy, err := context.NetworkACLPolicy(p) 104 105 if err == nil && packetPolicy.Action.Accepted() { 106 context.Counters().IncrementCounter(counters.ErrSynAckToExtNetAccept) 107 if err = d.conntrack.UpdateApplicationFlowMark( 108 p.SourceAddress(), 109 p.DestinationAddress(), 110 p.IPProto(), 111 p.SourcePort(), 112 p.DestPort(), 113 markconstants.DefaultConnMark, 114 ); err != nil { 115 zap.L().Error("Failed to update conntrack table for UDP flow at transmitter", 116 zap.String("net-data-acl", p.L4FlowHash()), 117 zap.Error(err), 118 ) 119 120 } 121 return conn, nil 122 } 123 124 if err := d.sendUDPFinPacket(p); err != nil { 125 return nil, fmt.Errorf("net state not found, unable to send fin ack packets: %s", err) 126 } 127 if d.PacketLogsEnabled() { 128 zap.L().Debug("No connection found for the flow, Dropping it", 129 zap.String("flow", p.L4FlowHash()), 130 zap.Error(err), 131 ) 132 } 133 return nil, err 134 } 135 } 136 137 // We are processing only one connection at a time. 138 conn.Lock() 139 defer conn.Unlock() 140 141 p.Print(packet.PacketStageIncoming, d.PacketLogsEnabled()) 142 143 if d.service != nil { 144 if !d.service.PreProcessUDPNetPacket(p, conn.Context, conn) { 145 p.Print(packet.PacketFailureService, d.PacketLogsEnabled()) 146 return conn, conn.Context.Counters().CounterError(counters.ErrUDPNetPreProcessingFailed, errors.New("pre processing failed for network packet")) 147 } 148 } 149 150 // handle handshake packets and do not deliver to application. 151 action, claims, err := d.processNetUDPPacket(p, conn.Context, conn) 152 if err != nil && err != errHandshakePacket && err != errDropQueuedPacket { 153 zap.L().Debug("Rejecting packet because of policy decision", 154 zap.String("flow", p.L4FlowHash()), 155 zap.Error(err), 156 ) 157 return conn, fmt.Errorf("packet processing failed for network packet: %s", err) 158 } 159 160 // Process the packet by any external services. 161 if d.service != nil { 162 if !d.service.PostProcessUDPNetPacket(p, action, claims, conn.Context, conn) { 163 p.Print(packet.PacketFailureService, d.PacketLogsEnabled()) 164 return conn, conn.Context.Counters().CounterError(counters.ErrUDPNetPostProcessingFailed, errors.New("post service processing failed for network packet")) 165 } 166 } 167 168 // If reached the final state, drain the queue. 169 if conn.GetState() == connection.UDPClientSendAck { 170 conn.SetState(connection.UDPData) 171 for udpPacket := conn.ReadPacket(); udpPacket != nil; udpPacket = conn.ReadPacket() { 172 if d.service != nil { 173 // PostProcessServiceInterface 174 // We call it for all outgoing packets. 175 if !d.service.PostProcessUDPAppPacket(udpPacket, nil, conn.Context, conn) { 176 udpPacket.Print(packet.PacketFailureService, d.PacketLogsEnabled()) 177 zap.L().Error("Failed to encrypt queued packet") 178 } 179 } 180 181 err = d.ignoreFlow(udpPacket) 182 if err != nil { 183 zap.L().Error("Unable to ignore the flow", zap.Error(err)) 184 } 185 186 err = d.writeUDPSocket(udpPacket.GetBuffer(0), udpPacket) 187 if err != nil { 188 zap.L().Error("Unable to transmit Queued UDP packets", zap.Error(err)) 189 } 190 } 191 return conn, fmt.Errorf("Drop the packet") 192 } 193 194 if conn.GetState() != connection.UDPData { 195 // handshake packets are not to be delivered to application. 196 197 return conn, errHandshakePacket 198 199 } 200 201 return conn, nil 202 } 203 204 func (d *Datapath) netSynUDPRetrieveState(p *packet.Packet) (*connection.UDPConnection, error) { 205 206 // Retrieve the context from the packet information. 207 context, err := d.contextFromIP(false, p.Mark, p.DestPort(), packet.IPProtocolUDP) 208 if err != nil { 209 return nil, counters.CounterError(counters.ErrNonPUTraffic, errNonPUTraffic) 210 } 211 212 // Check if a connection already exists for this flow. This can happen 213 // in the case of retransmissions. If there is no connection, create 214 // a new one. 215 conn, cerr := d.udpNetOrigConnectionTracker.Get(p.L4FlowHash()) 216 if cerr != nil { 217 conn := connection.NewUDPConnection(context, d.udpSocketWriter) 218 conn.Secrets, conn.Auth.LocalDatapathPrivateKey, conn.Auth.LocalDatapathPublicKeyV1, conn.Auth.LocalDatapathPublicKeySignV1, conn.Auth.LocalDatapathPublicKeyV2, conn.Auth.LocalDatapathPublicKeySignV2 = context.GetSecrets() 219 return conn, nil 220 } 221 return conn.(*connection.UDPConnection), nil 222 } 223 224 func (d *Datapath) netSynAckUDPRetrieveState(p *packet.Packet) (*connection.UDPConnection, error) { 225 conn, err := d.udpSourcePortConnectionCache.GetReset(p.SourcePortHash(packet.PacketTypeNetwork), 0) 226 if err != nil { 227 return nil, counters.CounterError(counters.ErrUDPSynAckNoConnection, errors.New("No connection.Drop the syn ack packet")) 228 } 229 230 return conn.(*connection.UDPConnection), nil 231 } 232 233 func (d *Datapath) netUDPAckRetrieveState(p *packet.Packet) (*connection.UDPConnection, error) { 234 235 hash := p.L4FlowHash() 236 conn, err := d.udpNetReplyConnectionTracker.GetReset(hash, 0) 237 if err != nil { 238 conn, err = d.udpNetOrigConnectionTracker.GetReset(hash, 0) 239 if err != nil { 240 // This might be an existing udp connection. 241 // Send FinAck to reauthorize the connection. 242 243 return nil, fmt.Errorf("net state not found: %s", err) 244 } 245 } 246 return conn.(*connection.UDPConnection), nil 247 } 248 249 // processNetUDPPacket processes a network UDP packet and dispatches it to different methods based on the flags. 250 // This applies only to control packets. 251 func (d *Datapath) processNetUDPPacket(udpPacket *packet.Packet, context *pucontext.PUContext, conn *connection.UDPConnection) (action interface{}, claims *tokens.ConnectionClaims, err error) { 252 253 // Extra check, just in case the caller didn't provide a connection. 254 if conn == nil { 255 return nil, nil, fmt.Errorf("no connection provided") 256 } 257 258 udpPacketType := udpPacket.GetUDPType() 259 260 // Update connection state in the internal state machine tracker 261 switch udpPacketType { 262 case packet.UDPSynMask: 263 264 // Parse the packet for the identity information. 265 action, claims, err = d.processNetworkUDPSynPacket(context, conn, udpPacket) 266 if err != nil { 267 if err = d.sendUDPRstPacket(udpPacket, conn); err != nil { 268 zap.L().Error("Unable to send rst packet", zap.Error(err), zap.String("FlowHash", udpPacket.L4FlowHash())) 269 } 270 271 return nil, nil, err 272 } 273 // Send the return packet. 274 if err = d.sendUDPSynAckPacket(udpPacket, context, conn); err != nil { 275 return nil, nil, err 276 } 277 278 // Mark the state that we have transmitted a SynAck packet. 279 conn.SetState(connection.UDPReceiverSendSynAck) 280 return action, claims, errHandshakePacket 281 282 case packet.UDPAckMask: 283 // Retrieve the header and parse the signatures. 284 if err = d.processNetworkUDPAckPacket(udpPacket, context, conn); err != nil { 285 return nil, nil, err 286 } 287 288 // Set the connection to 289 conn.SetState(connection.UDPReceiverProcessedAck) 290 return nil, nil, errHandshakePacket 291 292 case packet.UDPSynAckMask: 293 // Process the synack header and claims of the other side. 294 action, claims, err = d.processNetworkUDPSynAckPacket(udpPacket, context, conn) 295 if err != nil { 296 return nil, nil, err 297 } 298 // Send back the acknowledgement. 299 err = d.sendUDPAckPacket(udpPacket, context, conn) 300 if err != nil { 301 return nil, nil, err 302 } 303 304 conn.SetState(connection.UDPClientSendAck) 305 306 return action, claims, errHandshakePacket 307 case packet.UDPPolicyRejectMask: 308 309 if err := d.processUDPPolicyRstPacket(udpPacket, context, conn); err != nil { 310 zap.L().Debug("unable to process udp policy rst", 311 zap.String("flowhash", udpPacket.L4FlowHash()), zap.Error(err)) 312 return conn, nil, err 313 } 314 return conn, nil, fmt.Errorf("dropping udp rst control packet") 315 default: 316 state := conn.GetState() 317 if state == connection.UDPReceiverProcessedAck || state == connection.UDPClientSendAck || state == connection.UDPData { 318 conn.SetState(connection.UDPData) 319 return nil, nil, nil 320 } 321 return nil, nil, fmt.Errorf("invalid packet at state: %d", state) 322 } 323 } 324 325 // ProcessApplicationUDPPacket processes packets arriving from an application and are destined to the network 326 func (d *Datapath) ProcessApplicationUDPPacket(p *packet.Packet) (conn *connection.UDPConnection, err error) { 327 328 if d.PacketLogsEnabled() { 329 zap.L().Debug("Processing application UDP packet ", 330 zap.String("flow", p.L4FlowHash()), 331 ) 332 defer zap.L().Debug("Finished Processing UDP application packet ", 333 zap.String("flow", p.L4FlowHash()), 334 zap.Error(err), 335 ) 336 } 337 // First retrieve the connection state. 338 conn, err = d.appUDPRetrieveState(p) 339 if err != nil { 340 zap.L().Debug("Connection not found", zap.Error(err)) 341 return nil, counters.CounterError(counters.ErrNonPUTraffic, errNonPUTraffic) 342 } 343 344 // We are processing only one packet from a given connection at a time. 345 conn.Lock() 346 defer conn.Unlock() 347 348 // do some pre processing. 349 if d.service != nil { 350 // PreProcessServiceInterface 351 if !d.service.PreProcessUDPAppPacket(p, conn.Context, conn, packet.UDPSynMask) { 352 p.Print(packet.PacketFailureService, d.PacketLogsEnabled()) 353 return nil, conn.Context.Counters().CounterError(counters.ErrUDPAppPreProcessingFailed, errors.New("pre service processing failed for UDP application packet")) 354 } 355 } 356 357 triggerControlProtocol := false 358 switch conn.GetState() { 359 case connection.UDPStart: 360 // Queue the packet. We will send it after we authorize the session. 361 if err = conn.QueuePackets(p); err != nil { 362 // unable to queue packets, perhaps queue is full. if start 363 // machine is still in start state, we can start authorisation 364 // again. A drop counter is incremented. 365 zap.L().Debug("udp queue full for connection", zap.String("flow", p.L4FlowHash())) 366 } 367 368 // Set the state indicating that we send out a Syn packet 369 conn.SetState(connection.UDPClientSendSyn) 370 // Drop the packet. We stored it in the queue. 371 triggerControlProtocol = true 372 373 case connection.UDPReceiverProcessedAck, connection.UDPClientSendAck, connection.UDPData: 374 conn.SetState(connection.UDPData) 375 376 default: 377 if err = conn.QueuePackets(p); err != nil { 378 return conn, conn.Context.Counters().CounterError(counters.ErrUDPDropQueueFull, fmt.Errorf("Unable to queue packets:%s", err)) 379 } 380 return conn, conn.Context.Counters().CounterError(counters.ErrUDPDropInNfQueue, errDropQueuedPacket) 381 } 382 383 if d.service != nil { 384 // PostProcessServiceInterface 385 if !d.service.PostProcessUDPAppPacket(p, nil, conn.Context, conn) { 386 p.Print(packet.PacketFailureService, d.PacketLogsEnabled()) 387 return conn, conn.Context.Counters().CounterError(counters.ErrUDPAppPostProcessingFailed, errors.New("Encryption failed for application packet")) 388 } 389 } 390 391 if triggerControlProtocol { 392 err = d.triggerNegotiation(p, conn.Context, conn) 393 if err != nil { 394 return conn, conn.Context.Counters().CounterError(counters.ErrUDPDropInNfQueue, errDropQueuedPacket) 395 } 396 return conn, errDropQueuedPacket 397 } 398 399 return conn, nil 400 } 401 402 func (d *Datapath) appUDPRetrieveState(p *packet.Packet) (*connection.UDPConnection, error) { 403 404 hash := p.L4FlowHash() 405 406 if conn, err := d.udpAppReplyConnectionTracker.GetReset(hash, 0); err == nil { 407 return conn.(*connection.UDPConnection), nil 408 } 409 410 if conn, err := d.udpAppOrigConnectionTracker.GetReset(hash, 0); err == nil { 411 return conn.(*connection.UDPConnection), nil 412 } 413 414 context, err := d.contextFromIP(true, p.Mark, p.SourcePort(), packet.IPProtocolUDP) 415 if err != nil { 416 return nil, counters.CounterError(counters.ErrNonPUTraffic, errors.New("No context in app processing")) 417 } 418 419 return connection.NewUDPConnection(context, d.udpSocketWriter), nil 420 } 421 422 // processApplicationUDPSynPacket processes a single Syn Packet 423 func (d *Datapath) triggerNegotiation(udpPacket *packet.Packet, context *pucontext.PUContext, conn *connection.UDPConnection) (err error) { 424 newPacket, err := d.clonePacketHeaders(udpPacket) 425 if err != nil { 426 return fmt.Errorf("Unable to clone packet: %s", err) 427 } 428 var udpData []byte 429 conn.Secrets, conn.Auth.LocalDatapathPrivateKey, udpData = context.GetSynToken(nil, conn.Auth.Nonce, nil) 430 udpOptions := packet.CreateUDPAuthMarker(packet.UDPSynMask, uint16(len(udpData))) 431 // Attach the UDP data and token 432 newPacket.UDPTokenAttach(udpOptions, udpData) 433 if udpPacket.PlatformMetadata != nil { 434 newPacket.PlatformMetadata = udpPacket.PlatformMetadata.Clone() 435 } 436 statusChannel := make(chan bool) 437 438 go func() { 439 // We started a handhsake drop reverse packets automatically 440 // Assert connmark before relaseing packets if response is receied 441 if err = d.conntrack.UpdateApplicationFlowMark( 442 udpPacket.SourceAddress(), 443 udpPacket.DestinationAddress(), 444 udpPacket.IPProto(), 445 udpPacket.SourcePort(), 446 udpPacket.DestPort(), 447 markconstants.HandshakeConnmark, 448 ); err != nil { 449 zap.L().Error("Failed to update conntrack table for UDP flow at transmitter", 450 zap.String("app-conn", udpPacket.L4FlowHash()), 451 zap.String("state", fmt.Sprintf("%d", conn.GetState())), 452 zap.Error(err), 453 ) 454 455 } 456 loop: 457 for { 458 select { 459 case <-statusChannel: 460 break loop 461 case <-time.After(ACLCheckMultipler * time.Millisecond): 462 return 463 } 464 } 465 conn.Lock() 466 defer conn.Unlock() 467 if conn.GetState() == connection.UDPStart { 468 // We did not receive any response from the remote. 469 // It is most likely an external network lets evaluate acls at this point to see if we are allowed to talk to this ip 470 report, pkt, perr := context.ApplicationACLPolicyFromAddr(udpPacket.DestinationAddress(), udpPacket.DestPort(), udpPacket.IPProto()) 471 if perr != nil && pkt.Action.Rejected() { 472 d.reportExternalServiceFlow(context, report, pkt, true, udpPacket) 473 return 474 } 475 <-time.After(50 * time.Millisecond) //Arbitrary number to ensure last handshake packet is dropped in our tables 476 // Assert connmark before relaseing packets if response is receied 477 if err = d.conntrack.UpdateApplicationFlowMark( 478 udpPacket.SourceAddress(), 479 udpPacket.DestinationAddress(), 480 udpPacket.IPProto(), 481 udpPacket.SourcePort(), 482 udpPacket.DestPort(), 483 markconstants.DefaultExternalConnMark, 484 ); err != nil { 485 zap.L().Error("Failed to update conntrack table for UDP flow at transmitter", 486 zap.String("app-conn", udpPacket.L4FlowHash()), 487 zap.String("state", fmt.Sprintf("%d", conn.GetState())), 488 zap.Error(err), 489 ) 490 491 } 492 for udpPacket := conn.ReadPacket(); udpPacket != nil; udpPacket = conn.ReadPacket() { 493 if d.service != nil { 494 // PostProcessServiceInterface 495 // We call it for all outgoing packets. 496 if !d.service.PostProcessUDPAppPacket(udpPacket, nil, conn.Context, conn) { 497 udpPacket.Print(packet.PacketFailureService, d.PacketLogsEnabled()) 498 zap.L().Error("Failed to encrypt queued packet") 499 } 500 } 501 502 err = d.ignoreFlow(udpPacket) 503 if err != nil { 504 zap.L().Error("Unable to ignore the flow", zap.Error(err)) 505 } 506 507 err = d.writeUDPSocket(udpPacket.GetBuffer(0), udpPacket) 508 if err != nil { 509 zap.L().Error("Unable to transmit Queued UDP packets", zap.Error(err)) 510 } 511 } 512 conn.SetState(connection.UDPData) 513 d.reportExternalServiceFlow(context, report, pkt, true, udpPacket) 514 return 515 } 516 517 }() 518 519 // send packet 520 err = d.writeWithRetransmit(newPacket, conn, conn.SynChannel(), statusChannel) 521 if err != nil { 522 zap.L().Error("Unable to send syn token on raw socket", zap.Error(err), zap.Time("time", time.Now())) 523 return fmt.Errorf("unable to transmit syn packet") 524 } 525 526 // Populate the caches to track the connection 527 hash := udpPacket.L4FlowHash() 528 d.udpAppOrigConnectionTracker.AddOrUpdate(hash, conn) 529 d.udpSourcePortConnectionCache.AddOrUpdate(newPacket.SourcePortHash(packet.PacketTypeApplication), conn) 530 531 return nil 532 533 } 534 535 func (d *Datapath) writeWithRetransmit(udpPacket *packet.Packet, conn *connection.UDPConnection, stop chan bool, statusChan chan bool) error { 536 buffer := udpPacket.GetBuffer(0) 537 localBuffer := make([]byte, len(buffer)) 538 copy(localBuffer, buffer) 539 zap.L().Debug("TRYINGT to send control packet", zap.String("FlowHash", udpPacket.L4FlowHash())) 540 if err := d.writeUDPSocket(localBuffer, udpPacket); err != nil { 541 zap.L().Error("Failed to write control packet to socket", zap.Error(err), zap.String("FlowHash", udpPacket.L4FlowHash())) 542 return err 543 } 544 545 go func() { 546 547 for retries := 0; retries < retransmitRetries; retries++ { 548 delay := time.Millisecond * time.Duration((retransmitDelay * (retries + 1))) 549 select { 550 case <-stop: 551 return 552 case <-time.After(delay): 553 if err := d.writeUDPSocket(localBuffer, udpPacket); err != nil { 554 zap.L().Error("Failed to write control packet to socket", zap.Error(err), zap.String("FlowHash", udpPacket.L4FlowHash())) 555 } 556 } 557 } 558 // We did not get a synack maybe this dest is an external network 559 if statusChan != nil { 560 zap.L().Debug("Timedout should start acl") 561 statusChan <- true 562 } 563 // retransmits did not succeed. Reset the state machine so that 564 // next packet can try again. 565 conn.SetState(connection.UDPStart) 566 567 }() 568 return nil 569 } 570 571 func (d *Datapath) clonePacketHeaders(p *packet.Packet) (*packet.Packet, error) { 572 // copy the ip and udp headers. 573 newSize := uint16(p.IPHeaderLen() + packet.UDPDataPos) 574 newPacket := make([]byte, newSize) 575 p.FixupIPHdrOnDataModify(p.IPTotalLen(), newSize) 576 577 origBuffer := p.GetBuffer(0) 578 _ = copy(newPacket, origBuffer[:newSize]) 579 580 return packet.New(packet.PacketTypeApplication, newPacket, p.Mark, true) 581 } 582 583 // sendUDPSynAckPacket processes a UDP SynAck packet 584 func (d *Datapath) sendUDPSynAckPacket(udpPacket *packet.Packet, context *pucontext.PUContext, conn *connection.UDPConnection) (err error) { 585 586 claimsHeader := claimsheader.NewClaimsHeader() 587 claims := &tokens.ConnectionClaims{ 588 CT: context.CompressedTags(), 589 LCL: conn.Auth.Nonce[:], 590 RMT: conn.Auth.RemoteNonce, 591 DEKV1: conn.Auth.LocalDatapathPublicKeyV1, 592 SDEKV1: conn.Auth.LocalDatapathPublicKeySignV1, 593 DEKV2: conn.Auth.LocalDatapathPublicKeyV2, 594 SDEKV2: conn.Auth.LocalDatapathPublicKeySignV2, 595 ID: context.ManagementID(), 596 RemoteID: conn.Auth.RemoteContextID, 597 } 598 599 var udpData []byte 600 601 udpData, err = d.tokenAccessor.CreateSynAckPacketToken(conn.Auth.Proto314, claims, conn.EncodedBuf[:], conn.Auth.Nonce[:], claimsHeader, conn.Secrets, conn.Auth.SecretKey) 602 if err != nil { 603 return counters.CounterError(appUDPSynAckCounterFromError(err), err) 604 } 605 606 // Create UDP Option 607 608 udpPacket.CreateReverseFlowPacket() 609 610 // This for Windows and isn't necessary, but helps when driver is logging 611 err = d.reverseFlow(udpPacket) 612 if err != nil { 613 return counters.CounterError(appUDPSynAckCounterFromError(err), err) 614 } 615 // Create UDP Option 616 udpOptions := packet.CreateUDPAuthMarker(packet.UDPSynAckMask, uint16(len(udpData))) 617 // Attach the UDP data and token 618 udpPacket.UDPTokenAttach(udpOptions, udpData) 619 620 // If we have already a backgroun re-transmit session, stop it at this point. We will 621 // start from the beginning. 622 if conn.GetState() == connection.UDPReceiverSendSynAck { 623 conn.SynAckStop() 624 } 625 626 // Only start the retransmission timer once. Not on every packet. 627 if err := d.writeWithRetransmit(udpPacket, conn, conn.SynAckChannel(), nil); err != nil { 628 zap.L().Debug("Unable to send synack token on raw socket", zap.Error(err)) 629 return err 630 } 631 632 return nil 633 } 634 635 func (d *Datapath) sendUDPAckPacket(udpPacket *packet.Packet, context *pucontext.PUContext, conn *connection.UDPConnection) (err error) { 636 // This for Windows and isn't necessary, but helps when driver is logging 637 err = d.reverseFlow(udpPacket) 638 if err != nil { 639 return counters.CounterError(appUDPAckCounterFromError(err), err) 640 } 641 642 udpPacket.CreateReverseFlowPacket() 643 644 claims := &tokens.ConnectionClaims{ 645 ID: context.ManagementID(), 646 RMT: conn.Auth.RemoteNonce, 647 RemoteID: conn.Auth.RemoteContextID, 648 } 649 650 udpData, err := d.tokenAccessor.CreateAckPacketToken(conn.Auth.Proto314, conn.Auth.SecretKey, claims, conn.EncodedBuf[:]) 651 if err != nil { 652 return counters.CounterError(appUDPAckCounterFromError(err), err) 653 } 654 // Create UDP Option 655 udpOptions := packet.CreateUDPAuthMarker(packet.UDPAckMask, uint16(len(udpData))) 656 // Attach the UDP data and token 657 udpPacket.UDPTokenAttach(udpOptions, udpData) 658 659 // send packet 660 err = d.writeUDPSocket(udpPacket.GetBuffer(0), udpPacket) 661 if err != nil { 662 return err 663 } 664 // We reached final state drain the queue here 665 666 <-time.After(40 * time.Millisecond) //Arbitrary number give receiver chance to plumb conntrack 667 for udpPacket := conn.ReadPacket(); udpPacket != nil; udpPacket = conn.ReadPacket() { 668 if d.service != nil { 669 // PostProcessServiceInterface 670 // We call it for all outgoing packets. 671 if !d.service.PostProcessUDPAppPacket(udpPacket, nil, conn.Context, conn) { 672 udpPacket.Print(packet.PacketFailureService, d.PacketLogsEnabled()) 673 zap.L().Error("Failed to encrypt queued packet") 674 } 675 } 676 677 err = d.ignoreFlow(udpPacket) 678 if err != nil { 679 zap.L().Error("Unable to ignore the flow", zap.Error(err)) 680 } 681 682 err = d.writeUDPSocket(udpPacket.GetBuffer(0), udpPacket) 683 if err != nil { 684 zap.L().Error("Unable to transmit Queued UDP packets", zap.Error(err)) 685 } 686 } 687 688 // When server and client are the same machine, we can't ignore the 689 // flow until the server side receives the Ack packet 690 if !udpPacket.SourceAddress().Equal(udpPacket.DestinationAddress()) { 691 if err := d.ignoreFlow(udpPacket); err != nil { 692 zap.L().Error("Failed to ignore flow", zap.Error(err)) 693 } 694 } 695 if err = d.conntrack.UpdateApplicationFlowMark( 696 udpPacket.SourceAddress(), 697 udpPacket.DestinationAddress(), 698 udpPacket.IPProto(), 699 udpPacket.SourcePort(), 700 udpPacket.DestPort(), 701 markconstants.DefaultConnMark, 702 ); err != nil { 703 zap.L().Error("Failed to update conntrack table for UDP flow at transmitter", 704 zap.String("app-conn", udpPacket.L4FlowHash()), 705 zap.String("state", fmt.Sprintf("%d", conn.GetState())), 706 zap.Error(err), 707 ) 708 return err 709 } 710 711 conn.SetState(connection.UDPData) 712 zap.L().Debug("Clearing fin packet entry in cache", zap.String("flowhash", udpPacket.L4FlowHash())) 713 if err := d.udpFinPacketTracker.Remove(udpPacket.L4FlowHash()); err != nil { 714 zap.L().Debug("Unable to remove entry from udp finack cache") 715 } 716 return nil 717 } 718 719 // processNetworkUDPSynPacket processes a syn packet arriving from the network 720 func (d *Datapath) processNetworkUDPSynPacket(context *pucontext.PUContext, conn *connection.UDPConnection, udpPacket *packet.Packet) (action interface{}, claims *tokens.ConnectionClaims, err error) { 721 722 rejected := false 723 networkReport, pkt, perr := context.NetworkACLPolicy(udpPacket) 724 if perr == nil { 725 rejected = pkt.Action.Rejected() 726 if rejected { 727 perr = fmt.Errorf("rejected by ACL policy %s", pkt.PolicyID) 728 } 729 } else { 730 // We got an error, but ensure it isn't the catch all policy 731 if !(pkt != nil && pkt.Action.Rejected() && pkt.PolicyID == "default") { 732 rejected = true 733 } 734 } 735 736 if rejected { 737 d.reportExternalServiceFlow(context, networkReport, pkt, false, udpPacket) 738 return nil, nil, context.Counters().CounterError(counters.ErrUDPSynDroppedPolicy, fmt.Errorf("packet had identity: incoming connection dropped:due to reject acl %s", perr)) 739 } 740 claims = &conn.Auth.ConnectionClaims 741 secretKey, _, controller, remoteNonce, remoteContextID, proto314, err := d.tokenAccessor.ParsePacketToken(conn.Auth.LocalDatapathPrivateKey, udpPacket.ReadUDPToken(), conn.Secrets, claims, false) 742 743 if err != nil { 744 d.reportUDPRejectedFlow(udpPacket, conn, collector.DefaultEndPoint, context.ManagementID(), context, collector.InvalidToken, nil, nil, false) 745 return nil, nil, conn.Context.Counters().CounterError(netUDPSynCounterFromError(err), fmt.Errorf("UDP Syn packet dropped because of invalid token: %s", err)) 746 } 747 748 if controller != nil && !controller.SameController { 749 conn.SourceController = controller.Controller 750 } 751 752 // Why is this required. Take a look. 753 //txLabel, _ := claims.T.Get(enforcerconstants.TransmitterLabel) 754 755 // Add the port as a label with an @ prefix. These labels are invalid otherwise 756 // If all policies are restricted by port numbers this will allow port-specific policies 757 tags := claims.T.Copy() 758 tags.AppendKeyValue(constants.PortNumberLabelString, fmt.Sprintf("%s/%s", constants.UDPProtoString, strconv.Itoa(int(udpPacket.DestPort())))) 759 760 // Add the controller to the claims 761 if controller != nil && len(controller.Controller) > 0 { 762 tags.AppendKeyValue(constants.ControllerLabelString, controller.Controller) 763 } 764 765 report, pkt := context.SearchRcvRules(tags) 766 if pkt.Action.Rejected() { 767 d.reportUDPRejectedFlow(udpPacket, conn, remoteContextID, context.ManagementID(), context, collector.PolicyDrop, report, pkt, false) 768 return nil, nil, conn.Context.Counters().CounterError(counters.ErrUDPSynDroppedPolicy, fmt.Errorf("connection rejected because of policy: %s", claims.T.String())) 769 } 770 771 hash := udpPacket.L4FlowHash() 772 773 // conntrack 774 d.udpNetOrigConnectionTracker.AddOrUpdate(hash, conn) 775 d.udpAppReplyConnectionTracker.AddOrUpdate(udpPacket.L4ReverseFlowHash(), conn) 776 777 conn.Auth.SecretKey = secretKey 778 conn.Auth.RemoteNonce = remoteNonce 779 conn.Auth.RemoteContextID = remoteContextID 780 conn.Auth.Proto314 = proto314 781 782 // Record actions 783 conn.ReportFlowPolicy = report 784 conn.PacketFlowPolicy = pkt 785 786 return pkt, claims, nil 787 } 788 789 func (d *Datapath) processNetworkUDPSynAckPacket(udpPacket *packet.Packet, context *pucontext.PUContext, conn *connection.UDPConnection) (action interface{}, claims *tokens.ConnectionClaims, err error) { 790 conn.SynStop() 791 claims = &conn.Auth.ConnectionClaims 792 secretKey, _, controller, remoteNonce, remoteContextID, proto314, err := d.tokenAccessor.ParsePacketToken(conn.Auth.LocalDatapathPrivateKey, udpPacket.ReadUDPToken(), conn.Secrets, claims, true) 793 if err != nil { 794 d.reportUDPRejectedFlow(udpPacket, conn, context.ManagementID(), collector.DefaultEndPoint, context, collector.MissingToken, nil, nil, true) 795 return nil, nil, conn.Context.Counters().CounterError(netUDPSynAckCounterFromError(err), errors.New("SynAck packet dropped because of bad claims")) 796 } 797 798 if controller != nil && !controller.SameController { 799 conn.DestinationController = controller.Controller 800 } 801 // Add the port as a label with an @ prefix. These labels are invalid otherwise 802 // If all policies are restricted by port numbers this will allow port-specific policies 803 tags := claims.T.Copy() 804 tags.AppendKeyValue(constants.PortNumberLabelString, fmt.Sprintf("%s/%s", constants.UDPProtoString, strconv.Itoa(int(udpPacket.SourcePort())))) 805 806 // Add the controller to the claims 807 if controller != nil && len(controller.Controller) > 0 { 808 tags.AppendKeyValue(constants.ControllerLabelString, controller.Controller) 809 } 810 811 report, pkt := context.SearchTxtRules(tags, !d.mutualAuthorization) 812 if pkt.Action.Rejected() { 813 d.reportUDPRejectedFlow(udpPacket, conn, remoteContextID, context.ManagementID(), context, collector.PolicyDrop, report, pkt, true) 814 return nil, nil, conn.Context.Counters().CounterError(counters.ErrUDPSynAckPolicy, fmt.Errorf("dropping because of reject rule on transmitter: %s", claims.T.String())) 815 } 816 817 // conntrack 818 d.udpNetReplyConnectionTracker.AddOrUpdate(udpPacket.L4FlowHash(), conn) 819 conn.Auth.SecretKey = secretKey 820 conn.Auth.RemoteNonce = remoteNonce 821 conn.Auth.RemoteContextID = remoteContextID 822 conn.Auth.Proto314 = proto314 823 824 return pkt, claims, nil 825 } 826 827 func (d *Datapath) processNetworkUDPAckPacket(udpPacket *packet.Packet, context *pucontext.PUContext, conn *connection.UDPConnection) (err error) { 828 conn.SynAckStop() 829 if err = d.tokenAccessor.ParseAckToken(conn.Auth.Proto314, conn.Auth.SecretKey, conn.Auth.Nonce[:], udpPacket.ReadUDPToken(), &conn.Auth.ConnectionClaims); err != nil { 830 d.reportUDPRejectedFlow(udpPacket, conn, conn.Auth.RemoteContextID, context.ManagementID(), context, collector.InvalidToken, conn.ReportFlowPolicy, conn.PacketFlowPolicy, false) 831 return conn.Context.Counters().CounterError(netUDPAckCounterFromError(err), fmt.Errorf("ack packet dropped because signature validation failed: %s", err)) 832 } 833 834 // For Windows, we allow the flow 835 if err := d.setFlowState(udpPacket, true); err != nil { 836 zap.L().Error("Failed to ignore flow", zap.Error(err)) 837 } 838 839 // Plumb connmark rule here. 840 if err := d.conntrack.UpdateNetworkFlowMark( 841 udpPacket.SourceAddress(), 842 udpPacket.DestinationAddress(), 843 udpPacket.IPProto(), 844 udpPacket.SourcePort(), 845 udpPacket.DestPort(), 846 markconstants.DefaultConnMark, 847 ); err != nil { 848 zap.L().Error("Failed to update conntrack table after ack packet") 849 } 850 851 d.reportUDPAcceptedFlow(udpPacket, conn, conn.Auth.RemoteContextID, context.ManagementID(), context, conn.ReportFlowPolicy, conn.PacketFlowPolicy, false) 852 853 conn.Context.Counters().IncrementCounter(counters.ErrUDPConnectionsProcessed) 854 return nil 855 } 856 857 // sendUDPFinPacket sends a Fin packet to Peer. 858 func (d *Datapath) sendUDPFinPacket(udpPacket *packet.Packet) (err error) { 859 // Create UDP Option 860 udpOptions := packet.CreateUDPAuthMarker(packet.UDPFinAckMask, 0) 861 udpPacket.CreateReverseFlowPacket() 862 863 err = d.reverseFlow(udpPacket) 864 if err != nil { 865 866 return counters.CounterError(counters.ErrUDPDropFin, err) 867 } 868 // Attach the UDP data and token 869 udpPacket.UDPTokenAttach(udpOptions, []byte{}) 870 871 // no need for retransmits here. 872 err = d.writeUDPSocket(udpPacket.GetBuffer(0), udpPacket) 873 if err != nil { 874 zap.L().Debug("Unable to send fin packet on raw socket:", zap.Error(err)) 875 return counters.CounterError(counters.ErrUDPDropFin, fmt.Errorf("Unable to send fin packet on raw socket: %s", err.Error())) 876 } 877 878 return nil 879 } 880 881 // sendUDPRstPacket sends a rst packet to Peer. 882 func (d *Datapath) sendUDPRstPacket(udpPacket *packet.Packet, conn *connection.UDPConnection) (err error) { 883 // Create UDP Option 884 udpOptions := packet.CreateUDPAuthMarker(packet.UDPPolicyRejectMask, 0) 885 udpPacket.CreateReverseFlowPacket() 886 // TODO ::: Have a signed payload this packets will force remote end to process acls 887 // So we have to be sure someone we trust send this 888 err = d.reverseFlow(udpPacket) 889 if err != nil { 890 return conn.Context.Counters().CounterError(counters.ErrUDPDropRst, err) 891 } 892 893 // Attach the UDP data and token 894 udpPacket.UDPTokenAttach(udpOptions, []byte{}) 895 896 // For Windows, this mark udpPacket packet so that when writeUDPSocket is called, 897 // it will send the packet but will drop additional packets for this flow. 898 if err := d.dropFlow(udpPacket); err != nil { 899 zap.L().Error("Failed to drop flow", zap.Error(err)) 900 } 901 902 // no need for retransmits here. 903 err = d.writeUDPSocket(udpPacket.GetBuffer(0), udpPacket) 904 if err != nil { 905 zap.L().Debug("Unable to send fin packet on raw socket", zap.Error(err)) 906 return conn.Context.Counters().CounterError(counters.ErrUDPDropRst, fmt.Errorf("Unable to send rst packet on raw socket: %s", err.Error())) 907 } 908 909 // conn.SynStop() 910 // conn.SynAckStop() 911 // Plumb connmark rule here. drop packet on this flow. Till we see a acceptable handshake packet again 912 if err := d.conntrack.UpdateNetworkFlowMark( 913 udpPacket.SourceAddress(), 914 udpPacket.DestinationAddress(), 915 udpPacket.IPProto(), 916 udpPacket.SourcePort(), 917 udpPacket.DestPort(), 918 markconstants.DropConnmark, 919 ); err != nil { 920 zap.L().Error("Failed to update conntrack table after ack packet") 921 } 922 return nil 923 } 924 925 func (d *Datapath) processUDPPolicyRstPacket(udpPacket *packet.Packet, context *pucontext.PUContext, conn *connection.UDPConnection) (err error) { // nolint 926 conn.SetState(connection.UDPRST) 927 conn.SynStop() 928 conn.SynAckStop() 929 if err := d.udpAppOrigConnectionTracker.Remove(udpPacket.L4ReverseFlowHash()); err != nil { 930 zap.L().Debug("Failed to clean cache udpappOrigConnectionTracker", zap.Error(err)) 931 } 932 if err := d.udpSourcePortConnectionCache.Remove(udpPacket.SourcePortHash(packet.PacketTypeNetwork)); err != nil { 933 zap.L().Debug("Failed to clean cache udpsourcePortConnectionCache", zap.Error(err)) 934 } 935 if err := d.setFlowState(udpPacket, false); err != nil { 936 zap.L().Error("Failed to drop flow", zap.Error(err)) 937 } 938 if err := d.conntrack.UpdateNetworkFlowMark( 939 udpPacket.SourceAddress(), 940 udpPacket.DestinationAddress(), 941 udpPacket.IPProto(), 942 udpPacket.SourcePort(), 943 udpPacket.DestPort(), 944 markconstants.DropConnmark, 945 ); err != nil { 946 zap.L().Error("Failed to update conntrack table after ack packet") 947 } 948 return nil 949 } 950 951 // Update the udp fin cache and delete the connmark. 952 func (d *Datapath) processUDPFinPacket(udpPacket *packet.Packet) (err error) { // nolint 953 954 // add it to the udp fin cache. If we have already received the fin packet 955 // for this flow. There is no need to change the connmark label again. 956 if d.udpFinPacketTracker.AddOrUpdate(udpPacket.L4ReverseFlowHash(), true) { 957 return nil 958 } 959 960 // clear cache entries. 961 if err := d.udpAppOrigConnectionTracker.Remove(udpPacket.L4ReverseFlowHash()); err != nil { 962 zap.L().Debug("Failed to clean cache udpappOrigConnectionTracker", zap.Error(err)) 963 } 964 if err := d.udpSourcePortConnectionCache.Remove(udpPacket.SourcePortHash(packet.PacketTypeNetwork)); err != nil { 965 zap.L().Debug("Failed to clean cache udpsourcePortConnectionCache", zap.Error(err)) 966 } 967 if err := d.setFlowState(udpPacket, false); err != nil { 968 zap.L().Error("Failed to drop flow", zap.Error(err)) 969 } 970 if err = d.conntrack.UpdateNetworkFlowMark( 971 udpPacket.SourceAddress(), 972 udpPacket.DestinationAddress(), 973 udpPacket.IPProto(), 974 udpPacket.SourcePort(), 975 udpPacket.DestPort(), 976 markconstants.DeleteConnmark, 977 ); err != nil { 978 zap.L().Error("Failed to update conntrack table for flow to terminate connection", 979 zap.String("app-conn", udpPacket.L4FlowHash()), 980 zap.Error(err), 981 ) 982 } 983 984 return nil 985 } 986 987 // note: for platforms that need it (Windows), please ensure that udpPacket.PlatformMetadata is set. 988 // thus, for any Packets created outside of the driver packet callback, the originating metadata must be 989 // propagated to the udpPacket argument before this call. 990 func (d *Datapath) writeUDPSocket(buf []byte, udpPacket *packet.Packet) error { 991 return d.udpSocketWriter.WriteSocket(buf, udpPacket.IPversion(), udpPacket.PlatformMetadata) 992 }