Mac OS X IPSec to WRV54G

A shell script to allow Mac users to make a VPN connection to Linksys WRV54G home VPN routers.


Download 

  •  Works with Mac OS X
  • Makes IPSec VPN connection to Linksys WRV54G home wifi router  
  • Runs in command line / terminal mode 
  • 4/16/07 - Updated to improve status output, improved hostname parsing, added verbosity control 

Linksys does not have a Mac OS X VPN client available for their WRV54G wireless router.  The WRV54G uses standard IPSec, but uses a proprietary authentication mechanism to negotiate "pre-shared keys".  To get around this problem, I hacked together a shell script, which performs the SSL authentication, creates the IPSec configuration, and establishes the session.  This is all done from a shell script in the terminal, not a GUI.  But, it works pretty well, and gives Mac users a way to use their WRV54G's full potential.

Usage Info:

  • To use the script, you must first edit it to add your user and network settings.  These include: VPN user-id, password, hostname or IP address of gateway, address and netmask of protected network. 
  • script must be run as admin, "sudo wrvinit.sh".   This is required because the IPsec session negotiation program, "racoon", requires root privileges to set up the networking.
  • It runs in verbose mode, so it spits out a lot of IPSec information when it's running.  Hopefully this can be ignored, or can be used to debug connection problems. 
  • The script runs independently of Mac OS's VPN configuration.   The Mac OS VPN client should be disabled, otherwise it conflicts and racoon can't bind to the necessary IKE port (UDP/500). 
  • The Mac IPSec doesn't use virtual adapters,  it just routes packets through the VPN tunnel (or not) based on the address of the destination / protected network configured in the script.   This can make it a bit difficult to tell when the IPSec tunnel is up and working.  The racoon status messages shown below are a good indicator, but pinging or otherwise connecting to a machine on the protected network is a more definitive way.
  • It currently only works on Mac OS X, but could easily be modified to work in Linux or other Unix OS's.  It uses the command "ipconfig" to get the status and address of the network interfaces.   This would need to be modified to use ifconfig, or another available Linux/Unix command. 

Where to find config parameters on your router: 

 

 

 

 

 

 

 

 

 

 

 

 

Possible 'gotchas':

  • Make sure the network you're connecting from allows IPSec and IKE packets to pass.  This can be a bit difficult to verify, some ways I use are: enable syslog logging on the router and see that the connection attemtpts are logged, use tcpdump on your Mac and verify that response packets are coming from the WRV54G.
  • Make sure the source network you're on is in a different IP subnet than the destination network.  This is especially important if you use common/default networks like 192.168.1.0, 192.168.0.0, 10.1.1.0, 10.10.10.0, etc.   If you are using the same network on both ends, your system can't tell whether you're trying to connect to a local machine or through the VPN.  If possible, use an unusual subnet for your local LAN configuration to minimize conflicts, e.g. 10.119.137.0
  • Verify that the SSL authentication session is actually working.  Even an incorrect password will return a session key (otherwise, an attacker could do a brute-force password scan).  Verify that the user's status is active in the WRV54G's web UI. 
  • Make sure your Mac's VPN settings are turned off.  If the Mac OS IPsec is enabled, it will prevent ths script from setting up the session.  The script uses the same infrastructure as Mac OS IPSec (or other VPN tools, like IPSecuritas and VPN Tracker),  only one can be running and setting up sessions.   The error message will be something like "isakmp_setup_socket(): failed to bind (Address already in use)", meaning that the MacOS IPSec is already claiming UDP port 500.

Sample output from an IPSec connection:

 sudo wrvinit.sh
Password:
en0:
Using the wireless ethernet, en1.  Local Address: 192.168.2.4
Foreground mode.
2006-04-22 10:34:11: INFO: main.c:176:main(): @(#)racoon 20001216 20001216 sakane@kame.net
2006-04-22 10:34:11: INFO: main.c:177:main(): @(#)This product linked OpenSSL 0.9.7i 14 Oct 2005 (http://www.openssl.org/)
2006-04-22 10:34:11: DEBUG: pfkey.c:371:pfkey_init(): call pfkey_send_register for AH
2006-04-22 10:34:11: DEBUG: pfkey.c:371:pfkey_init(): call pfkey_send_register for ESP
2006-04-22 10:34:11: DEBUG: pfkey.c:371:pfkey_init(): call pfkey_send_register for IPCOMP
2006-04-22 10:34:11: DEBUG: cftoken.l:567:yycf_set_buffer(): reading config file /etc/racoon/wrv_racoon.conf
2006-04-22 10:34:11: DEBUG: pfkey.c:2292:pk_checkalg(): compression algorithm can not be checked because sadb message doesn't support it.
2006-04-22 10:34:11: DEBUG: isakmp.c:1611:isakmp_open(): 192.168.2.4[500] used as isakmp port (fd=7)
2006-04-22 10:34:11: DEBUG: isakmp.c:1629:isakmp_open(): 192.168.2.4[4500] used as nat-t isakmp port (fd=8)
2006-04-22 10:34:11: DEBUG: pfkey.c:195:pfkey_handler(): get pfkey X_SPDDUMP message
2006-04-22 10:34:11: DEBUG: pfkey.c:195:pfkey_handler(): get pfkey X_SPDDUMP message
2006-04-22 10:34:11: DEBUG: policy.c:184:cmpspidxstrict(): sub:0xbffff880: 10.10.10.0/24[0] 192.168.2.4/32[0] proto=any dir=in
2006-04-22 10:34:11: DEBUG: policy.c:185:cmpspidxstrict(): db :0x3068f8: 10.10.10.0/24[0] 10.10.10.164/32[0] proto=any dir=in

(snip) 

2006-04-22 10:35:23: DEBUG: pfkey.c:195:pfkey_handler(): get pfkey ACQUIRE message
2006-04-22 10:35:23: DEBUG: pfkey.c:1567:pk_recvacquire(): suitable outbound SP found: 192.168.2.4/32[0] 10.10.10.0/24[0] proto=any dir=out.
2006-04-22 10:35:23: DEBUG: policy.c:184:cmpspidxstrict(): sub:0xbffff870: 10.10.10.0/24[0] 192.168.2.4/32[0] proto=any dir=in
2006-04-22 10:35:23: DEBUG: policy.c:185:cmpspidxstrict(): db :0x3068f8: 10.10.10.0/24[0] 10.10.10.164/32[0] proto=any dir=in
2006-04-22 10:35:23: DEBUG: policy.c:184:cmpspidxstrict(): sub:0xbffff870: 10.10.10.0/24[0] 192.168.2.4/32[0] proto=any dir=in
2006-04-22 10:35:23: DEBUG: policy.c:185:cmpspidxstrict(): db :0x306b38: 10.10.10.0/24[0] 192.168.2.4/32[0] proto=any dir=in
2006-04-22 10:35:23: DEBUG: pfkey.c:1583:pk_recvacquire(): suitable inbound SP found: 10.10.10.0/24[0] 192.168.2.4/32[0] proto=any dir=in.
2006-04-22 10:35:23: DEBUG: pfkey.c:1622:pk_recvacquire(): new acquire 192.168.2.4/32[0] 10.10.10.0/24[0] proto=any dir=out
2006-04-22 10:35:23: DEBUG: proposal.c:826:printsaproto():  (proto_id=ESP spisize=4 spi=00000000 spi_p=00000000 encmode=Tunnel reqid=0:0)

(snip)

 2006-04-22 10:35:26: DEBUG: isakmp_quick.c:700:quick_i2send(): pfkey update sent.
2006-04-22 10:35:26: DEBUG: algorithm.c:509:alg_ipsec_encdef(): encription(3des)
2006-04-22 10:35:26: DEBUG: algorithm.c:552:alg_ipsec_hmacdef(): hmac(hmac_md5)
2006-04-22 10:35:26: DEBUG: pfkey.c:1260:pk_sendadd(): call pfkey_send_add
pfkey_setsadbsa2: flags = 0x0, port = 0.
2006-04-22 10:35:26: DEBUG: isakmp_quick.c:707:quick_i2send(): pfkey add sent.
2006-04-22 10:35:26: DEBUG: pfkey.c:195:pfkey_handler(): get pfkey UPDATE message
2006-04-22 10:35:26: DEBUG: pfkey.c:1131:pk_recvupdate(): pfkey UPDATE succeeded: ESP/Tunnel 24.2.249.9->192.168.2.4 spi=163989178(0x9c646ba)
2006-04-22 10:35:26: INFO: pfkey.c:1138:pk_recvupdate(): IPsec-SA established: ESP/Tunnel 24.2.249.9->192.168.2.4 spi=163989178(0x9c646ba)
2006-04-22 10:35:26: DEBUG: pfkey.c:1176:pk_recvupdate(): ===
2006-04-22 10:35:26: DEBUG: pfkey.c:195:pfkey_handler(): get pfkey ADD message
2006-04-22 10:35:26: INFO: pfkey.c:1367:pk_recvadd(): IPsec-SA established: ESP/Tunnel 192.168.2.4->24.2.249.9 spi=2721984434(0xa23e2fb2)
2006-04-22 10:35:26: DEBUG: pfkey.c:1372:pk_recvadd(): ===

---------

The initial connection attempt will generate a bunch of messages.  Then, when you attempt to connect to a protected resource, it will continue the negotiation process.  The "IPSec-SA established" at the tail end is when the phase 2 negotiation completes, and IPSec is fully up.  At that point, you should be able to access resources on the protected network.