
Set Up a Site-to-Site IPsec VPN on a Cisco ASA
Before you run this
This guide builds a policy-based site-to-site IPsec VPN between two Cisco ASAs using IKEv2, so hosts on your local LAN can reach hosts on a remote LAN over an encrypted tunnel across the public internet. It defines the crypto policy, a pre-shared key, the interesting-traffic ACL, the NAT exemption, and applies a crypto map to the outside interface.
You need privileged EXEC (enable) access and then global configuration mode (configure terminal). On most deployments that is privilege level 15. This is not a script you run once — every line below is a live change to a production firewall.
Read every command before you paste it, and if you can, build the config first on a lab ASA or an ASAv VM with the same software version. A wrong crypto ACL or, worse, a wrong NAT statement can black-hole production traffic, not just the VPN.
Firewall-specific cautions, and I mean these literally:
- Keep a separate console or out-of-band session open the whole time. If you apply the crypto map or a NAT rule wrong and you are managing the ASA over the same path the VPN or NAT touches, you can lock yourself out and cut user traffic at the same time.
- Back up the running config before you touch anything (commands below). The ASA has no timed auto-rollback like PAN-OS commit or a snapshot revert like some appliances. Your rollback is either negating each command with its
noform, or — if you have not yet runwrite memory— areloadthat reboots into the last saved startup config. - Do this in a maintenance window. The NAT-exemption line especially can affect existing sessions.
Nothing here is destructive to data, but a bad NAT or crypto map is disruptive to traffic, and that is enough reason to treat it carefully.
Assumptions
- Both ends are Cisco ASA running software 9.x (I tested this on 9.12; IKEv2 syntax is stable from 9.8 onward).
- The outside interface is named
outsideand the insideinside. - We are building a route-based-free, policy-based tunnel — the classic crypto-map style, which is the mainstream ASA approach. (VTI / route-based VPNs exist on 9.7+; that is a different build and I am not covering it here.)
- Both peers have a static, reachable public IP, and a default route toward the internet already works.
Replace every placeholder below with your real values:
| Placeholder | Meaning |
|---|---|
203.0.113.2 |
The remote ASA's public IP (peer) |
10.10.10.0 255.255.255.0 |
Your local protected subnet |
10.20.20.0 255.255.255.0 |
The remote protected subnet |
<YOUR-PSK> |
The pre-shared key, identical on both peers |
Step 0 — Back up the running config first
! From enable mode. Save a copy to flash before changing anything.
copy running-config disk0:/pre-vpn-backup.cfg
If you have a TFTP server, copy running-config tftp: works too. Do not run write memory again until the tunnel is verified — that way a reload gets you back to a clean state.
Step 1 — IKEv2 policy (Phase 1)
crypto ikev2 policy 10
encryption aes-256
integrity sha256
group 14
prf sha256
lifetime seconds 86400
The IKEv2 policy on the remote peer must offer a matching set. group 14 is a sound, widely-supported DH group; use a stronger group only if both ends support it.
Enable IKEv2 on the internet-facing interface:
crypto ikev2 enable outside
Step 2 — IPsec proposal (Phase 2)
crypto ipsec ikev2 ipsec-proposal AES256-SHA256
protocol esp encryption aes-256
protocol esp integrity sha-256
Step 3 — Define the interesting traffic
This ACL says "which traffic goes down the tunnel." It must be the mirror image of the remote peer's crypto ACL (their local/remote subnets swapped).
access-list VPN-TO-SITEB extended permit ip 10.10.10.0 255.255.255.0 10.20.20.0 255.255.255.0
Step 4 — Exempt VPN traffic from NAT
If your inside hosts are normally PAT'd to the outside, that translation will break the tunnel unless you exempt VPN traffic. This is the step that most often causes an outage, so read it twice.
object network LOCAL-LAN
subnet 10.10.10.0 255.255.255.0
object network REMOTE-LAN
subnet 10.20.20.0 255.255.255.0
nat (inside,outside) source static LOCAL-LAN LOCAL-LAN destination static REMOTE-LAN REMOTE-LAN no-proxy-arp route-lookup
This is a "NAT exemption" (identity NAT): traffic from LOCAL-LAN to REMOTE-LAN is translated to itself, i.e. not translated. On 9.x this manual NAT statement is inserted at the top of the NAT table by default, which is what we want.
Step 5 — Tunnel group and pre-shared key
tunnel-group 203.0.113.2 type ipsec-l2l
tunnel-group 203.0.113.2 ipsec-attributes
ikev2 remote-authentication pre-shared-key <YOUR-PSK>
ikev2 local-authentication pre-shared-key <YOUR-PSK>
The tunnel-group name is the peer's public IP for a LAN-to-LAN tunnel.
Step 6 — Crypto map and apply it
crypto map OUTSIDE-MAP 10 match address VPN-TO-SITEB
crypto map OUTSIDE-MAP 10 set peer 203.0.113.2
crypto map OUTSIDE-MAP 10 set ikev2 ipsec-proposal AES256-SHA256
crypto map OUTSIDE-MAP 10 set pfs group14
Then bind the crypto map to the outside interface. If a crypto map is already applied to outside, do not re-apply — just add your new sequence number (10) to the existing map name. Applying a second map to the same interface is not allowed and will error.
crypto map OUTSIDE-MAP interface outside
Now configure the mirror of all of this on the remote ASA (subnets swapped, same PSK, same crypto parameters).
Step 7 — Bring it up and verify
Send a ping from a local inside host to a remote inside host (or source a ping from the ASA's inside interface) to generate interesting traffic, then check:
show crypto ikev2 sa ! Phase 1 — expect state READY for the peer
show crypto ipsec sa ! Phase 2 — look for "encaps"/"decaps" counters climbing
show vpn-sessiondb detail l2l
If show crypto ikev2 sa shows nothing and traffic still fails, watch the negotiation live:
debug crypto ikev2 protocol 4
debug crypto ikev2 platform 4
Turn debugs off with undebug all when done — they are noisy on a busy box.
The usual culprits, in the order I check them: mismatched PSK, non-mirrored crypto ACLs, a NAT statement translating the VPN traffic before the exemption, or the peer unreachable on UDP 500/4500.
Make it permanent
Only once the tunnel is up, traffic passes, and production is unaffected:
write memory
Until you run that, a reload reverts the ASA to the pre-change startup config — your safety net.
How to undo it
There is no single rollback command on the ASA. Remove the pieces in reverse, using the no form of each block. The order matters — pull the crypto map off the interface first:
no crypto map OUTSIDE-MAP interface outside
clear configure crypto map OUTSIDE-MAP
no tunnel-group 203.0.113.2 ipsec-attributes
no tunnel-group 203.0.113.2 type ipsec-l2l
no nat (inside,outside) source static LOCAL-LAN LOCAL-LAN destination static REMOTE-LAN REMOTE-LAN no-proxy-arp route-lookup
no crypto ipsec ikev2 ipsec-proposal AES256-SHA256
no crypto ikev2 enable outside
no crypto ikev2 policy 10
no access-list VPN-TO-SITEB extended permit ip 10.10.10.0 255.255.255.0 10.20.20.0 255.255.255.0
Leave the object network definitions if anything else references them. If you saved with write memory and want to abandon everything, restoring disk0:/pre-vpn-backup.cfg merges rather than replaces on the ASA, so negating the commands above is the cleaner path.
For exact per-version syntax and the current recommended crypto parameters, check Cisco's own ASA configuration guides on cisco.com — search for the "ASA Series VPN CLI Configuration Guide" matching your software version, since defaults and supported DH groups do shift between releases.
Runs enterprise networks and security for a living, and writes Shore Up to turn two decades of hands-on Linux, Windows and mail-server work into guides you can actually use.
More about the author →Was this article helpful?
Tap a star — no sign-in needed.
Be the first to rate this article.
Related guides
Set Up a Site-to-Site IPsec VPN on a Palo Alto Firewall
This guide builds a route-based site-to-site IPsec VPN on a Palo Alto firewall: an encrypted tunnel between your firewall and a remote peer so two private subnets can talk over the public internet. You configure it entirely as candidate configuration in the web GUI and make it live with a Commit .
Set Up a Site-to-Site VPN Community on Check Point (R81.20)
This guide builds a site-to-site IPsec VPN community in Check Point SmartConsole so traffic between two sites' encryption domains is tunnelled and encrypted. The main path assumes both peers are Check Point gateways managed by the same Management Server (SMS) on R81.20 ; I note where a third-party peer (an Interoperable Device ) differs.
Configure a Site-to-Site VPN on a SonicWall (SonicOS 7)
This guide builds an IPsec site-to-site VPN between two SonicWall firewalls (or a SonicWall and a compatible third-party peer) so two private subnets can route to each other over the public internet. It changes live firewall configuration: it adds a VPN policy, address objects, and — automatically — access rules that permit traffic between the two networks. Getting the phase 1/phase 2 parameters or the local/remote networks wrong can break routing or expose a subnet you didn't intend to.
Route-Based Site-to-Site IPsec VPN Between Two FortiGates
This guide builds a route-based IPsec tunnel between two FortiGate firewalls so the LAN behind Site A can reach the LAN behind Site B and vice versa. "Route-based" means each end gets a virtual tunnel interface, and you steer traffic into the tunnel with a static route plus firewall policies — the mainstream FortiOS approach for a permanent office-to-office link.




