# Policy-Based IPsec VPN to Cisco ASA

> Policy-Based IPsec VPN between VyOS and Cisco ASA - IKEv1/IKEv2 config, crypto maps, and traffic selectors for cloud deployments

Source: https://opennix.org/en/docs/vyos/examples/vpn-cisco/


Policy-Based IPsec VPN lets you establish a Site-to-Site tunnel between VyOS and a Cisco ASA firewall, providing secure connectivity between remote locations or hybrid cloud deployments.

## Use Case

### Applicability

- **Hybrid Cloud**: Yandex Cloud / VK Cloud ↔ On-premises Cisco ASA
- **Branch Office**: Headquarters (Cisco ASA) ↔ Remote branches (VyOS)
- **Multi-Cloud**: Yandex Cloud (VyOS) ↔ another cloud provider
- **Legacy Integration**: Integration with existing Cisco infrastructure

### Benefits of Policy-Based VPN

1. **Wide Compatibility**: Support for legacy Cisco devices
2. **Granular Control**: Traffic selection by subnet pairs
3. **Simple Configuration**: Easier than Route-Based for simple scenarios
4. **NAT Traversal**: Works behind NAT

## Network Topology

### Basic Topology

```
┌────────────────────────────────────────────────┐
│  On-Premises Datacenter                        │
│                                                │
│  ┌──────────────────┐                          │
│  │  Cisco ASA 5516  │                          │
│  │  Outside: 203.0.113.1/30                    │
│  │  Inside: 192.168.1.1/24                     │
│  └──────────┬───────┘                          │
│             │                                  │
│         LAN │ 192.168.1.0/24                   │
│   ┌─────────┴──────────┐                       │
│   │ Servers, Workstations│                     │
│   └────────────────────┘                       │
└────────────────────────────────────────────────┘
                │
                │ Internet
                │ IPsec Tunnel
                │
┌────────────────────────────────────────────────┐
│  Yandex Cloud / VK Cloud                       │
│                                                │
│  ┌──────────────────┐                          │
│  │  VyOS Gateway    │                          │
│  │  eth0: 198.51.100.1/30 (public)            │
│  │  eth1: 10.10.1.1/24 (private)              │
│  └──────────┬───────┘                          │
│             │                                  │
│         VPC │ 10.10.1.0/24                     │
│   ┌─────────┴──────────┐                       │
│   │ Cloud VMs          │                       │
│   └────────────────────┘                       │
└────────────────────────────────────────────────┘
```

### VPN Parameters

| Parameter | Value |
|-----------|-------|
| VPN Type | Policy-Based IPsec |
| IKE Version | IKEv2 |
| Phase 1 Encryption | AES-256 |
| Phase 1 Hash | SHA-256 |
| Phase 1 DH Group | 14 (2048-bit) |
| Phase 2 Encryption | AES-256 |
| Phase 2 Hash | SHA-256 |
| Phase 2 PFS | DH Group 14 |
| Authentication | Pre-Shared Key |

## Requirements

### VyOS Requirements

- VyOS 1.4 (Sagitta) or newer
- Public IP address (elastic IP in the cloud)
- IPsec support (strongSwan)

### Cisco ASA Requirements

- Cisco ASA 5500-X, ASA 5506-X or newer
- ASA Software 9.x or newer
- Public IP address
- IKEv2 support

### Network Requirements

- UDP 500 (IKE) open on both firewalls
- UDP 4500 (NAT-T) if behind NAT
- ESP (IP protocol 50) allowed
- MTU awareness (1400 recommended for the tunnel)

## VyOS Configuration

### IKE Group (Phase 1)

```bash
configure

# IKE Group
set vpn ipsec ike-group IKE-CISCO lifetime '28800'
set vpn ipsec ike-group IKE-CISCO key-exchange 'ikev2'
set vpn ipsec ike-group IKE-CISCO proposal 1 encryption 'aes256'
set vpn ipsec ike-group IKE-CISCO proposal 1 hash 'sha256'
set vpn ipsec ike-group IKE-CISCO proposal 1 dh-group '14'

commit
```

### ESP Group (Phase 2)

```bash
configure

# ESP Group
set vpn ipsec esp-group ESP-CISCO lifetime '3600'
set vpn ipsec esp-group ESP-CISCO mode 'tunnel'
set vpn ipsec esp-group ESP-CISCO pfs 'dh-group14'
set vpn ipsec esp-group ESP-CISCO proposal 1 encryption 'aes256'
set vpn ipsec esp-group ESP-CISCO proposal 1 hash 'sha256'
set vpn ipsec esp-group ESP-CISCO compression 'disable'

commit
```

### Site-to-Site Peer

```bash
configure

# Peer (Cisco ASA public IP)
set vpn ipsec site-to-site peer 203.0.113.1 authentication mode 'pre-shared-secret'
set vpn ipsec site-to-site peer 203.0.113.1 authentication pre-shared-secret 'YourStrongPreSharedKey123!'
set vpn ipsec site-to-site peer 203.0.113.1 ike-group 'IKE-CISCO'
set vpn ipsec site-to-site peer 203.0.113.1 local-address '198.51.100.1'

# Tunnel definition (Policy-Based)
set vpn ipsec site-to-site peer 203.0.113.1 tunnel 1 esp-group 'ESP-CISCO'
set vpn ipsec site-to-site peer 203.0.113.1 tunnel 1 local prefix '10.10.1.0/24'
set vpn ipsec site-to-site peer 203.0.113.1 tunnel 1 remote prefix '192.168.1.0/24'

commit
save
```

### NAT Exclusion

```bash
configure

# Exclude VPN traffic from NAT (if Source NAT is used)
set nat source rule 100 description 'Exclude VPN traffic from NAT'
set nat source rule 100 destination address '192.168.1.0/24'
set nat source rule 100 source address '10.10.1.0/24'
set nat source rule 100 exclude

# Source NAT for the rest of Internet traffic
set nat source rule 200 description 'NAT for Internet'
set nat source rule 200 outbound-interface name 'eth0'
set nat source rule 200 source address '10.10.1.0/24'
set nat source rule 200 translation address 'masquerade'

commit
save
```

### Firewall Rules

```bash
configure

# Firewall for the WAN interface (allow IPsec)
set firewall ipv4-name WAN_LOCAL default-action 'drop'

# Allow established/related
set firewall ipv4-name WAN_LOCAL rule 1 action 'accept'
set firewall ipv4-name WAN_LOCAL rule 1 state established 'enable'
set firewall ipv4-name WAN_LOCAL rule 1 state related 'enable'

# Allow IKE (UDP 500)
set firewall ipv4-name WAN_LOCAL rule 10 action 'accept'
set firewall ipv4-name WAN_LOCAL rule 10 protocol 'udp'
set firewall ipv4-name WAN_LOCAL rule 10 destination port '500'
set firewall ipv4-name WAN_LOCAL rule 10 description 'Allow IKE'

# Allow NAT-T (UDP 4500)
set firewall ipv4-name WAN_LOCAL rule 20 action 'accept'
set firewall ipv4-name WAN_LOCAL rule 20 protocol 'udp'
set firewall ipv4-name WAN_LOCAL rule 20 destination port '4500'
set firewall ipv4-name WAN_LOCAL rule 20 description 'Allow NAT-T'

# Allow ESP (protocol 50)
set firewall ipv4-name WAN_LOCAL rule 30 action 'accept'
set firewall ipv4-name WAN_LOCAL rule 30 protocol 'esp'
set firewall ipv4-name WAN_LOCAL rule 30 description 'Allow ESP'

# Apply to interface
set firewall interface eth0 in name 'WAN_LOCAL'

commit
save
```

## Cisco ASA Configuration

### IKEv2 Policy

```cisco
! IKEv2 Policy
crypto ikev2 policy 10
 encryption aes-256
 integrity sha256
 group 14
 prf sha256
 lifetime seconds 28800
!
```

### IKEv2 Proposal

```cisco
! IPsec (ESP) Proposal
crypto ipsec ikev2 ipsec-proposal ESP-VYOS
 protocol esp encryption aes-256
 protocol esp integrity sha-256
!
```

### Tunnel Group

```cisco
! Tunnel Group (VyOS peer)
tunnel-group 198.51.100.1 type ipsec-l2l
tunnel-group 198.51.100.1 ipsec-attributes
 ikev2 remote-authentication pre-shared-key YourStrongPreSharedKey123!
 ikev2 local-authentication pre-shared-key YourStrongPreSharedKey123!
!
```

### Crypto Map

```cisco
! Access-list for interesting traffic
access-list VPN-TO-VYOS extended permit ip 192.168.1.0 255.255.255.0 10.10.1.0 255.255.255.0

! Crypto Map
crypto map OUTSIDE-MAP 10 match address VPN-TO-VYOS
crypto map OUTSIDE-MAP 10 set peer 198.51.100.1
crypto map OUTSIDE-MAP 10 set ikev2 ipsec-proposal ESP-VYOS
crypto map OUTSIDE-MAP 10 set pfs group14
crypto map OUTSIDE-MAP 10 set security-association lifetime seconds 3600

! Apply to outside interface
crypto map OUTSIDE-MAP interface outside
!
```

### NAT Exemption (Cisco ASA)

```cisco
! NAT exemption for VPN traffic
nat (inside,outside) source static OBJ-LAN-192.168.1.0 OBJ-LAN-192.168.1.0 destination static OBJ-VYOS-10.10.1.0 OBJ-VYOS-10.10.1.0 no-proxy-arp route-lookup

! Network Objects
object network OBJ-LAN-192.168.1.0
 subnet 192.168.1.0 255.255.255.0

object network OBJ-VYOS-10.10.1.0
 subnet 10.10.1.0 255.255.255.0
!
```

### Routes

```cisco
! Static route for the VyOS subnet (optional, if dynamic routing is not used)
route outside 10.10.1.0 255.255.255.0 198.51.100.1
!
```

## Integration with Yandex Cloud

### Scenario: VyOS in Yandex Cloud as a VPN Gateway

```bash
configure

# Yandex Cloud specifics
# eth0 = external interface (public IP via 1:1 NAT)
# eth1 = internal interface (VPC subnet)

# Interfaces
set interfaces ethernet eth0 address '10.128.0.5/24'
set interfaces ethernet eth0 description 'Yandex Cloud external (NAT to public IP)'

set interfaces ethernet eth1 address '10.10.1.1/24'
set interfaces ethernet eth1 description 'Yandex Cloud VPC subnet'

# IPsec configuration
# local-address = internal IP (Yandex Cloud will NAT it to the public IP)
set vpn ipsec site-to-site peer 203.0.113.1 local-address '10.128.0.5'

# NAT exclusion (important for Yandex Cloud)
set nat source rule 100 destination address '192.168.1.0/24'
set nat source rule 100 source address '10.10.1.0/24'
set nat source rule 100 exclude

# Routes (optional)
set protocols static route 192.168.1.0/24 next-hop '203.0.113.1' distance '10'

commit
save
```

### Yandex Cloud Security Group

In the Yandex Cloud Console, create a Security Group for VyOS:

**Ingress Rules**:
- UDP 500 from Cisco ASA IP (203.0.113.1)
- UDP 4500 from Cisco ASA IP (203.0.113.1)
- ESP (protocol 50) from Cisco ASA IP (203.0.113.1)

**Egress Rules**:
- UDP 500 to Cisco ASA IP
- UDP 4500 to Cisco ASA IP
- ESP (protocol 50) to Cisco ASA IP

## Integration with VK Cloud

### Configuration for VK Cloud

```bash
configure

# VK Cloud is similar to Yandex Cloud
# eth0 = management (internal IP, NAT to Floating IP)
# eth1 = VPC subnet

set interfaces ethernet eth0 address '10.0.1.5/24'
set interfaces ethernet eth0 description 'VK Cloud external (NAT to Floating IP)'

set interfaces ethernet eth1 address '10.10.1.1/24'
set interfaces ethernet eth1 description 'VK Cloud VPC subnet'

# IPsec local-address = internal IP
set vpn ipsec site-to-site peer 203.0.113.1 local-address '10.0.1.5'

# MTU for the VK Cloud overlay
set interfaces ethernet eth0 mtu '1450'
set interfaces ethernet eth1 mtu '1450'

# MSS clamping for TCP
set firewall interface eth0 in ipv4-adjust-mss '1360'
set firewall interface eth0 out ipv4-adjust-mss '1360'

commit
save
```

### VK Cloud Security Groups

Similar to Yandex Cloud, create a Security Group:
- Allow UDP 500, 4500 and ESP from the Cisco ASA IP

## Configuration Verification

### VyOS - IPsec Verification

```bash
# IPsec status
show vpn ipsec status

# Expected output:
# IPsec Process Running: yes
# IKE SAs: 1 established
# IPsec SAs: 1 established

# IPsec SA details
show vpn ipsec sa

# Should show:
# Peer: 203.0.113.1
# State: up
# Tunnels: 1 active
# Local subnet: 10.10.1.0/24
# Remote subnet: 192.168.1.0/24

# IKE SA
show vpn ike sa

# Security Associations
show vpn ipsec sa detail
```

### VyOS - Traffic Verification

```bash
# Ping through the tunnel (from VyOS to Cisco ASA inside)
ping 192.168.1.1 count 4

# Traceroute
traceroute 192.168.1.1

# IPsec statistics
show vpn ipsec sa statistics

# Bytes in/out should be increasing
```

### Cisco ASA - Verification

```cisco
! IPsec status
show crypto ikev2 sa

! Output:
! IKEv2 SAs:
! Session-id:1, Status:UP-ACTIVE, IKE count:1, CHILD count:1

! IPsec SA
show crypto ipsec sa peer 198.51.100.1

! Output:
! interface: outside
! Crypto map tag: OUTSIDE-MAP, seq num: 10, local addr: 203.0.113.1
! access-list VPN-TO-VYOS extended permit ip 192.168.1.0 255.255.255.0 10.10.1.0 255.255.255.0
! local ident (addr/mask/prot/port): (192.168.1.0/255.255.255.0/0/0)
! remote ident (addr/mask/prot/port): (10.10.1.0/255.255.255.0/0/0)
! current_peer: 198.51.100.1
! #pkts encaps: 150, #pkts encrypt: 150, #pkts digest: 150
! #pkts decaps: 140, #pkts decrypt: 140, #pkts verify: 140

! Ping from ASA to VyOS inside
ping 10.10.1.1
```

### Debugging

**VyOS**:
```bash
# Enable IPsec debugging
sudo swanctl --log

# Live IPsec logs
sudo journalctl -u strongswan -f

# IKE negotiation details
sudo ipsec statusall
```

**Cisco ASA**:
```cisco
! Debug IKEv2
debug crypto ikev2 platform 127
debug crypto ikev2 protocol 127

! Debug IPsec
debug crypto ipsec 127

! Clear and re-establish the tunnel (for testing)
clear crypto ikev2 sa
clear crypto ipsec sa peer 198.51.100.1
```

## Troubleshooting

### Issue 1: IKE Phase 1 does not establish

**Symptoms**:
```bash
show vpn ike sa
# Empty, no SA
```

**Causes and solutions**:

1. **Pre-Shared Key mismatch**:
   ```bash
   # VyOS - check the PSK
   show configuration commands | grep pre-shared-secret

   # Cisco ASA - check
   show running-config tunnel-group 198.51.100.1
   ```

2. **Firewall blocks UDP 500**:
   ```bash
   # VyOS - check the firewall
   show firewall ipv4-name WAN_LOCAL

   # Cisco ASA - check ACL
   show access-list outside_access_in
   ```

3. **Crypto parameters mismatch**:
   ```bash
   # VyOS - show IKE parameters
   show vpn ipsec ike-group IKE-CISCO

   # Cisco ASA
   show running-config crypto ikev2 policy
   ```

### Issue 2: Phase 1 OK, but Phase 2 (IPsec SA) does not establish

**Symptoms**:
```bash
show vpn ike sa  # Shows SA
show vpn ipsec sa  # Empty
```

**Causes**:

1. **ESP parameters mismatch**:
   ```bash
   # VyOS
   show vpn ipsec esp-group ESP-CISCO

   # Cisco ASA
   show running-config crypto ipsec ikev2 ipsec-proposal
   ```

2. **Traffic selectors mismatch**:
   ```bash
   # VyOS - check local/remote prefix
   show configuration commands | grep "tunnel 1"

   # Must match the Cisco ACL
   # Cisco ASA
   show access-list VPN-TO-VYOS
   ```

### Issue 3: Tunnel UP, but no connectivity

**Symptoms**:
```bash
show vpn ipsec sa  # State: up
ping 192.168.1.1  # Network unreachable
```

**Causes and solutions**:

1. **NAT is not excluded**:
   ```bash
   # VyOS - check NAT rules
   show nat source rules

   # There must be an exclude rule for VPN traffic
   # Add it
   set nat source rule 100 source address '10.10.1.0/24'
   set nat source rule 100 destination address '192.168.1.0/24'
   set nat source rule 100 exclude
   commit
   ```

2. **No route**:
   ```bash
   # VyOS - check routing
   show ip route 192.168.1.0/24

   # There must be a route through the VPN
   # If missing, a policy-based VPN should create it automatically

   # Cisco ASA - check routes
   show route
   ```

3. **Firewall blocks VPN traffic**:
   ```bash
   # VyOS - create a zone for the VPN
   set firewall zone VPN interface 'eth1'
   set firewall zone WAN interface 'eth0'
   set firewall zone VPN from WAN firewall name 'VPN-IN'

   # Allow traffic from the VPN zone
   set firewall ipv4-name VPN-IN default-action 'accept'
   commit
   ```

### Issue 4: Tunnel flapping (up/down)

**Causes**:

1. **DPD (Dead Peer Detection) too aggressive**:
   ```bash
   # VyOS - increase the DPD timeout
   set vpn ipsec site-to-site peer 203.0.113.1 connection-type 'respond'
   set vpn ipsec site-to-site peer 203.0.113.1 dpd action 'restart'
   set vpn ipsec site-to-site peer 203.0.113.1 dpd interval '30'
   set vpn ipsec site-to-site peer 203.0.113.1 dpd timeout '120'
   commit
   ```

2. **Keepalive traffic**:
   ```bash
   # Periodically send ICMP through the tunnel
   # Cron job for keepalive ping
   set system task-scheduler task vpn-keepalive executable path '/usr/bin/ping'
   set system task-scheduler task vpn-keepalive executable arguments '-c 1 192.168.1.1'
   set system task-scheduler task vpn-keepalive interval '60'
   commit
   ```

## Best Practices

### 1. Crypto Parameters

**Recommended**:
- IKE: AES-256, SHA-256, DH Group 14+
- ESP: AES-256, SHA-256, PFS Group 14+
- Lifetime: IKE 8h, IPsec 1h

### 2. NAT Considerations

```bash
# Always exclude VPN traffic from NAT
set nat source rule 100 exclude

# MSS clamping for TCP over VPN
set firewall interface eth0 in ipv4-adjust-mss '1360'
```

### 3. Firewall Security

```bash
# Restrict IKE to the Cisco peer only
set firewall ipv4-name WAN_LOCAL rule 10 source address '203.0.113.1'

# Rate limiting for IKE
set firewall ipv4-name WAN_LOCAL rule 10 recent count '10'
set firewall ipv4-name WAN_LOCAL rule 10 recent time 'minute'
```

### 4. Monitoring

```bash
# Monitor VPN status
watch -n 5 'show vpn ipsec sa'

# Log IPsec events
set system syslog global facility all level 'info'

# Alert on tunnel failure (custom script)
set system task-scheduler task check-vpn executable path '/config/scripts/check-vpn.sh'
set system task-scheduler task check-vpn interval '300'
```

### 5. Redundancy

For production, a redundant VPN is recommended:

```bash
# Secondary peer (a second Cisco ASA or a second VyOS)
set vpn ipsec site-to-site peer 203.0.113.2 ...

# Adjust the metric for failover
set protocols static route 192.168.1.0/24 next-hop 203.0.113.2 distance '20'
```

## References

- [VyOS IPsec Configuration](https://docs.vyos.io/en/latest/configuration/vpn/ipsec.html)
- [Cisco ASA VPN Configuration Guide](https://www.cisco.com/c/en/us/support/security/asa-5500-series-next-generation-firewalls/products-installation-and-configuration-guides-list.html)
- [RFC 7296 - IKEv2](https://datatracker.ietf.org/doc/html/rfc7296)
- [RFC 4301 - IPsec Architecture](https://datatracker.ietf.org/doc/html/rfc4301)
- [Yandex Cloud VPN](https://cloud.yandex.ru/docs/vpc/concepts/vpn)
- [VK Cloud VPN](https://mcs.mail.ru/docs/networks/vnet/vpn)

