Cisco 7940 HTTP File Error, Cookies and Laravel

The legacy 7940’s have not had SCCP firmware released in a good number of years, and recently I’ve come across a bug in latest version.

When running a custom XML service hosted on an external webserver, such as a weather script or similar, the phone will display HTTP File Error if you push any cookie to it.

In my specific scenario my Laravel 5.3 was returning both a laravel_session and a XSRF-TOKEN cookie for every HTTP GET. Every time the phone would request the service with these cookies would be returned and the phone would display the error. Interestingly, newer model phones like the 8945 and 9951’s don’t have an issue at all.

These cookies are very much needed for modern web security, however for a simple XML page, these are definitely not needed. There are provisions built into Laravel 5 for disabling CSRF protection in the VerifyCsrfToken middleware, however, these only stop the verification of CSRF tokens, not the setting of the XSRF token – as can be seen here:

After a lot of trial and error manipulating different parts of the middlewear kernel, routegroups, drivers etc, I’ve settled on this modification to the VerifyCsrfToken middlewear. This modification now means that any request that matches the URI defined in the $except array is excepted from CSRF checks, does not set the laravel_session cookie nor the XSRF-TOKEN cookie. Anything that does not match the URI gets the XSRF-TOKEN generated and continues with the default driver, meaning that the laravel_sesison cookie gets built. The only thing that I do not like about this method is that I had to copy the Cookie() functionality from addCookieToResponse from the original VerifyCsrfToken in vendor/laravel/framework/scr/Illuminate/Foundation/Http/Middlewear. This carries the possibility that the logic behind creating the cookie will be changed in the future and that my function won’t be up to date – but for now it works well. Below is my VerifyCsrfToken code.


namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Cookie;
use Carbon\Carbon;

class VerifyCsrfToken extends BaseVerifier
     * The URIs that should be excluded from CSRF verification.
     * @var array
    protected $except = [

    protected function addCookieToResponse($request, $response)
        $config = config('session');

        foreach ($this->except as $except) {
            if (Str::is($except, $request->path())) {
                \Config::set('session.driver', 'array');
                return $response;
            } else {
                    new Cookie(
                        'XSRF-TOKEN', $request->session()->token(), Carbon::now()->getTimestamp() + 60 * $config['lifetime'],
                        $config['path'], $config['domain'], $config['secure'], false
                return $response;

If anyone knows of a better way to include the cookie generation inside of the middlewear hit me up! For reference these links provided lots of insight.


Windows 10 KB3163018 Breaks CCM 9.0.1 SSL

After installing the Windows 10 KB3163018 update, you are no longer able to load Call Manager 9.0.1 web interfaces that use a self signed certificate.

There’s a bit of talk on the KB here:

And similar issues here for Viewmail on 11.5 –

I haven’t been able to check whether this is resolved with a properly signed certificate, or whether it’s a limitation in the tomcat library.

Interestingly it doesn’t impact 7.1.5 clusters. I will check against 11.0.1 shortly.

UPDATE: 11.0.1 works fine, just the usual self signed certificate warning.

Easy Cisco NAT Pools and VRF’s

I’ve been struggling to find a quick and dirty guide to use NAT Pool Overloads between two VRF’s. A lot of the guides I came across either had RDs, BGP or NATting into the global VRF table. All I wanted was to have Red talk to Blue by NATting the Red network to a NAT Pool which is routeable by Blue. In my scenario I would have an internet connection in a WWW VRF and my internal servers in a 10 VRF. I guess you could argue why to even use VRF’s in this case as there is no benefit in this specific example, but anyway. So here we go.

Build our VRF

ip vrf 10
ip vrf WWW

Configure the interfaces with IP’s in the right VRF

interface FastEthernet0/0
description Internet
ip vrf forwarding WWW
ip address
ip nat enable
duplex auto
speed auto

interface FastEthernet1/0
description Servers
ip vrf forwarding 10
ip address
ip nat enable
duplex auto
speed auto

Add a default route into the 10 VRF, exiting the Fa0/0 interface which will mark it in the WWW VRF and aim for a next hop of

ip route vrf 10 FastEthernet0/0

Allow our host to use the NAT Pool.

ip access-list extended NAT
permit ip any

Make sure to specify the add-route to the back of your NAT Pool, otherwise when the return traffic comes back it will be dropped as there is no subnet in the WWW VRF.

ip nat pool Global netmask add-route

Overload your NAT Pool in the 10 VRF.

ip nat source list NAT pool Global vrf 10 overload



NOTE: This only works in IOS, not IOS XE

DMVPN Tunnel Source Failover

Off the back of my last post about failing over outbound access using IP SLA and route-maps here I needed to also accommodate DMVPN tunnels in this process.

The issue that I ran into was that in a DMVPN spoke tunnel we specify the tunnel source <interface> manually. When were failing over between two providers obviously our interface will change rendering our tunnel useless.

I tried a few different workaround such as a duplicate tunnel to the same DMVPN hub and a new tunnel to a new DMVPN hub but due to my environment with one telco at the DMVPN hub end I couldn’t pass traffic. I didn’t dive too deeply into why, but I suspect that it was due to ipsec not being able to identify the correct source traffic as we were sharing interfaces and profiles.

There is a tunnel source dynamic command that Cisco support but I could only find documentation regarding this and routing protocols – again not something that I could run in my environment.

In order to solve this, I threw in a simple EEM script. EEM scripts will take inputs from router events and execute actions that you define.

I put together an EEM script that was triggered on the ip sla event and that actually typed out the commands to change the tunnel source interface. See below.

event manager applet change_dmvpn_source_down
event track 1 state down
action 1.0 cli command “enable”
action 1.5 cli command “config t”
action 2.0 cli command “interface tun0”
action 2.5 cli command “tunnel source gi0/2”
action 3.0 cli command “end”

event manager applet change_dmvpn_source_up
event track 1 state up
action 1.0 cli command “enable”
action 1.5 cli command “config t”
action 2.0 cli command “interface tun0”
action 2.5 cli command “tunnel source gi0/0”
action 3.0 cli command “end”

EEM always seems a little crude to me, but in these types of scenarios when you are pigeon-holed on technology and need a quick fix it works quite well.

Easy Cisco IOS Dual WAN Failover – IP SLA, NAT, Route Maps

I was looking for a solution of providing WAN failover to a site using two ISP’s with unique NAT pools whilst avoiding BGP. Obviously BGP solves all of these issues that were using IP SLA and route-maps for, but the stipulation was without a routing protocol. For whatever reason I couldn’t find a nice example so here’s an easy to follow config that I knocked up as a POC. If you want to replicate this in GNS drop in the below config on a 3725 platform and create Telco routers for each Telco with the /30 WAN addressing and a static route for and

As an overview:

  • We want to preference Telco 1. Telco 2 should only be used if Telco 1 goes down.
  • Telco 1 has a WAN of They statically route a prefix of to us which we will use for NAT overload. If the Telco didn’t route us a prefix though we could just overload the WAN interface.
  • Telco 2 has a WAN of They statically route a prefix of to us which we will use for NAT overload. If the Telco didn’t route us a prefix though we could just overload the WAN interface.

We will create a track with IP SLA to track Telco 1’s WAN address. This could be any routable IP in their network though. We set a default route to this Telco with the track. We set another default route to Telco 2 with a higher AD. This takes care of our default route movements should Telco 1 go down.

We create two route-maps one for each Telco. We match an ACL with our inside IP’s on our network. If you’re not worried about selectively providing NAT pool access, you can ommit the ACL match. We also match the exit interface for each Telco.

We set up our NAT pools and NAT source mapping’s referencing our route-maps.

interface FastEthernet0/0
description To Telco 1
ip address
ip nat outside
ip virtual-reassembly
duplex auto
speed auto

interface FastEthernet1/0
description To Telco 2
ip address
ip nat outside
ip virtual-reassembly
duplex auto
speed auto

ip sla 1
icmp-echo source-interface FastEthernet0/0
timeout 1000
threshold 800
frequency 30

ip sla schedule 1 life forever start-time now

track 1 rtr 1 reachability

ip route track 1
ip route 2

ip access-list extended NAT_ACL
permit ip any

route-map Telco1 permit 10
match ip address NAT_ACL
match interface FastEthernet0/0

route-map Telco2 permit 10
match ip address NAT_ACL
match interface FastEthernet1/0

ip nat pool Telco1 netmask
ip nat pool Telco2 netmask
ip nat inside source route-map Telco1 pool Telco1 overload
ip nat inside source route-map Telco2 pool Telco2 overload


I recently spent a lot of time trying to pull out the IP address of a handset registered to a CUCM9 cluster via AXL. It turns out the standard AXL response doesn’t include this information as it’s handled by the RIS service.

I had some luck with getting the RisPort wsdl working inside PHP but couldn’t return specific queries, everything I tried returned the first 1000 devices listed on the cluster.

I came across some varying info from Cisco regarding RIS.


The RisPort WSDL is deprecated. Use the RisPort70 WSDL.

I tried to use the RisPort70 from my CCM’s RIS page but PHP complained that it wasn’t able to interpret the WSDL. Then I came across this stating that the WSDL RPC’s were being deprecated and being replaced with doc/literal

Beginning in 9.0, the Serviceability XML WSDLs are available in both remote procedure call (RPC) encoded and doc/literal style formats.

Developers should migrate to the doc/literal style WSDL as soon as possible. Cisco plans to deprecate the rpc-encoded WSDL in Unified CM 11.0(1).

It stated that the RisPort70 RPC could be found at: https://servername:8443/realtimeservice/services/RisPort70?wsdl whilst the RisPort70 doc/literal could be found at https://ServerName:8443/realtimeservice2/services/RISService70?wsdl. I could hit the RISService70 even though the RIS page on my CCM didn’t list it. There was no small menu like in normal RIS – the page just returned the WSDL. Good enough for me.

After hacking around with the RISService70 and trying different approaches in CCM I finally got my PHP working. My PHP script now searches all clusters for a device registered with an IP address that I specify and returns the structure in an array that I can parse manually with PHP and then operate on.

$soapClientRIS70 = new SoapClient(“https://YOURCCMHERE:8443/realtimeservice2/services/RISService70?wsdl”,

$soap_response = $soapClientRIS70->SelectCmDevice(array(“StateInfo”=>””, “CmSelectionCriteria”=>array(“NodeName”=>””, “Status”=>”Registered”, “SelectBy”=>”IPV4Address”, “SelectItems”=>array(“item”=>array(“Item”=>”DEVICEIPADDRESSHERE”)))));


From there the Cisco RIS API documentation should provide you with everything else you need:

I hope that this will be portable into CCM11 but I’m guessing that the WSDL will be updated – hopefully no structure will change, but some better error responses would be nice.

I hope that this serves to save someone the time that I spent trying to work this out…

Reset VSOM admin password

What do you do when a retarded engineer sets a VSOM admin password and leaves the company? Call TAC and get the below super secret (not really) script . The below will reset the admin password to admin.

# /usr/BWhttpd/vsom_be/db/


NAT Timeout Variations

Just a quick note on the varying state of NAT timeouts as used by different vendors.

RFC1122 states the below regarding TCP keep-alives as programmatically designed:

Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval. This interval MUST be configurable and MUST default to no less than two hours.

RFC5382 states the below about NAT keeping RFC1122 in mind:

If a NAT cannot determine whether the endpoints of a TCP connection are active, it MAY abandon the session if it has been idle for some time. In such cases, the value of the “established connection idle-timeout” MUST NOT be less than 2 hours 4 minutes. The value of the “transitory connection idle-timeout” MUST NOT be less than 4 minutes.


Keeping this in mind there is a huge difference between vendor implementations as a default value. NOTE that this is just using a quick browse of the net for specific references, so some may be old/updated etc.

  • RFC: 7440 sec (2 hours 4 mins)
  • Cisco IOS: 86400 sec (24 hours)
  • Cisco ASA: 10800 sec (3 hours)
  • A10 (Carrier Grade): 300 sec (5 mins)
  • Brocade ServerIron ADX: 120 sec (2 mins)
  • Netgear FVS318: 600 sec (10 mins)
  • Netgear FVS336Gv2: 1200 sec (20 mins)
  • D-Link DIR-615: 7800 sec (2 hours 10 mins)
  • DD-WRT: 3600 (1 hour)

CallManager 9 + VirtualBox + Ubuntu 12.04 + GNS3 + SIP

Following on from similar post I did a few years back about CCM7 in VirtualBox with a SIP trunk to a 2621XM, I’ve recreated the process for CCM9 with a few differences.

The final environment looks like the below:

  • Cisco SRP527W ADSL2+ Router
  • Ethernet to Ubuntu 11.04 running as the VirtualBox Host
  • Call Manager 9 Virtual Machine Guest
  • Ubuntu 12.04 Guest
  • GNS3 inside the 12.04 Guest
  • 2621XM running as CUBE inside GNS3
  • SIP trunk between Call Manager 9 and the 2621XM
  • SIP trunk between external provider and the 2621XM (my provider is Internode)

I won’t detail the SRP or VirtualBox Host config – it’s far too simple. The only note to add is to turn SIP ALG on on the SRP and forward 5060-5062 to the IP of your GNS3 router.

Continue Reading…