preface
IPsec has many configuration dependencies. If you don't pay attention to it, it is easy to make a configuration error. As long as the configuration error is wrong, it is easy to cause IPsec to fail; So I hope to use some means to simplify these complex configurations; So I use python language, which is not difficult to learn but very mature, to solve this kind of problem.1, Basic environment
Networking environment
Configure the IP address of each interface
Main basic configuration of headquarters exit router
sysname HQ ip route-static 0.0.0.0 0 100.0.0.100 acl advanced 3000 rule 5 permit ip interface GigabitEthernet0/2 nat outbound 3000
Main basic configuration of branch exit router
sysname branch ip route-static 0.0.0.0 0 200.0.0.2 acl advanced 3000 rule 5 permit ip interface GigabitEthernet0/0 nat outbound 3000
2, Write the jinja2 configuration template of IPsec
{# Create a stream of interest #} acl advanced {{ AclNumber }} rule permit ip source {{ SouNet }} destination {{ DestNet }} quit {# establish IKE proposal #} ike proposal 1 authentication-method pre-share encryption-algorithm aes-cbc-128 quit {# establish IKE Preshared key #} ike keychain {{ KPT }} pre-shared-key address {{ RemotePublicIp }} key simple {{ IkePassword }} quit {# establish IKE-profile,Specify the local and peer public network addresses, and call the pre shared key and IKE proposal#} ike profile {{ KPT }} keychain {{ KPT }} local-identity address {{ LocalPublicIp }} match remote identity address {{ RemotePublicIp }} proposal 1 quit {# establish IPsec Conversion set,Tunnel mode and are used by default esp Package, so don't worry #} ipsec transform-set {{ KPT }} esp authentication-algorithm sha1 esp encryption-algorithm aes-cbc-128 quit {# establish IPsec Policy, call the above configuration #} ipsec policy {{ KPT }} 1 isakmp security acl {{ AclNumber }} ike-profile {{ KPT }} transform-set {{ KPT }} remote-address {{ RemotePublicIp }} quit {# Issue on the public network interface IPsec strategy #} int {{ IntfPort }} ipsec apply policy {{ KPT }} quit {# Adaptation IPsec Public network of NAT ACL #} acl advanced {{ NatNum }} rule 1 deny ip source {{ SouNet }} destination {{ DestNet }} rule permit ip source any quit {# Modify on public network interface NAT Export ACL #} int {{ IntfPort }} nat outbound {{ NatNum }} quit
Why should IPsec traffic be rejected first on the NAT ACL rules of the public network adapted to IPsec
Solution: if the traffic data matches NAT, it will go through NAT by default. If it fails to make the traffic data go through IPsec, it needs to be rejected first to match the subsequent IPsec policies, and then match the rules in IPsec.
2, Write IPsec rendering script
import winreg #Get the desktop environment, and output the configuration file directly to the desktop for easy search from pathlib import Path #The dependency package for creating files is easier to use than os, so I use this from jinja2 import FileSystemLoader,Environment #Packages required for rendering using jinja2 def GetDesktop(): #Get desktop path key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders",) return Path(winreg.QueryValueEx(key, "Desktop")[0]) def IpsecVPnRender(outputpath): #IpsecVPN rendering loader = FileSystemLoader("templates") #Load templates template folder environment = Environment(loader=loader) #Added to jinja2's environment SouDevice = environment.get_template("IpsecVpn.conf.tp") DestDevice = environment.get_template("IpsecVpn.conf.tp") AclNumber = int(input("Input match IPsec of ACL Serial number:")) SouNet = input("Enter the network number of the local private network segment/host+Unmask:") #These two methods are reversed when rendering DestNet = input("Enter the network number of the destination private network segment/host+Unmask:") print("The following three modules will be uniformly named: ike-proposal,profile,transform") KPT = input("Enter the unified name of the three modules:") #Policy name of Src IkePassword = input("input IKE Password for:") LocalPublicIp = input("Input local public network IP Address without mask:") RemotePublicIp = input("Input peer-to-peer public network IP Address without mask:") IntfportSrc = input("Input local application IPsec Port for policy(Public network exit):") #Public network interface NatNum = input("Input local application NAT of ACL Serial number:") #Only advanced ACL S are supported because IPsec traffic should be rejected SouDevice.stream(AclNumber = AclNumber, SouNet = SouNet, DestNet = DestNet, KPT = KPT, IkePassword = IkePassword, LocalPublicIp = LocalPublicIp, RemotePublicIp = RemotePublicIp, IntfPort = IntfportSrc, NatNum = NatNum).dump(outputpath.format(f"IPSEC {LocalPublicIp}.conf")) #Such as the parameters required by the jinja2 template print("The local end has been rendered successfully, and the end-to-end rendering will be performed IPsec Mirror rendering, render?") tag = input("input y/n:") if tag == "y": KPT1 = KPT+"1" #As the policy name of Dest IntfportDest = input("Apply this to the input end IPsec Port for policy(Public network exit):") #Public network interface NatNum = input("Input to end application NAT of ACL Serial number:") DestDevice.stream(AclNumber = AclNumber, SouNet = DestNet, DestNet = SouNet, KPT = KPT1, IkePassword = IkePassword, LocalPublicIp = RemotePublicIp, RemotePublicIp = LocalPublicIp, IntfPort = IntfportDest, NatNum = NatNum).dump(outputpath.format(f"IPSEC {RemotePublicIp}.conf")) print("Local end+Both ends have been rendered") def main():#Use the main function to arrange the execution process DesktopPath = GetDesktop() / "config" DesktopPath.mkdir(parents=True,exist_ok=True) IpsecVPnRender(str(DesktopPath)+"\\{}") main() #Execute main function
4, Run the python script and enter the parameters according to the prompt (my environment uses Jupiter)
On the desktop, we can see that the IPsec configuration file has been generated; In order to distinguish, I use the file ending in conf. right click and use Notepad to open it, and use the public network address to distinguish. The public network address file name is the configuration of the end where the public network address is located.
Open the file and the configuration file has been rendered. Directly use the shortcut commonly used by our network people Ctrl + A and then Ctrl + C; Right click and paste in the configuration interface; Of course, it needs to be improved for different environments, so the configuration file is generated. In this way, some other configurations can be attached and pasted together; You can also make corresponding configuration changes for different environments.
test
The opposite IP address is 2.1; Communication is normal. IPsec setup succeeded.
Why don't I use yaml to write configuration modules
Because the amount of code is too small and there are few modules, the efficiency of using yaml to write configuration files is still relatively low, especially for those who are not familiar with yaml, they also need to learn yaml syntax first; the loss outweighs the gain; For this interactive environment, running scripts can be used; Very convenient.