1
1
package handler
2
2
3
3
import (
4
+ "bytes"
5
+ "crypto/sha1"
4
6
"encoding/binary"
5
7
"fmt"
6
8
"math/big"
7
9
"net"
8
10
11
+ "github.com/pkg/errors"
9
12
"github.com/sirupsen/logrus"
10
13
"golang.org/x/sys/unix"
11
14
@@ -50,13 +53,17 @@ const (
50
53
51
54
func HandleIKESAINIT (
52
55
udpConn * net.UDPConn ,
53
- n3iwfAddr , ueAddr * net.UDPAddr ,
56
+ ueAddr , n3iwfAddr * net.UDPAddr ,
54
57
message * ike_message.IKEMessage ,
55
58
) {
56
59
ikeLog .Infoln ("Handle IKESA INIT" )
57
60
58
61
var sharedKeyExchangeData []byte
59
62
var remoteNonce []byte
63
+ var notifications []* ike_message.Notification
64
+ // For NAT-T
65
+ var ueIsBehindNAT , n3iwfIsBehindNAT bool
66
+ var err error
60
67
61
68
for _ , ikePayload := range message .Payloads {
62
69
switch ikePayload .Type () {
@@ -78,6 +85,18 @@ func HandleIKESAINIT(
78
85
Bytes ()
79
86
case ike_message .TypeNiNr :
80
87
remoteNonce = ikePayload .(* ike_message.Nonce ).NonceData
88
+ case ike_message .TypeN :
89
+ notifications = append (notifications , ikePayload .(* ike_message.Notification ))
90
+ }
91
+ }
92
+
93
+ if len (notifications ) != 0 {
94
+ ueIsBehindNAT , n3iwfIsBehindNAT , err = HandleNATDetect (
95
+ message .InitiatorSPI , message .ResponderSPI ,
96
+ notifications , ueAddr , n3iwfAddr )
97
+ if err != nil {
98
+ ikeLog .Errorf ("Handle IKE_SA_INIT: %v" , err )
99
+ return
81
100
}
82
101
}
83
102
@@ -95,9 +114,11 @@ func HandleIKESAINIT(
95
114
ConcatenatedNonce : append (n3ueSelf .LocalNonce , remoteNonce ... ),
96
115
ResponderSignedOctets : append (n3ueSelf .N3IWFUe .N3IWFIKESecurityAssociation .
97
116
ResponderSignedOctets , remoteNonce ... ),
117
+ UEIsBehindNAT : ueIsBehindNAT ,
118
+ N3IWFIsBehindNAT : n3iwfIsBehindNAT ,
98
119
}
99
120
100
- err : = ikeSecurityAssociation .IKESAKey .GenerateKeyForIKESA (ikeSecurityAssociation .ConcatenatedNonce ,
121
+ err = ikeSecurityAssociation .IKESAKey .GenerateKeyForIKESA (ikeSecurityAssociation .ConcatenatedNonce ,
101
122
sharedKeyExchangeData , ikeSecurityAssociation .LocalSPI , ikeSecurityAssociation .RemoteSPI )
102
123
if err != nil {
103
124
ikeLog .Errorf ("Generate key for IKE SA failed: %+v" , err )
@@ -111,7 +132,7 @@ func HandleIKESAINIT(
111
132
112
133
func HandleIKEAUTH (
113
134
udpConn * net.UDPConn ,
114
- n3iwfAddr , ueAddr * net.UDPAddr ,
135
+ ueAddr , n3iwfAddr * net.UDPAddr ,
115
136
message * ike_message.IKEMessage ,
116
137
) {
117
138
ikeLog .Infoln ("Handle IKE AUTH" )
@@ -581,6 +602,13 @@ func HandleIKEAUTH(
581
602
childSecurityAssociationContext .InitiatorToResponderIntegrityKey ,
582
603
)
583
604
605
+ // NAT-T concern
606
+ if ikeSecurityAssociation .UEIsBehindNAT || ikeSecurityAssociation .N3IWFIsBehindNAT {
607
+ childSecurityAssociationContext .EnableEncapsulate = true
608
+ childSecurityAssociationContext .N3IWFPort = n3iwfAddr .Port
609
+ childSecurityAssociationContext .NATPort = ueAddr .Port
610
+ }
611
+
584
612
// Setup interface for ipsec
585
613
newXfrmiName := fmt .Sprintf ("%s-%d" , n3ueSelf .N3ueInfo .XfrmiName , n3ueSelf .N3ueInfo .XfrmiId )
586
614
if _ , err = xfrm .SetupIPsecXfrmi (newXfrmiName ,
@@ -603,7 +631,7 @@ func HandleIKEAUTH(
603
631
604
632
func HandleCREATECHILDSA (
605
633
udpConn * net.UDPConn ,
606
- n3iwfAddr , ueAddr * net.UDPAddr ,
634
+ ueAddr , n3iwfAddr * net.UDPAddr ,
607
635
message * ike_message.IKEMessage ,
608
636
) {
609
637
ikeLog .Tracef ("Handle CreateChildSA" )
@@ -733,6 +761,13 @@ func HandleCREATECHILDSA(
733
761
return
734
762
}
735
763
764
+ // NAT-T concern
765
+ if ikeSecurityAssociation .UEIsBehindNAT || ikeSecurityAssociation .N3IWFIsBehindNAT {
766
+ childSecurityAssociationContextUserPlane .EnableEncapsulate = true
767
+ childSecurityAssociationContextUserPlane .N3IWFPort = n3iwfAddr .Port
768
+ childSecurityAssociationContextUserPlane .NATPort = ueAddr .Port
769
+ }
770
+
736
771
n3ueSelf .N3ueInfo .XfrmiId ++
737
772
// Aplly XFRM rules
738
773
if err = xfrm .ApplyXFRMRule (false , n3ueSelf .N3ueInfo .XfrmiId , childSecurityAssociationContextUserPlane ); err != nil {
@@ -809,7 +844,7 @@ func HandleCREATECHILDSA(
809
844
810
845
func HandleInformational (
811
846
udpConn * net.UDPConn ,
812
- n3iwfAddr , ueAddr * net.UDPAddr ,
847
+ ueAddr , n3iwfAddr * net.UDPAddr ,
813
848
message * ike_message.IKEMessage ,
814
849
) {
815
850
ikeLog .Infoln ("Handle Informational" )
@@ -823,3 +858,85 @@ func HandleInformational(
823
858
ikeLog .Warnf ("Unimplemented informational message" )
824
859
}
825
860
}
861
+
862
+ func HandleNATDetect (
863
+ initiatorSPI , responderSPI uint64 ,
864
+ notifications []* ike_message.Notification ,
865
+ ueAddr , n3iwfAddr * net.UDPAddr ,
866
+ ) (bool , bool , error ) {
867
+ ueBehindNAT := false
868
+ n3iwfBehindNAT := false
869
+
870
+ srcNatDData , err := GenerateNATDetectHash (initiatorSPI , responderSPI , n3iwfAddr )
871
+ if err != nil {
872
+ return false , false , errors .Wrapf (err , "handle NATD" )
873
+ }
874
+
875
+ dstNatDData , err := GenerateNATDetectHash (initiatorSPI , responderSPI , ueAddr )
876
+ if err != nil {
877
+ return false , false , errors .Wrapf (err , "handle NATD" )
878
+ }
879
+
880
+ for _ , notification := range notifications {
881
+ switch notification .NotifyMessageType {
882
+ case ike_message .NAT_DETECTION_SOURCE_IP :
883
+ ikeLog .Tracef ("Received IKE Notify: NAT_DETECTION_SOURCE_IP" )
884
+ if ! bytes .Equal (notification .NotificationData , srcNatDData ) {
885
+ ikeLog .Tracef ("N3IWF is behind NAT" )
886
+ n3iwfBehindNAT = true
887
+ }
888
+ case ike_message .NAT_DETECTION_DESTINATION_IP :
889
+ ikeLog .Tracef ("Received IKE Notify: NAT_DETECTION_DESTINATION_IP" )
890
+ if ! bytes .Equal (notification .NotificationData , dstNatDData ) {
891
+ ikeLog .Tracef ("UE(SPI: %016x) is behind NAT" , responderSPI )
892
+ ueBehindNAT = true
893
+ }
894
+ default :
895
+ }
896
+ }
897
+ return ueBehindNAT , n3iwfBehindNAT , nil
898
+ }
899
+
900
+ func BuildNATDetectNotifPayload (
901
+ localSPI uint64 , remoteSPI uint64 ,
902
+ payload * ike_message.IKEPayloadContainer ,
903
+ ueAddr , n3iwfAddr * net.UDPAddr ,
904
+ ) error {
905
+ srcNatDHash , err := GenerateNATDetectHash (localSPI , remoteSPI , ueAddr )
906
+ if err != nil {
907
+ return errors .Wrapf (err , "build NATD" )
908
+ }
909
+ // Build and append notify payload for NAT_DETECTION_SOURCE_IP
910
+ payload .BuildNotification (
911
+ ike_message .TypeNone , ike_message .NAT_DETECTION_SOURCE_IP , nil , srcNatDHash )
912
+
913
+ dstNatDHash , err := GenerateNATDetectHash (localSPI , remoteSPI , n3iwfAddr )
914
+ if err != nil {
915
+ return errors .Wrapf (err , "build NATD" )
916
+ }
917
+ // Build and append notify payload for NAT_DETECTION_DESTINATION_IP
918
+ payload .BuildNotification (
919
+ ike_message .TypeNone , ike_message .NAT_DETECTION_DESTINATION_IP , nil , dstNatDHash )
920
+
921
+ return nil
922
+ }
923
+
924
+ func GenerateNATDetectHash (
925
+ initiatorSPI , responderSPI uint64 ,
926
+ addr * net.UDPAddr ,
927
+ ) ([]byte , error ) {
928
+ // Calculate NAT_DETECTION hash for NAT-T
929
+ // : sha1(ispi | rspi | ip | port)
930
+ natdData := make ([]byte , 22 )
931
+ binary .BigEndian .PutUint64 (natdData [0 :8 ], initiatorSPI )
932
+ binary .BigEndian .PutUint64 (natdData [8 :16 ], responderSPI )
933
+ copy (natdData [16 :20 ], addr .IP .To4 ())
934
+ binary .BigEndian .PutUint16 (natdData [20 :22 ], uint16 (addr .Port )) // #nosec G115
935
+
936
+ sha1HashFunction := sha1 .New () // #nosec G401
937
+ _ , err := sha1HashFunction .Write (natdData )
938
+ if err != nil {
939
+ return nil , errors .Wrapf (err , "generate NATD Hash" )
940
+ }
941
+ return sha1HashFunction .Sum (nil ), nil
942
+ }
0 commit comments