Caveat: What follows could best be classified as a hack. I have posted this information because sometimes a hack is called for but also because it highlights the strength of OCS as a platform. Although implementing this workaround is via supported mechanisms, there is no support for the code included below. Please test in a non-production environment to ensure that this solves your problem with no other side effects.
On a particular voice deployment, we noticed an issue with PSTN callers to OCS not hearing any ring back tones (the ringing sound) in certain situations. We were able to fix the issue, though, with the creative use of the Microsoft SIP Processing Language (MSPL).
Our specific scenario was that the Communicator user had configured OCS to simultaneously ring (hereafter simply called “SimRing”) a PSTN phone number. While the user was signed into Communicator, the caller would hear ringing and SimRing would work. When the user was not signed into Communicator, the caller would not hear ringing and the call would disconnect within a few seconds before the called party could pick up the SimRing phone.
The problem occurred because of a missing “180 Ringing” SIP response message. When Communicator is signed in, it generates the ringing message and OCS routes this back to the caller appropriately. When Communicator is not signed in, it obviously does not generate this message. The endpoint that is being called through SimRing should generate it and OCS will route that back to the caller. In our case, that other endpoint was not generating it. So, to the caller, it did not look like any endpoints were ringing.
The most appropriate fix, in this case, would be to resolve why the ringing endpoint is not sending the alert appropriately. But, that would involve working with multiple vendors and resolving a complex call flow. We chose, instead, to simply generate the “180 Ringing” response for all calls inbound from the PSTN regardless of Communicator’s online status. This amounts to a little white lie. We will be telling the caller that an endpoint is ringing in some cases where none really are. (Because of the way it works, too, if Communicator is online, two ringing responses will be sent.)
The script that generates this response is pretty straightforward. It is written in MSPL and is added to the OCS front end server that is the mediation server’s next hop. Because it generates ringing responses for all inbound calls from the mediation server, it is likely to help in other situations where PSTN callers are not hearing ring back tones. To my knowledge, this script has been used without issue on both OCS 2007 and OCS 2007 R2.
The code is provided below for easy discovery and reading. To use the code, I have also provided it as an attachment to this post (RespondWithRinging.am). You can download that attachment and install it with the steps below. (Sometimes the attachment link is hard to find. Open the post and look for the attachments just before the comment section.)
To Install the Script
Select the “Front End Scripts” node that is under the OCS server that is the next hop for your mediation server. (You may need to repeat these steps for each server or pool that mediation servers use.) We will be adding this script to the list in the position just above UserServices. Right-click “Front End Scripts” and choose “Properties” to modify the list of scripts.
Click the “Add…” button to add a new script.
Complete the “Add Front End Script” dialog with the appropriate information. The script path is wherever you have saved the RespondWithRinging.am file attached to this post. The script name is an arbitrary value you can supply. The URI must match the appUri value given in the application manifest.
The script will be added to the bottom of the list. In this position, it will not be called for inbound calls because they will be handled by applications higher in the stack. You will need to use the “Up” button to move the script into the position above UserServices. There is no reason to mark this script as critical.
After applying the new front end script properties, your list of front end scripts should look like this:
With this script in place, you should be able to see the “180 Ringing” responses that are generated by it for inbound PSTN calls. Notice the “FALSE-180” header that the script inserts to let you know where this response comes from.
For reference, here are the contents of RespondWithRinging.am. (If you view this post, you can see the attachments link just before the comment area at the bottom.)
<?xml version="1.0"?> <lc:applicationManifest lc:appUri="http://www.contoso.com/RespondWithRinging" xmlns:lc="http://schemas.microsoft.com/lcs/2006/05"> <lc:allowRegistrationBeforeUserServices action="true" /> <lc:requestFilter methodNames="INVITE" strictRoute="false" registrarGenerated="true" domainSupported="true" /> <lc:responseFilter reasonCodes="NONE" /> <lc:proxyByDefault action="true" /> <lc:scriptOnly /> <lc:splScript><![CDATA[ // This script will respond to incoming INVITEs from // the mediation server. // Build the user@host from the To: header. toUri = GetUri( sipRequest.To ); toUserAtHost = Concatenate( GetUserName( toUri ), "@", GetHostName( toUri ) ); Log( "Debug", false, "RespondWithRinging: we have a request: ", sipRequest.Method, " ", toUserAtHost ); // Check if this is a re-INVITE and exit if so foreach ( sessionExpires in GetHeaderValues( "Session-Expires" ) ) { if ( ContainsString( sessionExpires, "refresher", true ) ) { Log( "Debug", false, "RespondWithRinging: * skipped; This is a session refreshing invite" ); return; } } // Check to make sure that the INVITE is from a mediation server foreach ( userAgent in GetHeaderValues( "USER-AGENT" ) ) { if ( ! ContainsString( userAgent, "mediation", true ) ) { Log( "Debug", false, "RespondWithRinging: * skipped; not a mediation server request" ); return; } } // If we're here, send a 180 response // Headers are being added in case it's important to detect this generated 180 response in a log Log( "Debug", 1, "RespondWithRinging: * Ringing response being submitted" ); AddHeader( "FALSE-180", "true" ); Respond( 180, "Ringing", "FALSE-180=true" ); return; ]]></lc:splScript> </lc:applicationManifest>
As I have mentioned, there is no support for this solution. If it feels like a kludge to you, you are right to feel that way. That said, it may be the quickest way to workaround issues of missing ring back tones while you are working to resolve the real underlying issue. If you use this script in your environment, I would appreciate you contacting me and letting me know how it’s going.
--Doug
This post has been brought to you by VoIPNorm.
The new Response Group Service in Office Communications Server 2007 R2 is a neat solution that provides inbound call routing to available agents. In terms of features, it sits somewhere between the hunt group offered on your PBX and a full contact center ACD. It’s pretty simple to setup initially and then you can delegate some workflow management tasks to the end users. There are other blogs that will walk you through setting up a response group.
There are scenarios where it is desirable to have the response group service forward the incoming call to a PSTN(1) number. This can be done when a call has remained in the queue longer than desired, when the queue is full, or anytime outside your designated working hours. The user interface is deceptively simple. As configured in the below dialog, any calls that remain in the InfoDesk queue for longer than 300 seconds will be forwarded to (206) 555-1202:
Pretty straightforward, right? I thought so, too. However, I had two reports of this not working in the same week. Then, I found this post from Kevin which, after claiming outbound PSTN calls don’t work, provides a workaround. Given the conflicting evidence on the issue, an investigation was in order.
If the Communicator logs from the client aren’t appropriate or available, I always start my investigations with OCSLogger. Since this problem involved outbound calls, I made sure to check the OutboundRouting component.
To reproduce the problem, I called into this response group from a PSTN phone and waited in the queue until it timed out then tried (but failed) to send me to the external number. Here is a (significantly trimmed) snippet of what shows up in the OutboundRouting log:
Creating a OutboundRoutingTransaction object (4) From uri: +12065551201@contoso.com From User Uc Enabled: False From User Policy: <null> ReferrerUri: infodesk@contoso.com Referrer Uc Enabled: True Referrer Policy: <instance><property name="Name"><![CDATA[Default Policy]]></property>... Referrer Home server: <null> IsAvMCUDialOut: False Applying referrer's outbound policy Routing request based on caller: infodesk@contoso.com User infodesk@contoso.com has UC policy: Default Policy target phone number: +12065551202, PhoneRouteUsage: Default Usage No hits. Exit. Respond with 403
Can you tell what the problem is? I’ll wait here until you find it. :-)
Every outbound call that OCS makes must be done in the context of a voice policy. It is the voice policy that lets OCS know if the caller is authorized to make the call and, if so, which route should be selected. Usually, this is the policy that is assigned to the enterprise voice user making the call.
However, in several scenarios, it makes sense to apply a different policy. In the delegate scenario, you can place a call “on behalf of” the boss have the voice policy of the boss apply. For a call placed by an Exchange UM Auto Attendant, the policy assigned to the OCS AutoAttendant user is used. And, here, in the case of response groups, the policy assigned to the response group contact object is used. (Look for “Applying referrer's outbound policy” in the log above.)
“Wait,” you say. “When I created the response group contact object, I wasn’t able to specify a voice policy.” That’s right. The tool leaves the UC policy attribute blank for the application contact so OCS uses the “Default Policy.” In this case, the “Default Policy” has no routes. You can tell by the “No hits” statement in the log.
Note: This explains why the problem happens for some but not for others. If you have modified your enterprise voice Default Policy to include a valid route for the destination number, then you are blissfully ignorant of this particular problem.
There are two avenues, then, to correcting the problem. The first (and easiest) would be to modify the default policy to include a valid route for the PSTN numbers that you allow to be called. Because this policy may be used as the default in other situations, though, I would be wary of changing it. Perhaps the best idea is to leave it with no valid routes and choose my second option: modify the voice policy that is assigned to the response group contact object.
There are a number ways that you could modify the response group application contact object. I had problems, though, using any of the GUI tools. (I don’t think the OCS admin tool was really built to work from the Sites and Services snap-in which is what you need if you use the default settings and store application contacts in the AD configuration container.)
Since WMI is the supported method of administering OCS settings and since PowerShell is great with WMI, I decided to try that. These PowerShell commands will take the voice policy of an existing user and assign it to the Response Group Service application contact:
$VoiceUser = gwmi -q "select * from MSFT_SIPESUserSetting where PrimaryURI='sip:alice@contoso.com'" $RGSContact = gwmi -q "select * from MSFT_SIPApplicationContactSetting where PrimaryURI='sip:infodesk@contoso.com'" $RGSContact.UCPolicy = $VoiceUser.UCPolicy $RGSContact.Put()
Note: The WMI objects for OCS should be available on any machine where the OCS Administration Tools have been installed.
When selecting which voice policy to assign to the response group, consider who the managers of the workflow are and use the most restrictive policy that applies to them. This will avoid issues where the workflow can be configured to route calls to numbers that the users should not be able to call directly.
After correcting the voice policy and reproducing the scenario again, this is the corresponding OutboundRouting log:
Creating a OutboundRoutingTransaction object (2) From uri: +12065551201@contoso.com From User Uc Enabled: False From User Policy: <null> ReferrerUri: infodesk@contoso.com Referrer Uc Enabled: True Referrer Policy: <instance><property name="Name"><![CDATA[Unrestricted Calling]]></property>... Referrer Home server: <null> IsAvMCUDialOut: False Applying referrer's outbound policy Routing request based on caller: infodesk@contoso.com User infodesk@contoso.com has UC policy: Unrestricted Calling target phone number: +12065551202, PhoneRouteUsage: Unrestricted #hits: 2, route names: Default Route Default Attempting to find GetNextHop: Length:1; StartAt:0; Tried:1; FQDN/State:UCLAB-MS1.contoso.com:5061-Up New request line: sip:+12065551202@UCLAB-MS1.contoso.com:5061;user=phone;maddr=UCLAB-MS1.contoso.com. Exit.
Notice in this log that a policy other than the empty “Default Policy” is selected. You can see that a mediation server is selected from among the valid routes.
Note: This problem would not have occurred for a call from an enterprise voice-enabled user that called into the queue from Communicator. In that case, the caller’s voice policy (as determined by the From URI) would be applied instead of the policy of the response group contact object (as determined by the Referrer URI).
I hope that this post helps to resolve this particular issue for you but, more importantly, I hope it provides some insight into how OCS outbound routing works and how to troubleshoot these kinds of issues.
Footnote 1: Most of the time, when I say “PSTN number” in this context, I really mean “any number not handled by OCS.” This could be an internal number on your PBX as easily as a PSTN number.
This post has been brought to you by RGSCOT.EXE – Ah, RGSCOT, you could have been so much more.
A lot has been written about the way that Microsoft Office Communicator uses DNS to automatically discover a registration point for a given SIP URI. I won’t repeat all of that here. But, I do want to emphasize one of the unique constraints that Communicator places on the DNS SRV records it uses.
For automatic configuration to succeed, Communicator requires that the domain of the target host match the domain of the user’s SIP URI. This requirement is driven by a security decision the Communicator team made (not by a DNS requirement). The reason is provided in the documentation this way:
This tight validation between the host name and the URI is done specifically because the only configuration with which the client is provided is the SIP URI. Because of this, the client must be very careful not to allow DNS attacks to allow it to connect to any man-in-the-middle, who could thereby watch Communicator’s traffic. By having a tight tie between the URI and the host names allowed for logon, Communicator has better certainty that the certificate the user is validating actually has authority for the domain to which he is trying to log on to.
In other words, it’s not sufficient for an attacker to simply create the appropriate DNS SRV records to fool your Communicator to logon through his server. (Which would be trivial.) He’ll also need to get a certificate that you trust for an FQDN that falls within in your organization’s domain. (Which should be much harder.)
In practice, this constraint means that this is a valid SRV record to be used in automatic configuration for the user alice@contoso.com:
_sipinternaltls._tcp.contoso.com. 86400 IN SRV 0 0 5061 sip.contoso.com.
However, this record will not be used by Communicator for automatic configuration even though it is a valid SRV record:
_sipinternaltls._tcp.contoso.com. 86400 IN SRV 0 0 5061 sip.litwareinc.com.
(I’m using this standard format for representing SRV records: _Service._Proto.Name TTL Class SRV Priority Weight Port Target. In the second example, notice that the target host is not in the contoso.com domain.)
This can create problems for organizations that do not resolve queries for their public DNS name internally. If you use an internal DNS namespace, it is likely to be unrelated to the domain of your SIP URIs (because we recommend that your SIP URI match your SMTP address which must be a public DNS domain). You might be tempted to put a record like this in your public DNS:
_sipinternaltls._tcp.contoso.com. 86400 IN SRV 0 0 5061 ocspool.contoso.local.
Unfortunately, Communicator will not attempt to connect to ocspool.contoso.local for the someone in the contoso.com SIP domain. (To be more correct, it will connect to ocspool.contoso.local if that name is provided by group policy or configured manually in Communicator. It is only considered invalid for the purposes of automatic configuration.)
Additionally, creating these records in your external DNS for internal clients will reveal something about your internal addressing to the outside world. Most security folk consider this a “no-no.”
For these reasons, I generally say that split-brain DNS is required to enable the automatic configuration of Communicator to work properly for both internal use (where Communicator should find a director or pool server) and external use (where Communicator should find your Access Edge). For many of my customers, this has not been a problem. They have already been resolving some form of their public name internally already.
For the customers that don’t already have split-brain DNS implemented, it is a big leap for them to begin resolving their external domain internally. To suggest that Contoso should suddenly put the DNS zone contoso.com on their internal DNS servers simply to accommodate an OCS deployment will likely get you laughed out of the room.
A more reasonable suggestion is to create what I’ll call two “pinpoint” DNS zones. These are internal zones that will resolve just the names that we want for automatic configuration. All other names in their external DNS domain will be unaffected.
To implement this for Contoso, we would create a zone “_sipinternaltls._tcp.contoso.com” and zone “sip.contoso.com.” Notice that these are two zones – not two records in one “contoso.com” zone. A zone is a name resolution boundary in the hierarchical DNS namespace. By configuring the internal DNS server to be authoritative only for these two names, clients will continue resolving other names in the contoso.com domain as they always have.
Coincidentally, over on his blog, Geoff Clark has just suggested the same thing. He describes the problem and suggests the same solution but shows a method of creating the zone on a Windows DNS server via the DNS management console. Unfortunately, there is a limitation in the management console that is not present in the underlying Windows DNS implementation. This limitation required Geoff to create the zone as “_tcp.contoso.com” when what we would really like is a zone named “_sipinternaltls._tcp.contoso.com.”
This limitation in the user interface can be resolved by creating the zones and the records using the Dnscmd command line tool. For Contoso, here are the required commands:
dnscmd . /zoneadd _sipinternaltls._tcp.contoso.com. /dsprimary dnscmd . /recordadd _sipinternaltls._tcp.contoso.com. @ SRV 0 0 5061 sip.contoso.com. dnscmd . /zoneadd sip.contoso.com. /dsprimary dnscmd . /recordadd sip.contoso.com. @ A 172.16.45.12
Of course, you’ll need to make the appropriate changes for your environment. If you are not running the command on your Windows DNS server, you will need to replace the first dot with your server name. You may also prefer a different zone type than “dsprimary.” If so, change the zoneadd commands appropriately. I doubt that your pool’s IP address is the same as my example but, if you have followed me this far, you already know what to change there.
I hope this suggestion helps somebody. Please let me know by providing feedback.
This post has been brought to you by someone who disagreed with me and forced me to explain myself.
Over the years, I’ve seen a number of different discussions about the directors, what they do, how they behave, and when we should use them. This post summarizes what I believe to be the salient points concerning the director component. Hopefully, this will serve to clarify rather than confuse.
One of the advantages of directors that we originally touted was that it “offloaded authentication” and relieved the pool of that duty. This is only partially true. The behavior is slightly different whether we are talking about external users or internal users.
Please consider the following diagram while I describe the traffic flow:
External case (the Chicago user in the diagram):
Internal case (the London user in the diagram):
Given the above understanding, let’s make some application. Here are the benefits of directors:
Security: In an environment with an access edge but no director, unauthenticated traffic will be sent to your production pool for authentication. The edge server will validate some SIP headers but it would be possible to craft a SIP message that gets through. This gives an attacker a direct path to your internal production server. The director component lets you isolate that unauthenticated traffic to a server that is less critical. Some organizations will find this very important even in single pool deployments.
Performance: For remote users, the director will proxy all SIP traffic. Without directors, you have to pick a pool that will proxy the traffic. This could have a performance impact to the users homed on that pool. The director is also handling authentication for those remote users.
I have been asked if there’s a certain number of users that your deployment should be supporting before it makes sense to have a director. It’s not the user-count that is important; it is whether or not the deployment has remote access and the number of internal pools. Let’s consider the four different combinations of these two factors:
Note: I should point out that in the above traffic flow descriptions, when evaluating how to handle the registration request, the director or the pool doesn’t really know if the user is external or internal. All it knows is whether it is the first hop or not (based on SIP Via headers). The default behavior of every OCS front end (whether in a director pool or a user pool) is to redirect traffic to the correct home server if it is the first hop and proxy the traffic if it is not. (This default behavior can be changed by modifying the RedirectMethods property of MSFT_SIPEsEmSetting.)
This post has been brought to you by Visio. Pretty drawing, huh?
I’ve seen various customers that were building OCS dial plans that did not comply with our recommendation to follow RFC 3966. Some of these customers had problems while I was engaged with them. All the rest will have problems later.
Note: RFC 3966 is the standard related to specifying a “tel” URI. It is the reason OCS uses E.164 global numbers prefixed with a plus sign. Because E.164 is easier to say than RFC 3966, some (including me) will use the former term when the latter is more correct.
Phone numbers in OCS are different from phone numbers in a typical PBX because they are based on a enterprise-wide directory. A user from any location in your organization must be able to look in the directory and place a call to a user in any other location. Using local extensions or regional number formats is simply not an option in the directory.
I want to encourage you to “think big” when it comes to designing your dial plan for OCS. You are probably integrating with a single PBX or gateway today. Superficially, it makes sense to build an OCS dial plan that accommodates the dial plan of the PBX.
What will happen when you want to integrate with a second gateway and perform least cost routing? What will happen when you move a portion of your telephony to a SIP trunking provider? Or, when your company expands into another country? Or, when you federate OCS with your business partners? Will the dial plan you design today still make sense then?
The diagram below depicts the high-level operations performed on a phone number entered by a user in OCS. The core of these operations should be based on standard tel URIs. Only at the input and output of this process are other dial strings appropriate.
The Line URI is a tel URI and should follow RFC 3966 which is the standard specifying the format for tel URIs. It follows then that a normalization rule should result in a number that complies with RFC 3966. Similarly, a route decision should be based on numbers that comply with RFC 3966.
(Notice that the above picture is only intended to show what happens to numbers that the user provides. Phone numbers can also be provided by federated partners that were normalized by their rules but must be routed according to your voice policies. That alone demonstrates why following standards here will be so important.)
These things should not be in your normalized numbers: PBX steering codes, trunk access codes, authorization codes, international dialing prefixes, or anything that is not related to the normal form of the user’s phone number. If they are, it will cause problems with reverse number lookup, click-to-call dialing, international calling, least cost routing, and federated partner numbers.
I have seen a U.S. number normalized to something like +912065550100. Nine is a common outside line access code here in the U.S. and some people want to put the access codes into their normalized numbers so that the mediation server will send that to the IP-PBX. However, this will cause problems for reverse number lookup and for routing calls to India that has country code 91.
I have also seen numbers normalized to extensions like +8632. The ‘+’ sign signifies a “global” number and this is clearly not one. If the user has a DID, simply use that for their phone number specified as a full E.164 number. If not, options are provided by the RFC for specifying the extension with a DID number in a format like +12065550100;ext=8632.
Leaving off the country code assuming that you’ll only have to deal with in-country calls is equally wrong. I cringe when I see +2125550100 unless we’re referring to a number in Morocco.
If you build your OCS dial plan with anything less than E.164 today, then you limit your growth options later. Perhaps you have only a single mediation server connected directly to your corporate office PBX today. But, what about when you add a mediation server connected to the PSTN or PBX in another city or country where the numbering plan is different? Using E.164 in OCS lets conversion to locally-appropriate formats happen at the local gateway.
Similarly, not using E.164 will limit your ability to add SIP trunking. One deployment option with significant cost savings potential is to deploy OCS with two mediation servers: one connected to your PBX via a gateway for internal calls and the other connected to a SIP trunk for low cost external calling and new incoming DIDs. You'll need to be using E.164 for that type of routing.
If you federate with any partners, the presence information that you receive from them and that you send to them will include normalized phone numbers. Your user policies and routing must be able to handle their phone numbers. (And, conversely, their routing must be able to handle the normalized phone numbers you are passing to them.) If your (and their) OCS dial plan is not based on E.164, this will be problematic, at best.
Some may feel limited by this reliance on E.164 within OCS; I consider it an advantage. Routing is performed without consideration of the local format required to place the call. This is what provides the great flexibility in what you connect to the mediation server because your OCS dial plan does not need to accommodate any distinctions between gateways, IP-PBXes, or SIP trunks. The conversion to a locally-relevant dial string can be done where the local knowledge exists.
Ultimately, using global numbers makes your OCS dial plan much simpler than previously possible with an enterprise-wide PBX deployment. You could say this is another reason we don’t refer to OCS as an IP-PBX – it’s not a private branch exchange. It’s a distributed unified communications platform and demands a dial plan that recognizes that.
This post has been brought to you by the letter E and the numbers 1, 6, and 4.
The on-premise conferencing capability in Office Communications Server allows you to invite anonymous participants. These anonymous participants shouldn’t be allowed to have a meeting all by themselves, though. At least one authenticated enterprise user is required to be in the meeting.
With data conferencing in the Live Meeting Console, an anonymous participant can activate the conference. But — after a grace period — if no enterprise users join, the meeting will be terminated. Once the enterprise user does join, the meeting is safe. The enterprise user doesn’t have to be a presenter. A presenter will be needed to manipulate content in the meeting but the attendees can still talk to each other.
You would expect audio conferences to work similarly. (In an audio conference, the “presenters” are called “leaders.”) Except, there has been a bug in this feature until recently. (If you’d like more information on the OCS dial-in conferencing architecture, start here.)
The bug prevented the anonymous PSTN callers from being allowed into the meeting until a leader joined. Enterprise users that joined could talk to each other but the anonymous participants would continue to hear only music on hold until a leader joined.
The Conferencing Attendant fix just released will make the audio conferencing behavior consistent with the data conferencing behavior. Any authenticated enterprise participant that joins will start the audio conference and bring in the anonymous PSTN callers without the leader being present.
This fix is part of a big release of fixes for almost every component of OCS 2007 R2.
This post has been brought to you by the letters Q, F, and E.
A new feature in Office Communications Server 2007 R2 is PSTN dial-in to audio conferences. (OCS 2007 had audio conferencing. It just didn’t have an attendant to which you could dial-in, provide a conference ID, and be placed in the right conference.)
The most important features of a traditional reservationless audio bridge are provided by OCS. One of these important features is a conference ID that represents your personal audio conference. (You can have unique conference IDs for each of your calls. But, the default option when you schedule a meeting simply uses your assigned conference ID.)
I had a colleague recently tell me that her assigned OCS conference ID kept changing. This was wreaking havoc with her meetings because, for no apparent reason, the ID that the meeting was created with had become invalid.
I just learned this was another bug that was (at least partially) addressed in the OCS QFE released last week. The problem is with the Conferencing Add-in for Outlook. When you delete one occurrence of a recurring meeting that uses your default conference ID, the add-in mistakenly sends a command to delete that conference ID. This will make all the meetings that use that conference ID invalid.
The real fix will be made in some future version of the Conferencing Add-in. In the mean time, with these fixes, the server will ignore the incorrect conference delete commands. Now you can schedule OCS conference calls and be confident that your ID will work when you need it.
This post has been brought to you by Microsoft Update. Please update your servers!
If you’re installing Office Communications Server (or anything else, for that matter) on Windows Server 2008, you’ve probably been frustrated that the telnet client is no longer installed by default. Perhaps telnet isn’t the best troubleshooting tool. But, who hasn’t tried “telnet ocspool 5061” to quickly verify that the load balancer is at least doing something?
The typical method to install the telnet client involves starting Server Manager and (after waiting for it to start) choosing to Add Features. Stepping through the following wizard is easy enough, requiring only a few clicks.
A quicker method, though, for simply installing the telnet client is this command line:
ServerManagerCmd -i Telnet-Client
Note: This should be run from an elevated (“Run as administrator”) command prompt.
Before you complain that telnet should be installed by default, remember that security concerns are at play. This change is for the good. Reducing the number of features installed by default reduces the surface area for attack and minimizes the components that might require patching. Gone are the days when a default Windows Server installation includes a bunch of unneeded stuff.
This post has been brought to you by the Microsoft Trustworthy Computing Initiative.