Monday, May 23, 2022

how to connect a 7941 cisco voip phone directly to voip.ms from behind a consumer-grade nat.

this is the write-up explaining how to connect a 7941 cisco voip phone directly to voip.ms from behind a consumer-grade nat.

rtfm

first of all, let's read the fucking manual, which is up at my growing google drive manual share:

basic research on tftp

now that you're a little familiar with the phone, i'm going to direct you to the following video to get an understanding of what a tftp server is and how to upload or reset the firmware:


the video is helpful, but the steps i needed to follow were a little bit different. so, i'm posting it as a reference but i'm not suggesting you follow exactly the same steps - unless you're actually trying to connect to a local pbx, which we are not doing. rather, we are connecting to a remote pbx, and from behind a nat.

factory reset

first, i would advise purposefully bricking your phone by following the factory reset instructions at the following site:

Generic factory reset procedure:

  1. Press and hold #, power cycle the phone
  2. When an LED starts to flash, release #, and enter:

    • Hard Reset (format flash): 3491672850*#

    The phone will display Upgrading and erase its configuration. 

downloading firmware

now that your phone is wiped clean, let us find new firmware to download.

i need to start with a word of warning, and i do think this is a reasonable suggestion, given that you're trying to use a phone from c. 2005 - the procedure i'm going to describe requires two network interfaces connected via internet connection sharing, if attempted in xp. xp will not pick up your phone if you try to connect it to the computer using a vlan, a loopback adapter or a switch. xp will always assume that it is intended to be a client to anything you plug it into, unless you go out of your way to tell it otherwise; newer versions of windows allow for more intuitive, plug and play type two-way networking. i was able to get a second connection on my xp laptop using a usb-to-rj45 connector, and i had to plug the phone into that connector (and the nic into the router, in my case via a switch) in order to get it to pick up the connection. conversely, i was able to get windows 7 to pick up the phone as a client by simply plugging it into the back of the computer, and letting it connect to a dismantled vlan that hadn't been destroyed yet. i'm going to provide both sets of directions that i used to connect the phone to the respective operating systems, but just keep in mind that the point is that the tftp server has to bind to an open connection. the tftp server essentially piggybacks on to an existing connection, so you just have to have an existing connection, but this isn't obvious if you only have one nic, nor is it clear what to do next when faced with the reality of having one nic and needing to set up a dhcp server on your xp computer or your air gapped windows 7 computer.

but, before you can upload the firmware, you need to have firmware first.

the video suggests using the files at firewall.cx, but there is a strong suggestion online that they do not work behind a nat. it is not clear to me if my solution will work with the 9.3 firmware files or not, because i downgraded to 8.5 as a troubleshooting step and do not want to upgrade to see, but it would seem as though the problem was misdiagnosed by the internet community and, as such, the solution may not require downgrading, after all. if somebody wants to play with that, feel free to let me know the outcome.

regardless, the firmware i am using is not the one in the video but is rather this one:

3cx is a commercial provisioning provider, and if you want to avoid headaches then you may even consider buying their product. as it is, they are providing a safe download link to a firmware version that is no longer hosted by cisco. i have that file archived, but let us hope 3cx continues to provide it for free.

take that file and unzip it somewhere. next, go to where you unzipped it and immediately delete cisco_dialplan.html.

there are numerous walkthroughs online, but they all get the basic setting required to get the phone to work wrong and are all full of comments by people complaining that the answers don't actually work. if you want this to work, do not follow any of the other walkthroughs on the internet. however, i started by following these walkthroughs, and used their files as starting points, so i am going to properly reference them, as i correct the errors within them.

it is easiest to start with this walkthrough because it provides three accessible files:

you can read through the discussion on nat if you'd like, but i would advise you not to take it at all seriously in any way, except to realize that this is an office phone. it is certainly true that you don't want office phones connecting out to the internet, and it is likewise true that the examples on the forums of people not being able to connect to remote servers have to do with the phone's networking settings preventing them from doing it, but this external ip/nat thing did not fix my problem, did not fix the poster's problem and doesn't really seem to have anything to do with it. i was even able to open 30000 ports for the phone, which was sitting behind ics, using a batch script; it made no difference in resolving what is not a port forwarding error but a handshake error. in hindsight, it shouldn't have been expected to, because the error was that i was trying to complete a handshake over udp, not that i was unable to reach ports over tcp.

to continue with an actual working solution, download and extract each of those three files to the same directory that you extracted the 3cx download to. keeping in mind that you will eventually have to dial 1 to dial out, there is no reason to alter the dial plan or xmldefault files. the sepmac file will be where the user-configurable entries will be edited. and you should immediately change the name of the file so that it contains the mac address, as explained in the video and the forum post.

there is one more file required for the firmware. go to the following webpage and search for sip.conf:

create a new txt file in your directory that you unzipped everything to, paste the following contents into it and save it as sip.conf:

udpbindaddr=0.0.0.0
tcpenable=yes
tcpbindaddr=0.0.0.0
callcounter=yes
transport=udp, tcp

this enables your phone to use tcp as a transport protocol, which allows it to log into an external web server. otherwise, your phone will try to log into voip.ms using udp and the handshake will never complete - some intermediate device, like a virtual nat (ics), will send back a "destination unreachable" response, instead.

uploading firmware to your phone

a) using windows 7 or 10

when i bought the phone, i intended to use it as a front-end for microsip running in windows xp on an evo n800c, so i spent quite a while trying to get it to accept an ip from windows xp, with no success. after a while, i decided i had to try it in 7 to make sure it works, and i happen to only have one wired ethernet port in my only working 7 box, so i had to be creative about getting it to bind.

if you have two ethernet ports or an ethernet port and a wireless port, then it should be straight-forward like in the video. if you don't, you'll need to trick your computer into making it look like it has an open connection.

the way i got it to work was to right click on my lan connection, go to properties and select configure on the network card (in my case, an integrated intel card). i then went to the vlan tab and added a vlan. i then restarted the computer. after rebooting, i then went back and deleted the vlan i just created. this vlan will disappear on another reboot, but is still available as a ghost binding for the tftp server while the machine is on, and until the machine turns off. now, plug your phone in and the icon should spin rather than say "unplugged". i then went to my normal lan connection and changed it to a static ip and continued to bind it to tftp, like in the video. i would suggest you disable the tftp client. now, your phone should pick up an ip address from the dhcp server running in tftp and then connect to the tftp server. to flash the phone, you want to push # (on the phone) on startup until the lights flash, then type 123456789*0#.

b) using windows xp sp3

you need two physical connections for this to work. i used the ethernet port in my laptop (connected to the switch) as the local area network connection and then connected the phone to a usb-to-rj45 connector, which installed as a secondary adapter. the trick is to connect the two adapters using internet connection sharing, which turns the usb-to-rj45 connector into a virtual nat. your phone will then pick up an ip address from the laptop, which is now a server. you can then bind your virtual tftp server to the virtual subnet.

first, i'd suggest you just turn all software firewalls running in xp off for a second, altogether.

next, you create the internet sharing connection by going to the advanced tab of the adapter properties and clicking the appropriate box. you will then need to restart your computer; when it comes back up, you'll notice that the second connector has ip address 192.168.0.1, and is acting like a virtual router. your phone should pick up an address on that subnet (192.168.0.x), meaning you won't need to set up a dhcp server in tftp.

i would advise installing an alias on the virtual ics router to bind the tftp server to, as it keeps the concept conceptually cleaner; you can have your virtual router at 192.168.0.1, and your tftp server at something like 192.168.0.2. you can do this by entering the advanced tab of the tcp/ip properties in the adapter (lan) properties and adding a new address for the tftp server to bind to. you should then be able to reset the phone by holding down # on power up and keying in 123456789*0# when the lights flash - your phone will get the ip from the virtual nat and connect to the tftp server on the virtual subnet.

----

note that your phone now has the firmware on it, but it probably doesn't have the right configuration file and you probably don't have a long term tftp solution. so, we're now going to disconnect everything and put it back together in a more stable way.

giving your phone access to the wan

now, plug your phone directly into your router and make sure it can get an ip address from it. personally, i plug my phone into a switch that connects to a router on one side and a laptop (the evo n800c) for the tftp server on the other side. in the router's firmware, i use mac filtering (meaning i restrict which physical devices are allowed to connect to the network, behind the nat) and i have a very restricted pool of static ip addresses on a dhcp server that only hands out addresses to identified devices. so, if you come to my house and try to plug your cell phone or laptop into my network, it won't work until the router knows your mac address and i open up an exception in the dhcp list. so, on my network, the phone has a static ip address set in the router's firmware, and assigned to the phone's mac address. you will set up your network as you will, but the phone needs to be able to access the wan and needs an ip address from the router.

setting up the stable tftp server

you need to have some computer running a tftp server on the same subnet as the phone every time you turn this phone on. this is entirely absurd, but it's just how it works.

whether you are using a windows 7 or xp machine, the steps are now the same - disable whatever sharing scheme you had (either by rebooting the windows 7 machine with the vlan off or by disabling internet connection sharing on your xp machine and unplugging the secondary adapter, if it's not hard-wired) and just plug it directly into your router, in order to get an ip address on the same subnet as the phone. in my case, i keep all of my pcs off the internet, entirely; i will be using the evo n800c laptop as the tftp server, connected into the switch, as described before. this laptop has a static ip address on the subnet, as assigned by the router, to the laptop's mac address.

while you may just use this static ip address for your tftp server, i would again advise that you use an alias for it using the same procedure as before. that way, your computer and tftp servers will not have the same ip address on the subnet, and you can readily identify between them, if you need to analyze any traffic. broadly speaking, i would suggest that each virtual device ought to be given a unique alias on any subnet, real or virtual, as a best practice.

if you are using an alias, or if you are not, you can now bind the tftp server to the computer's active ip address on the subnet by using the steps in the video or in the forum post.

hardcoding addresses into your phone

this step will not apply to you if you are using dhcp servers to assign random ip addresses on the fly, but you may find yourself repeatedly reconfiguring your device if you choose that path, which is the opposite of the intent of the technology. based on my (limited) experience with this device, i would strongly suggest that you assign it a static ip and assign your tftp server to a static ip as well.

to enter the settings, push the settings button. if you don't know where that is, read the fucking manual.

now, push **# to unlock the settings on your phone. if you have just uploaded the stock config file, your phone will not have a password on it. yet.

- go to network configuration, then go to ipv4 configuration and change dhcp to disabled. 
- now, go down to the ip address and type in the address you decided should be assigned to it by the router.
- below that is the subnet mask. perhaps your phone entered a subnet mask automatically, and perhaps it did not; you will need to look up how to do that if you don't know how, but you'd better enter in the right value.
- default router should be the ip address of your router, on the subnet
- dns server is probably the same as default router
- now, go down to tftp server and enter the alias to the computer's ip address, or the computer's ip address itself, if you insist on being unorganized.
- press save
- press **# again to lock the phone
- press **#** to reboot the phone

at this stage, your phone should correctly get an ip address from your router, and you should get an error when it loads data from the tftp server, but you need to be sure that it can connect to both of these external devices before you move forwards. if you're not sure, check the log messages in the tftp server; don't worry if there's error messages, just make sure it's actually connected.

updating the configuration file

i started with the configuration file (the sepmac file) at the above forum site and made a number of changes, which are highlighted here in red.

<device>
<deviceProtocol>SIP</deviceProtocol> 
<sshUserId>whatever</sshUserId>  
<sshPassword>whatever</sshPassword> 
<devicePool>  
 <dateTimeSetting>  
    <dateTemplate>M/D/Y</dateTemplate>  
    <timeZone>Eastern Standard/Daylight Time</timeZone>
    <ntps>  
         <ntp>  
             <name>128.138.140.44</name>  
             <ntpMode>Unicast</ntpMode>  
         </ntp>  
    </ntps>  
 </dateTimeSetting>  
 <callManagerGroup>  
    <members>  
       <member priority="0">  
          <callManager>  
             <ports>  
                <ethernetPhonePort>2000</ethernetPhonePort>  
                <sipPort>5060</sipPort>  
                <securedSipPort>5061</securedSipPort>  
             </ports>  
             <processNodeName>ip address of voip.ms proxy server</processNodeName>  
          </callManager>  
       </member>  
    </members>  
 </callManagerGroup>  
</devicePool>  
<sipProfile> 
 <sipProxies>  
    <backupProxy></backupProxy>  
    <backupProxyPort></backupProxyPort>  
    <emergencyProxy></emergencyProxy>  
    <emergencyProxyPort></emergencyProxyPort>  
    <outboundProxy></outboundProxy>  
    <outboundProxyPort></outboundProxyPort>  
    <registerWithProxy>true</registerWithProxy>  
 </sipProxies>  
 <sipCallFeatures> 
    <cnfJoinEnabled>true</cnfJoinEnabled>  
    <callForwardURI>x--serviceuri-cfwdall</callForwardURI>  
    <callPickupURI>x-cisco-serviceuri-pickup</callPickupURI>  
    <callPickupListURI>x-cisco-serviceuri-opickup</callPickupListURI>  
    <callPickupGroupURI>x-cisco-serviceuri-gpickup</callPickupGroupURI>  
    <meetMeServiceURI>x-cisco-serviceuri-meetme</meetMeServiceURI>  
    <abbreviatedDialURI>x-cisco-serviceuri-abbrdial</abbreviatedDialURI>  
    <rfc2543Hold>false</rfc2543Hold>  
    <callHoldRingback>2</callHoldRingback>  
    <localCfwdEnable>true</localCfwdEnable>  
    <semiAttendedTransfer>true</semiAttendedTransfer>  
    <anonymousCallBlock>1</anonymousCallBlock>  
    <callerIdBlocking>0</callerIdBlocking>  
    <dndControl>1</dndControl>  
    <remoteCcEnable>true</remoteCcEnable>  
 </sipCallFeatures> 
 <sipStack>  
    <sipInviteRetx>6</sipInviteRetx>  
    <sipRetx>10</sipRetx>  
    <timerInviteExpires>180</timerInviteExpires>  
    <timerRegisterExpires>180</timerRegisterExpires>  
    <timerRegisterDelta>5</timerRegisterDelta>  
    <timerKeepAliveExpires>120</timerKeepAliveExpires>  
    <timerSubscribeExpires>120</timerSubscribeExpires>  
    <timerSubscribeDelta>5</timerSubscribeDelta>  
    <timerT1>500</timerT1>  
    <timerT2>4000</timerT2>  
    <maxRedirects>70</maxRedirects>  
    <remotePartyID>false</remotePartyID>  
    <userInfo>None</userInfo>  
 </sipStack> 
 <autoAnswerTimer>1</autoAnswerTimer>  
 <autoAnswerAltBehavior>false</autoAnswerAltBehavior>  
 <autoAnswerOverride>true</autoAnswerOverride>  
 <transferOnhookEnabled>false</transferOnhookEnabled>  
 <enableVad>false</enableVad> 
 <preferredCodec>g711ulaw</preferredCodec>  
 <dtmfAvtPayload>101</dtmfAvtPayload>  
 <dtmfDbLevel>3</dtmfDbLevel>  
 <dtmfOutofBand>avt</dtmfOutofBand>  
 <alwaysUsePrimeLine>false</alwaysUsePrimeLine>  
 <alwaysUsePrimeLineVoiceMail>false</alwaysUsePrimeLineVoiceMail>  
 <kpml>3</kpml>
 <natReceivedProcessing></natReceivedProcessing>  
 <natEnabled>true</natEnabled>  
 <natAddress></natAddress>  
 <phoneLabel>name displayed on phone</phoneLabel> 
 <stutterMsgWaiting>1</stutterMsgWaiting> 
 <callStats>false</callStats>  
 <silentPeriodBetweenCallWaitingBursts>10</silentPeriodBetweenCallWaitingBursts>  
 <disableLocalSpeedDialConfig>false</disableLocalSpeedDialConfig> 
 <startMediaPort>10001</startMediaPort>  
 <stopMediaPort>20000</stopMediaPort> 
 <sipLines> 
  <line  button="1"> 
       <featureID>9</featureID>  
       <featureLabel>name of line 1</featureLabel>  
       <proxy>USECALLMANAGER</proxy>  
       <port>5060</port> 
       <name>##VOIPMSUSER##</name> 
       <displayName>call display name</displayName>  
       <autoAnswer>
          <autoAnswerEnabled>2</autoAnswerEnabled>
       </autoAnswer>  
       <callWaiting>3</callWaiting> 
       <authName>##VOIPMSUSER##</authName>  
       <authPassword>##VOIPMSPASS##</authPassword>  
       <sharedLine>false</sharedLine> 
       <messageWaitingLampPolicy>1</messageWaitingLampPolicy>  
       <messagesNumber>*97</messagesNumber>  
       <ringSettingIdle>4</ringSettingIdle>  
       <ringSettingActive>5</ringSettingActive> 
       <contact>##VOIPMSUSER##</contact>  
       <forwardCallInfoDisplay>  
          <callerName>true</callerName>  
          <callerNumber>true</callerNumber>  
          <redirectedNumber>false</redirectedNumber>  
          <dialedNumber>true</dialedNumber>  
       </forwardCallInfoDisplay>  
    </line>
</sipLines>
 <voipControlPort>5061</voipControlPort>  
 <dscpForAudio>184</dscpForAudio>  
 <ringSettingBusyStationPolicy>0</ringSettingBusyStationPolicy>  
 <dialTemplate>dialplan.xml</dialTemplate>  
</sipProfile> 
<commonProfile>  
 <phonePassword>password for phone</phonePassword>
 <backgroundImageAccess>true</backgroundImageAccess>  
 <callLogBlfEnabled>2</callLogBlfEnabled>  
</commonProfile> 
<loadInformation>SIP41.8-5-4S</loadInformation> 
<vendorConfig> 
 <disableSpeaker>false</disableSpeaker> 
 <disableSpeakerAndHeadset>false</disableSpeakerAndHeadset> 
 <pcPort>0</pcPort> 
 <settingsAccess>1</settingsAccess>
 <garp>0</garp> 
 <voiceVlanAccess>0</voiceVlanAccess>
 <videoCapability>0</videoCapability>  
 <autoSelectLineEnable>0</autoSelectLineEnable> 
 <webAccess>0</webAccess>  
 <spanToPCPort>0</spanToPCPort>  
 <loggingDisplay>1</loggingDisplay>  
 <loadServer></loadServer>  
</vendorConfig> 
<versionStamp></versionStamp> 
<userLocale> 
 <name>United_States</name> 
<uid>1</uid> 
 <langCode>en_US</langCode> 
<version>1.0.0.0-1</version> 
 <winCharSet>iso-8859-1</winCharSet> 
</userLocale> 
<deviceSecurityMode>1</deviceSecurityMode> 
<authenticationURL></authenticationURL>  
<directoryURL></directoryURL>  
<idleURL></idleURL>  
<informationURL></informationURL> 
<messagesURL></messagesURL>  
<proxyServerURL></proxyServerURL>  
<servicesURL></servicesURL> 
<dscpForSCCPPhoneConfig>96</dscpForSCCPPhoneConfig>  
<dscpForSCCPPhoneServices>0</dscpForSCCPPhoneServices>  
<dscpForCm2Dvce>96</dscpForCm2Dvce>
<transportLayerProtocol>1</transportLayerProtocol>

<capfAuthMode>0</capfAuthMode>  
<capfList>  
 <capf>  
    <phonePort>3804</phonePort>  
 </capf>  
</capfList> 
<certHash></certHash>  
<encrConfig>false</encrConfig>  
</device>

====

notes: 

1)  <anonymousCallBlock>1</anonymousCallBlock> ensures that anonymous callers cannot reach you. if you want to be reached by anonymous callers, pick 0. 2 does not seem to be in use.
2)   <callerIdBlocking>0</callerIdBlocking> allows your call display name to appear on the phones of the people you're calling. if you want to make anonymous calls, pick 1. 2 does not appear to be in use. 
3)   <dndControl>1</dndControl> this is supposed to block incoming calls, but i don't think it works.
4)   <timerRegisterExpires>180</timerRegisterExpires>  is recommended by voip.ms
5)  <natReceivedProcessing></natReceivedProcessing>. note that i removed the value from this entry. i do not believe my headers are being processed by voip.ms.
6) <natEnabled>true</natEnabled>. i am, in fact, behind a nat.  
7)  <natAddress></natAddress>. but, this isn't necessary to fill in.  
8) <phoneLabel>name displayed on phone</phoneLabel> 
9)   <line  button="1"> i removed the carriage line, here.
10)  <proxy>USECALLMANAGER</proxy>. the call manager tag is defined above.  a hard-coded ip might also work.
11)   <displayName>call display name</displayName>. this is the name displayed on the phones of the people you're calling. 
12)  <phonePassword>password for phone</phonePassword>. if you enter a (short) password here, you will need to provide it after pressing **# to edit values on the phone.
13) <loadInformation>SIP41.8-5-4S</loadInformation>. you need to get the firmware revision correct, here.
14) <transportLayerProtocol>1</transportLayerProtocol> - this is the magic setting that fixed everything, and it seems to have been badly misunderstood. the numbers i've seen entered are 2 and 4 and the assumption seems to have been that you're telling the phone what layer to use in the osi framework. that is not what this setting is at all. this setting has values of 1 and 2, where 1 tells the phone to communicate over tcp and 2 tells it to use udp. functionally, 1 means you're behind a nat and trying to get through it and 2 means you're communicating strictly on the local subnet.

make sure that voip.ms is set to nat=yes

a common troubleshooting step is to try it with nat=no at voip.ms, but that does not make sense. you are, in fact, behind a nat. make sure that voip.ms knows that.

if you press settings, then **#** your phone will reboot and it should do the following:

1) find an ip address
2) load the tftp server
3) register

you should get a dial tone when you pick the phone up. 

make sure to press one before dialing out.