Use cases and policies
TrustCore SDK NanoSec provides flexibility for an almost unlimited number of IPsec/IKE configurations. However, typical applications generally fall into one of just four use cases. To configure policies for a NanoSec deployment, first determine which use case most closely matches the desired configuration.
This section provides use case diagrams for typical NanoSec deployment scenarios, and detailed information and examples of how to configure the corresponding security policies by either of two alternate approaches, either by using policy scripts or NanoSec API method calls.
For detailed instructions, see Managing Policies with API Methods.
For details and diagrams, see the following sections:
Host-to-Host Two peer machines communicate securely at the IP layer level.
VPN Tunnel Client and host machines communicate securely using VPN by implementing a secure IPsec tunnel.
MOBIKE One peer has a fixed address while the other peer’s address is changing (due to mobility or an interface change).
Multicast One broadcaster machine securely sends information (through a router) to multiple receivers (clients).
After identifying the best use case match, decide which policy approach is appropriate:
Policy scripting: NanoSec policy scripts are strings of keywords that are used to configure IPsec policies. Using these scripts is an easier alternative to manually building the required structures within an application and making calls to add the policies to the SPD (security policy database).
For detailed instructions, see Adding Policies by Using NanoSec Policy Scripts below. - Coding with NanoSec API methods: When a direct, controlled approach is needed to manage security policies, such as for multicasting scenarios, the necessary policy, key structures, and call NanoSec API methods must be manually defined to apply the desired policies.
Adding Policies by Using NanoSec Policy Scripts
To add policies created by policy scripting, a buffer is filled with the policy information and then the NanoSec IPSEC_ParseScript function is used to add the policies to the SPD.
To add a policy using a NanoSec policy script:
Fill a buffer with the policy script, using either of the following approaches:
Using a Policy File
Embedding Policies in Code
Call IPSEC_ParseScript to parse the buffer and add the policies to the SPD.
Important: This procedure adds the policies to the end of the SPD. To change an existing policy, either start over (stop and restart NanoSec, and create the desired policies) or use the API methods (see Managing Policies with API Methods).
Example
This example illustrates how to use a policy file, read it using the MOCANA_readFile
function, and then add the file’s policies to the SPD.
static sbyte4 loadConfFile(sbyte *configFile) { MSTATUS status; ubyte *buffer; ubyte4 fsize; if (NULL == configFile) return -1; status = MOCANA_readFile(configFile, &buffer, &fsize); /* Read policy file */ if (status != OK) { perror(configFile); return status; } buffer[fsize] = (ubyte)0; if (OK > (status = IPSEC_ParseScript((sbyte *)buffer))) /* Add policy to SPD */ { fprintf(stderr, "Error parsing config script: %dn", status); } free(buffer); return status; }
Figure 1: IPsec tunnel and transport modes
Using a Policy File
To avoid recompiling an application code whenever a policy needs to be changed, place the policies in a policy file—a text file containing the policy script.
For details about policy script elements and syntax, see Appendix: NanoSec Policy Scripts Syntax.
The following code listing is a simple example of a NanoSec policy file:
# This line is a comment! # # Examples of transport mode mirror policy: # { laddr 192.168.3.122 raddr 192.168.3.110 ulp icmp } ipsec { encr_algs 3des encr_auth_algs sha1 } # # # Examples of tunnel mode mirror policy: # tladdr - local tunnel gateway # traddr - remote tunnel gateway # { laddr 192.168.1.2 raddr 192.168.2.2 } ipsec { tladdr 10.0.0.1 traddr 10.0.0.2 encr_algs 3des encr_auth_algs sha1 } # # { raddr 192.168.3.110 ulp icmp } ipsec { encr_algs 3des encr_auth_algs sha1 } { raddr 192.168.3.115 ulp icmp } ipsec { encr_algs aes encr_auth_algs md5 } { raddr 192.168.3.116 ulp icmp } ipsec { encr_algs any encr_auth_algs any } # AES CBC algorithm with key length 192 bits and blake2b auth algorithm { raddr 192.168.3.117 ulp icmp } ipsec { encr_algs aes keylength 24 encr_auth_algs blake2b } # # AES GCM algorithm with key length 256 bits and ICV 12 bytes { raddr 192.168.3.118 ulp icmp } ipsec { encr_algs gcm tag 12 keylength 32 } # AES CCM algorithm with key length 192 bits and ICV 12 bytes { raddr 192.168.3.119 ulp icmp } ipsec { encr_algs ccm tag 12 keylength 24 } # AES GCM algorithm with key length 256 bits and ICV 12 bytes { raddr 192.168.3.120 ulp icmp } ipsec { encr_algs gcm tag 12 keylength 32 } # AES GMAC algorithm with key length 192 bits (ICV is fixed at 16 bytes) { raddr 192.168.3.120 ulp icmp } ipsec { encr_algs gmac keylength 24 }
An application can use any method to read the policy file and place its contents into a buffer so that the policies can be added to the SPD:
Use the MOCANA_readFile function.
Use an application-specific read function.
Use low-level read functions, such as fopen.
It does not matter which method is used as long as the result is a buffer (containing the policy script) that can be used as the parameter of the IPSEC_ParseScript.
Embedding Policies in Code
An alternative to using a policy file is to create the policies’ script within the application code itself. Simply define a ubyte buffer and fill it with a NULL-terminated string containing the desired policies.
Although this approach requires that the code be recompiled any time the policies are changed, it is useful when there are security or maintainability concerns about using text files separate from the application’s code.
Managing Policies with API Methods
Although using NanoSec policy scripts is the easiest way to add IPsec policies, there are times when a direct, controlled approach is needed to manage the policies, such as when:
The configuration changes frequently while NanoSec is running.
A policy failure needs to debugged. (Debugging a policy script error such as a typo can be difficult because it is tricky to determine which policies have been applied up to the failure point.)
Fields for ipsecConf need to be configured and there are no corresponding script fields .
Only a single policy instead of resetting all policies.
A single policy needs to be dynamically added while leaving the existing policies intact.
Keys need to be manually managed instead of using NanoSec IKE (e.g., when using multicasting).
To manage a policy with an API method:
Allocate an ipsecConf structure.
Fill in the required fields, as well as any optional fields that are needed to fully define the desired policy (see below table).
Call the appropriate NanoSec API function:
IPSEC_confAdd
Add one or more policies to the end of the SPD (security policy database).IPSEC_confDelete
Delete a single policy from the SPD.IPSEC_confFlush
Flush (delete) all the policies from the SPD.
These functions can be called anytime—during initialization to set up initial policies, or dynamically during program execution to change policies.
The table below lists the ipsecConf structure’s fields, provides a description of valid values for each field, and where applicable, lists the NanoSec policy script element that corresponds to the structure field.
ipsecConf Field | Description | Policy Script Field(s) |
---|---|---|
dwSrcIP | Source IP address (in host byte order); |
|
dwSrcIPEnd | (Optional) source IP range upper limit; |
|
wSrcPort | Source port number; | sport, rport, lport |
dwDestIP | Destination IP address (in host byte order); |
|
dwDestIPEnd | (Optional) Destination IP range upper limit; |
|
wDestPort | Destination port number; |
|
oProto | Upper layer protocol; |
|
oAction | Any of the IPsec actions for SPD: |
|
oDir | Any of the IPsec directions for SPD: |
|
oSaLen | SA bundle depth (typically 1) | Derived from the contents of the |
pxSA | Pointer to SA bundle; |
|
oMode | Any of the IPsec mode definitions: | Derived from the contents of the script (which addresses are included) |
dwTunlDestIP | Tunnel destination IP address (in host byte order). |
|
dwTunlSrcIP | Tunnel source IP address (in host byte order). |
|
index | SPD index; |
|
oFlags | Specifies backward compatibility of IPv6 policies to IPv4 when the | Derived from the IP addresses’ format (IPv4 or IPv6) |
Figure 2: Example of MOBIKE with changing public IPs due to roaming
Host-to-Host
In host-to-host communications, two peer machines communicate securely by using NanoSec in transport mode (see below). The most typical application for this configuration is to encrypt telnet TCP traffic between a workstation and router, where the router is the actual destination.
For policy examples of typical host-to-host scenarios, see the following sections: (below) - Encrypting All Packets (below) - Encrypting TCP Traffic - Encrypting Telnet Port Traffic
Encrypting All Packets
The easiest and most secure scheme is to encrypt all packets between the two peers.
Policy Scripting
To encrypt all packets sent between peer A and peer B, use the following NanoSec security policy for Peer A:
{laddr 192.168.3.1 raddr 192.168.3.5} ipsec {encr_algo <en> encr_auth_algs <auth>}
where:
<en>
is the desired encryption algorithm, such as 3des.<auth>
is the desired authentication mechanism, such as sha1.
Note: The use of the mirrored ipsec action field is highly recommended overusing separate apply and permit definitions.
The NanoSec security policy for Peer B is simply a mirror image of Peer A’s policy with respect to the local and remote address fields (laddr and raddr, respectively):
{laddr 192.168.3.5 raddr 192.168.3.1} ipsec {encr_algo <en> encr_auth_algs <auth>}
Using API Methods
As an alternative to scripting, the ipsecConf structure can be manually defined to add policies that enables encryption of all traffic.
On Peer A, execute the code in the following listing:
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwSrcIP = ipv4_addr(192,168,3,1); conf.dwDestIP = ipv4_addr(192,168,3,5); conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TRANSPORT; conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
Figure 3: Example of using MOBIKE to switch between a laptop’s two interfaces
On Peer B, execute the code in the following listing:
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwSrcIP = ipv4_addr(192,168,3,5); conf.dwDestIP = ipv4_addr(192,168,3,1); conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TRANSPORT; conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
Encrypting TCP Traffic
Sometimes it is neither necessary nor desirable to encrypt all traffic between peers. For example, encrypting only TCP traffic leaves the remaining communications unaffected, which can improve performance.
Policy Scripting
To specify that only TCP upper layer protocol packets be encrypted, add “ulp tcp” to the previous security policies (see Encrypting All Packets).
The policy for Peer A becomes:
{laddr 192.168.3.1 raddr 192.168.3.5 ulp tcp} ipsec {encr_algo <en> encr_auth_algs <auth>}
The policy for Peer B is:
{laddr 192.168.3.5 raddr 192.168.3.1 ulp tcp} ipsec {encr_algo <en> encr_auth_algs <auth>}
Using API Methods
As an alternative to scripting, the ipsecConf structure can be manually defined to add policies that enable encryption of only TCP traffic. On Peer A, execute the code in the following listing.
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwSrcIP = ipv4_addr(192,168,3,1); conf.dwDestIP = ipv4_addr(192,168,3,5); conf.oProto = IPPROTO_TCP; conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TRANSPORT; conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
NanoSec Policy Configuration Structure Fields
On Peer B, execute the code in the following listing.
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwSrcIP = ipv4_addr(192,168,3,5); conf.dwDestIP = ipv4_addr(192,168,3,1); conf.oProto = IPPROTO_TCP; conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TRANSPORT; conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
Example of host-to-host transport mode with NanoSec
Encrypting Telnet Port Traffic
In addition to specifying the type of traffic to encrypt, traffic can be encrypted for specific ports, such as Telnet port 23.
Policy Scripting
To specify that encryption should be applied only to traffic through Telnet port 23, add “rport” and “lport” fields to security policies.
Which peer uses the lport definition is determined by which peer is providing the applicable service. In this section’s example, Peer B is acting as the Telnet server, so the lport (local port) definition is part of Peer B’s policy, while the corresponding rport definition is included in Peer A’s policy.
Continuing with the preceding example, the policy for Peer A becomes:
{laddr 192.168.3.1 raddr 192.168.3.5 ulp tcp rport 23} ipsec {encr_algo <en> encr_auth_algs <auth>}
The policy for Peer B is:
{laddr 192.168.3.5 raddr 192.168.3.1 ulp tcp lport 23} ipsec {encr_algo <en> encr_auth_algs <auth>}
Using API Methods
As an alternative to scripting, the ipsecConf structure can be manually defined to add policies to enable encryption of only traffic on TCP Telnet port 23.
On Peer A, execute the code in the following listing.
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwSrcIP = ipv4_addr(192,168,3,1); conf.dwDestIP = ipv4_addr(192,168,3,5); conf.wDestPort = 23; conf[0[.oProto = IPPROTO_TCP; conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TRANSPORT; conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
On Peer B, execute the code in the following listing.
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwSrcIP = ipv4_addr(192,168,3,5); conf.dwDestIP = ipv4_addr(192,168,3,1); conf.wSrcPort = 23; conf.oProto = IPPROTO_TCP; conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TRANSPORT; conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
Figure 7: Example of MOBIKE with changing public IPs due to roaming
VPN Tunnel
VPN tunnels secure traffic between two machines (see below) just as host-to-host transport mode does; however, a VPN tunnel enables secure communications between private IP addresses, not just public addresses. This method supports the typical “road warrior” IPsec use case where a person uses a laptop computer while traveling (i.e., the public IP address changes from location to location) to connect to his or her business’s private network that uses a firewall.
Policy Scripting
To encrypt all packets between Client A and Server/Gateway B, use the following NanoSec security policy for Client A:
{laddr 10.10.1.1} ipsec {encr_algo <en> encr_auth_algs <auth> tladdr 192.168.3.1 traddr 192.168.3.5}
where:
<en>
is the desired encryption algorithm, such as 3des.<auth>
is the desired authentication mechanism, such as sha1.
The corresponding policy for Server/Gateway B is:
{raddr 10.10.1.1} ipsec {encr_algo <en> encr_auth_algs <auth> tladdr 192.168.3.5 traddr 192.168.3.1}
The security policies reference Client A’s private address (not Server/Gateway B’s private address), which is part of the VPN credentials for the user’s client machine.
Using API Methods
As an alternative to scripting, the ipsecConf structure can be manually defined to add policies to enable encrypting all packets between Client A’ s private IP and Server/Gateway B.
On Client A, execute the code in the following listing.
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwSrcIP = ipv4_addr(10,10,1,1); conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TUNNEL; conf.dwTunlSrcIP = ipv4_addr(192,168,3,1); conf.dwTunlDestIP = ipv4_addr(192,168,3,5); conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
On Server/Gateway B, execute the code in the following listing.
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwDestIP = ipv4_addr(10,10,1,1); conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TUNNEL; conf.dwTunlSrcIP = ipv4_addr(192,168,3,5); conf.dwTunlDestIP = ipv4_addr(192,168,3,1); conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
MOBIKE
MOBIKE is the mobility and multihoming extension to Internet Key Exchange (IKEv2), as defined in RFC 4555, IKEv2 Mobility and Multihoming Protocol (MOBIKE). It was developed to address situations where IP addresses change, such as:
Roaming devices (e.g., smartphones and wireless-connected laptops.)
Switching from one interface to another (e.g., from wired to wireless).
Roaming Devices
Below shows how MOBIKE is used when a device’s IP changes due to roaming.
When configuring NanoSec for MOBIKE, NanoSec automatically manages policy changes due to changing (roaming) IP addresses; therefore, the initial policy is set up just as it is for a standard VPN tunnel.
Policy Scripting
To encrypt all packets between Client A and Server/Gateway B, use the following NanoSec security policy for Client A:
{laddr 10.10.1.1} ipsec {encr_algo <en> encr_auth_algs <auth> tladdr 192.168.3.1 traddr 192.168.3.5}
where:
<en>
is the desired encryption algorithm, such as 3des.<auth>
is the desired authentication mechanism, such as sha1.
The corresponding policy for Server/Gateway B is:
{raddr 10.10.1.1} ipsec {encr_algo <en> encr_auth_algs <auth> tladdr 192.168.3.5 traddr 192.168.3.1}
Using API Methods
As an alternative to scripting, the ipsecConf structure can be manually defined to add policies to enable encrypting all packets between Client A’ s private IP and Server/Gateway B.
On Client A, execute the code in the following listing.
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwSrcIP = ipv4_addr(10,10,1,1); conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TUNNEL; conf.dwTunlSrcIP = ipv4_addr(192,168,3,1); conf.dwTunlDestIP = ipv4_addr(192,168,3,5); conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
On Server/Gateway B, execute the code in the following listing.
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwDestIP = ipv4_addr(10,10,1,1); conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TUNNEL; conf.dwTunlSrcIP = ipv4_addr(192,168,3,5); conf.dwTunlDestIP = ipv4_addr(192,168,3,1); conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
Changing Interfaces
The figure below shows how MOBIKE is used when a device has multiple interfaces that must be secured in sequence, such as when a user unplugs from a wired connection and switches to a wireless connection.
To change interfaces:
In the initialization code, create a listener (such as a UDP socket) for each interface.
Associate each interface’s listener with a server instance (i.e., the same application-specific identifier that is used in calls to IKE2_msgRecv).
Next is to set up the initial policies. Assuming that the connection is initially set up using Client A’s Interface 1, the initial policy set up is the same as the previous scenarios. Use either Policy scripting or API methods.
Policy scripting
To encrypt all packets between Client A and Server/Gateway B, use the following NanoSec security policy for Client A:
{laddr 10.10.1.1} ipsec {encr_algo <en> encr_auth_algs <auth> tladdr 192.168.3.1 traddr 192.168.3.5}
where:
<en>
is the desired encryption algorithm, such as 3des.<auth>
is the desired authentication mechanism, such as sha1.
Use the corresponding policy for Server/Gateway B:
{raddr 10.10.1.1} ipsec {encr_algo <en> encr_auth_algs <auth> tladdr 192.168.3.5 traddr 192.168.3.1}
Using API methods
To manually define the ipsecConf
structure and add the policies to enable encrypting all packets between Client A’s private IP and Server/Gateway B, execute the code in the following listings.
On Client A:
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwSrcIP = ipv4_addr(10,10,1,1); conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TUNNEL; conf.dwTunlSrcIP = ipv4_addr(192,168,3,1); conf.dwTunlDestIP = ipv4_addr(192,168,3,5); conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
Process Overview: Working with NanoSec
On the Server/Gateway B:
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; conf.dwDestIP = ipv4_addr(10,10,1,1); conf.oAction = IPSEC_ACTION_APPLY; conf.oDir = IPSEC_DIR_MIRRORED; conf.oMode = IPSEC_MODE_TUNNEL; conf.dwTunlSrcIP = ipv4_addr(192,168,3,5); conf.dwTunlDestIP = ipv4_addr(192,168,3,1); conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_SHA1; /* e.g., <auth> is sha1 */ saInfo.oEncrAlgo = IPSEC_ENCALG_3DES; /* e.g., <en> is 3des */ IPSEC_confAdd(&conf, 1);
When an application’s message processing loop detects that there is no communications through Interface 1, it should make a call to the IKE2_keyUpdate function to switch from Interface 1 (192.168.3.1) to Interface 2 (172.13.12.1).
The IKE2_keyUpdate function’s prototype is:
MOC_EXTERN sbyte4 IKE2_keyUpdate(sbyte4 serverInstanceOld, sbyte4 serverInstanceNew);
The serverInstanceOld and serverInstanceNew values are application-specific and depend on how the application creates server instances. The server values may be as simple as integer representations of the IP addresses, or as complicated as application-specific structures containing custom information. Regardless of their values, the server instances are those that are associated with the UDP listen sockets that are created during NanoSec IKE initialization.
Multicast
Multicasting can be ensured by using NanoSec as shown in Figure 9 below. Broadcaster B sends packets to a channel (IP range 224.0.0.0/4), port X. The Receivers R1, R2, and R3 register themselves as listeners on this channel using IGMP (Internet Group Management Protocol). This information is available to the Router R. Broadcaster B, and then sends packets to the router, which sends copies to each of the registered receivers.
Key Management
NanoSec IKE cannot be used for multicasting because, by definition, multicasting means communications from one node to many. It is impossible to automatically negotiate a single session key to communicate with many nodes. The session key can be manually managed or integrate NanoSec with NanoGDOI. For information about the NanoGDOI add-in and how to integrate it with NanoSec, refer to the NanoGDOI Product Guide.
Policy Setup
To enable encrypting all packets that Broadcaster B sends to each Receiver (R1, R2, and R3), execute the code in the following listing on Broadcaster B:
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; struct ipsecKey key = { 0 }; conf.dwSrcIP = ipv4_addr(172,168,1,1); conf.dwDestIP = ipv4_addr(224,0,0,0); conf.dwDestIPEnd = ipv4_addr(239,255,255,255); conf.oProto = 89; /* e.g., OSPF */ conf.oAction = IPSEC_ACTION_APPLY; conf.oMode = IPSEC_MODE_TRANSPORT; conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_MD5; /* e.g., <auth> is md5 */ saInfo.oEncrAlgo = IPSEC_ENCALG_AES; /* e.g., <en> is aes */ IPSEC_confAdd(&conf, 1); /* Enter Group SA for each channel Broadcaster B sends messages to */ key.oProtocol = IPPROTO_ESP; key.dwSpi = 0xab143f7b; /* manually configured */ key.dwSrcAddr = ipv4_addr(172,168,1,1) /* sender (i.e., this host) */ key.dwDestAddr = ipv4_addr(232,5,16,1); /* channel */ key.oAuthAlgo = IPSEC_AUTHALG_MD5; /* e.g., <auth> is md5 */ key.pAuthKey = "123456789abcdef0123456789abcdef0"; /* use your key */ key.wAuthKeyLen = 32; /* use your key length */ key.oEncrAlgo = IPSEC_ENCALG_AES; /* e.g., <en> is aes */ key.pEncrKey = "123456789abcdef0123456789abcdef1"; /* use your key */ key.wEncrKeyLen = 32; /* use your key length */ IPSEC_keyAdd(&key, 1);
On each receiver (R1, R2, and R3), execute the code in the following listing.
#define ipv4_addr(a,b,c,d) ((a<<24)+(b<<16)+(c<<8)+d) struct ipsecConf conf = { 0 }; struct sainfo saInfo = { 0 }; struct ipsecKey key = { 0 }; conf.dwSrcIP = ipv4_addr(172,168,1,1); conf.dwDestIP = ipv4_addr(224,0,0,0); conf.dwDestIPEnd = ipv4_addr(239,255,255,255); conf.oProto = 89; /* e.g., OSPF */ conf.oAction = IPSEC_ACTION_PERMIT; conf.oMode = IPSEC_MODE_TRANSPORT; conf.oSaLen = 1; conf.pxSa = &saInfo; saInfo.oSecuProto = IPSEC_PROTO_ESP_AUTH; saInfo.oAuthAlgo = IPSEC_AUTHALG_MD5; /* e.g., <auth> is md5*/ saInfo.oEncrAlgo = IPSEC_ENCALG_AES; /* e.g., <en> is aes */ IPSEC_confAdd(&conf, 1); /* Enter Group SA for each channel this Receiver belongs to */ key.oProtocol = IPPROTO_ESP; key.dwSpi = 0xab143f7b; /* manually configured */ key.dwSrcAddr = ipv4_addr(172,168,1,1) /* sender (Broadcaster B) */ key.dwDestAddr = ipv4_addr(232,5,16,1); /* channel */ key.oAuthAlgo = IPSEC_AUTHALG_MD5; /* e.g., <auth> is md5 */ key.pAuthKey = "123456789abcdef0123456789abcdef0"; /* use your key */ key.wAuthKeyLen = 32; /* use your key length */ key.oEncrAlgo = IPSEC_ENCALG_AES; /* e.g., <en> is aes */ key.pEncrKey = "123456789abcdef0123456789abcdef1"; /* use your key */ key.wEncrKeyLen = 32; /* use your key length */ IPSEC_keyAdd(&key, 1);