industry
65 TopicsNeed an ISO8583 Application Switch for card transactions?
What is ISO8583: ISO 8583 Financial transaction card originated messages — Interchange message specifications is the International Organization for Standardization standard for systems that exchange electronic transactions made by cardholders using payment cards. The first two digits in the ISO8583 message aren't important. However, the next four are what tell us about the type of message we are processing. For more information: http://en.wikipedia.org/wiki/ISO_8583 Using the rule below as a template you should be able to dynamically switch any ISO8583 message to the desired server. See if this helps: when CLIENT_ACCEPTED{ TCP::collect } This section collects the first 6 bytes and then uses 'switch' to find a match. It allows to you decide where to send a request based on its message type. You could also use this to simply log without performing a pool selection. when CLIENT_DATA { log local0. "in CLIENT_DATA" set clientData [TCP::payload 6] log local0. "Client Data raw: $clientData" switch -glob $clientData{ "??0800"{ pool pool_EchoTestMessage log local0. "This is a Network Management Message." } "??0810"{pool pool_ForClientAuthorizations} } TCP::release } when SERVER_CONNECTED { TCP::collect } This section allows you to perform an action base on the message type of the response from the server. You could log the message type or even manipulate it before sending it out. when SERVER_DATA{ set serverData [TCP::payload 6] log local0. "Response Data raw: $serverData" switch -glob $serverData{ "??0810"{ log local0. "This is a Network Management Message." } "??0820"{log local0. "This is type XXX" } } TCP::release }845Views0likes3CommentsISO8583 payload interpreter/switch
The previous verion of ISO8583 switch only processed the MTI (Message Type Identifier). This version goes far beyond and dives into the bitmap and payload. What does it do: 1) It reads and interprets the ISO8583 bitmap 2) It calculate the offset based on the fields present in the message With these two points we now have access to the message payload allowing one to pick out client identifier or location information (bits 41 & 42) or anything else you want access to. This information can be used for simple logging, routing or anything else you might be after. The following rule grabs field 63. Being a variable length field, it must retrieve the field length from within the payload before being able to locate the desired field data. when RULE_INIT { Build list of Bitmap Attribute Lengths 'var' represents a variable length field set static::bmAttrLengths [list 64 LL 6 12 12 12 10 8 8 8 6 6 4 4 4 4 4 4 3 3 3 3 3 3 2 2 1 8 8 8 8 LL LL LL LL LLL 12 6 2 3 8 15 40 LL LL LLL LLL LLL 3 3 3 64 16 LLL LLL LLL 12 12 12 LLL LLL LLL LLL 64] } when CLIENT_ACCEPTED { TCP::collect } when CLIENT_DATA { set clientData [TCP::payload] log local0. "Client Data raw: $clientData" Collect the bitmap from the payload - it follows the MTI. binary scan [binary format H* [string range $clientData 6 21]] B* data Start the offset at 22 for MTA & BitMap padding set offset 22 set i 0 while { $i < [string length $data]} { if {[string index $data $i] == 1} { set attr [lindex $static::bmAttrLengths $i] if { $attr == "LL" } { This is a variable length field. The next 2 values in the string tell us how long the field is. set beginData [expr { $offset + 2 }] set endData [expr { $beginData + [scan [string range $clientData $offset [expr { $offset + 1 }]] %d ]}] log local0. "Value for the field length is: [string range $clientData $offset [expr { $offset + 1 }]]" log local0. "Value for the Field is: [string range $clientData $beginData $endData]" } elseif { $attr == "LLL" } { This is a variable length field. The next 3 values in the string tell us how long the field is. set beginData [expr { $offset + 3 }] set endData [expr { $beginData + [scan [string range $clientData $offset [expr { $offset + 2 }]] %d ]}] log local0. "Value for the field length is: [string range $clientData $offset [expr { $offset + 2 }]]" log local0. "Value for the Field is: [string range $clientData $beginData $endData]" } else { We got a 1 in the bitmap - increment the offset. incr offset [lindex $static::bmAttrLengths $i] } } incr i } TCP::release } Tester feedback welcom and encourage - I only have access to an ISO8583 emulator written in python.611Views0likes0CommentsCreating a proper RADIUS Accounting-Response packet in iRules
Creating a proper RADIUS Accounting-Response packet in iRules If you do a lot of work with RADIUS messages being sent to your BIGIP so that you can get some information from another network node in the system, you are going to need to respond back to that node in a correct and proper way, so that you don’t mess it up, or otherwise fill up its error log with ‘improper response’ messages. I was working on just that kind of iRule, and got it working. Here’s the code: 1: 2: RADIUS Acct-Resp packet 3: 4: input variables: 5: $rId -> RADIUS Request ID field 6: $rAuth -> RADIUS Request Authorization field 7: $static::SHARED_SECRET -> RADIUS Shared secret of the 2 nodes. 8: 9: UDP::drop ; kill the incoming packet, don’t need it. 10: set RADcode 5 ; RADIUS Accounting-Response Type code. 11: set md5hash [ format "05%02x00%02x" $rId 20 ] 12: set md5hash $md5hash$rAuth$static::SHARED_SECRET 13: set hash [ binary format H* $md5hash ] 14: set respAuth [md5 $hash] 15: set payldhdr [ binary format ccS $RADcode $rId 20 ] 16: set payload $payldhdr$respAuth 17: UDP::respond $payload So the RADIUS Accounting-Response packet has, at a minimum, four fields: RADIUS Type code(1 byte), ID number(1 byte), Packet Length(2 byte Integer), and the Authenticator(16 bytes). Getting the response authenticator correct is really the only tricky part. Line 5: The RADIUS Request ID field comes from the incoming packet. You can retrieve this value previously in the iRule using a line of code like this: set rId [RADIUS::id]. Of course, this value can also be pulled out at the same time some other important fields are decoded using the sample code for line 6 below. Line 6: The RADIUS Request Authorization field in the incoming packet is an MD5 hash of most if the incoming packet. To get this value, you will need to do a binary scan of the UDP packet: set payload [UDP::payload] binary scan $payload ccSH32a* rType rId rLen rAuth rPkt In this example, we also pull out the Type Code (rType) and the packet ID (rId), the length of the overall packet, the Authorization field that we are looking for, and the rest of the packet, which should be all the AVP fields. Line 9: We don’t need (and usually don’t want) the RADIUS Request packet from going on from the BIGIP, so we just drop the packet to prevent this. Line 10: 0x05 is the RADIUS Type Code for an Account-Response packet. Line 11: Here’s where we start working on our response authenticator. We are going to setup a hexstring (which is hex characters displayed as a string; IE> “05140016” is four bytes 0x05, 0x14, 0x00, 0x16), pack all of our values into it, convert it to real binary hex, do the MD5 hash on the result, and use the MD5 checksum result in the response packet. This line sets Type Code, id, and Length (hard coded to 20 bytes). Line 12: Using the hexstring from the last line, it adds the Original request Authenticator, and the shared secret (which should already be in hexstring format) to it. We now have our complete hexstring that needs to be run through the MD5 checksum function. Line 13: This line simply converts the hexstring to a binary hex value. Line 14: We get our valid Authenticator for the response. Line 15: Now we create the actual response packet. This line sets the first three fields: Type Code, id, and Length. Line 16: We add the header and the response Authenticator and we have our RADIUS Accounting-Response packet. Line 17: Send the response back. The RADIUS Accounting-Response protocol is documented in RFC-2866, Section 4.2.867Views0likes7CommentsRADIUS Load Balancing with iRules
What is RADIUS? “Remote Authentication Dial In User Service” or RADIUS is a very mature and widely implemented protocol for exchanging ”Triple A” or “Authentication, Authorization and Accounting” information. RADIUS is a relatively simple, transactional protocol. Clients, such as remote access server, FirePass, BIG-IP, etc. originate RADIUS requests (for example, to authenticate a user based on a user/password combination) and then wait for a response from the RADIUS server. Information is exchanged between a RADIUS client and server in the form of attributes. User-name, user-password, IP Address, port, and session state are all examples of attributes. Attributes can be in the format of text, string, IP address, integer or timestamp. Some attributes are variable in length, some are fixed. Why is protocol-specific support valuable? In typical UDP Load Balancing (not protocol-specific), there is one common challenge: if a client always sends requests with the same source port, packets will never be balanced across multiple servers. This behavior is the default for a UDP profile. To allow load balancing to work in this situation, using "Datagram LB" is the common recommendation or the use of an immediate session timeout. By using Datagram LB, every packet will be balanced. However, if a new request comes in before the reply for the previous request comes back from the server, BIG-IP LTM may change source port of that new request before forwards it to the server. This may result in an application not acting properly. In this later case, “Immediate timeout” must then be used. An additional virtual server may be needed for outbound traffic in order to route traffic back to the client. In short, to enable load balancing for RADIUS transaction-based traffic coming from the same source IP/source port, Datagram LB or immediate timeout should be employed. This configuration works in most cases. However, if the transaction requires more than 2 packets (1 request, 1 response), then, further BIG-IP LTM work is needed. An example where this is important occurs in RADIUS challenge/response handshakes, which require 4 packets: * Client ---- access-request ---> Server * Client <-- access-challenge --- Server * Client --- access-request ----> Server * Client <--- access-accept ----- Server For this traffic to succeed, all packets associated with the same transaction must be returned to the same server. In this case, custom layer 7 persistence is needed. iRules can provide the needed persistency. With iRules that understand the RADIUS protocol, BIG-IP LTM can direct traffic based on any attribute sent by client or persist sessions based on any attribute sent by client or server. Session management can then be moved to the BIG-IP, reducing server-side complexity. BIG-IP can provide almost unlimited intelligence in an iRule that can even re-calculate md5, modify usernames, detect realms, etc. BIG-IP LTM can also provide security at the application level of the RADIUS protocol, rejecting malformed traffic, denial of service attacks, or similar threats using customized iRules. Solution Datagram LB UDP profile or immediate timeout may be used if requests from client always use the same source IP/port. If immediate timeout is used, there should be an additional VIP for outbound traffic originated from server to client and also an appropriate SNAT (same IP as VIP). Identifier or some attributes can be used for Universal Inspection Engine (UIE) persistence. If immediate timeout/2-side-VIP technique are used, these should be used in conjunction with session command with "any" option. iRules 1) Here is a sample iRule which does nothing except decode and log some attribute information. This is a good example of the depth of fluency you can achieve via an iRule dealing with RADIUS. when RULE_INIT { array set ::attr_code2name { 1 User-Name 2 User-Password 3 CHAP-Password 4 NAS-IP-Address 5 NAS-Port 6 Service-Type 7 Framed-Protocol 8 Framed-IP-Address 9 Framed-IP-Netmask 10 Framed-Routing 11 Filter-Id 12 Framed-MTU 13 Framed-Compression 14 Login-IP-Host 15 Login-Service 16 Login-TCP-Port 17 (unassigned) 18 Reply-Message 19 Callback-Number 20 Callback-Id 21 (unassigned) 22 Framed-Route 23 Framed-IPX-Network 24 State 25 Class 26 Vendor-Specific 27 Session-Timeout 28 Idle-Timeout 29 Termination-Action 30 Called-Station-Id 31 Calling-Station-Id 32 NAS-Identifier 33 Proxy-State 34 Login-LAT-Service 35 Login-LAT-Node 36 Login-LAT-Group 37 Framed-AppleTalk-Link 38 Framed-AppleTalk-Network 39 Framed-AppleTalk-Zone 60 CHAP-Challenge 61 NAS-Port-Type 62 Port-Limit 63 Login-LAT-Port } } when CLIENT_ACCEPTED { binary scan [UDP::payload] cH2SH32cc code ident len auth \ attr_code1 attr_len1 log local0. "code = $code" log local0. "ident = $ident" log local0. "len = $len" log local0. "auth = $auth" set index 22 while { $index < $len } { set hsize [expr ( $attr_len1 - 2 ) * 2] switch $attr_code1 { 11 - 1 { binary scan [UDP::payload] @${index}a[expr $attr_len1 - 2]cc \ attr_value attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } 9 - 8 - 4 { binary scan [UDP::payload] @${index}a4cc rawip \ attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) =\ [IP::addr $rawip mask 255.255.255.255]" } 13 - 12 - 10 - 7 - 6 - 5 { binary scan [UDP::payload] @${index}Icc attr_value \ attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } default { binary scan [UDP::payload] @${index}H${hsize}cc \ attr_value attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } } set index [ expr $index + $attr_len1 ] set attr_len1 $attr_len2 set attr_code1 $attr_code2 } } when SERVER_DATA { binary scan [UDP::payload] cH2SH32cc code ident len auth \ attr_code1 attr_len1 log local0. "code = $code" log local0. "ident = $ident" log local0. "len = $len" log local0. "auth = $auth" set index 22 while { $index < $len } { set hsize [expr ( $attr_len1 - 2 ) * 2] switch $attr_code1 { 11 - 1 { binary scan [UDP::payload] @${index}a[expr $attr_len1 - 2]cc \ attr_value attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } 9 - 8 - 4 { binary scan [UDP::payload] @${index}a4cc rawip \ attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) =\ [IP::addr $rawip mask 255.255.255.255]" } 13 - 12 - 10 - 7 - 6 - 5 { binary scan [UDP::payload] @${index}Icc attr_value \ attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } default { binary scan [UDP::payload] @${index}H${hsize}cc \ attr_value attr_code2 attr_len2 log local0. " $::attr_code2name($attr_code1) = $attr_value" } } set index [ expr $index + $attr_len1 ] set attr_len1 $attr_len2 set attr_code1 $attr_code2 } } This iRule could be applied to many areas of interest where a particular value needs to be extracted. For example, the iRule could detect the value of specific attributes or realm and direct traffic based on that information. 2) This second iRule allows UDP Datagram LB to work with 2 factor authentication. Persistence in this iRule is based on "State" attribute (value = 24). Another great example of the kinds of things you can do with an iRule, and how deep you can truly dig into a protocol. when CLIENT_ACCEPTED { binary scan [UDP::payload] ccSH32cc code ident len auth \ attr_code1 attr_len1 set index 22 while { $index < $len } { set hsize [expr ( $attr_len1 - 2 ) * 2] binary scan [UDP::payload] @${index}H${hsize}cc attr_value \ attr_code2 attr_len2 # If it is State(24) attribute... if { $attr_code1 == 24 } { persist uie $attr_value 30 return } set index [ expr $index + $attr_len1 ] set attr_len1 $attr_len2 set attr_code1 $attr_code2 } } when SERVER_DATA { binary scan [UDP::payload] ccSH32cc code ident len auth \ attr_code1 attr_len1 # If it is Access-Challenge(11)... if { $code == 11 } { set index 22 while { $index < $len } { set hsize [expr ( $attr_len1 - 2 ) * 2] binary scan [UDP::payload] @${index}H${hsize}cc attr_value \ attr_code2 attr_len2 if { $attr_code1 == 24 } { persist add uie $attr_value 30 return } set index [ expr $index + $attr_len1 ] set attr_len1 $attr_len2 set attr_code1 $attr_code2 } } } Conclusion With iRules, BIG-IP can understand RADIUS packets and make intelligent decisions based on RADIUS protocol information. Additionally, it is also possible to manipulate RADIUS packets to meet nearly any application need. Contributed by: Nat Thirasuttakorn Get the Flash Player to see this player.2.7KViews0likes4CommentsThe (hopefully) definitive guide to load balancing Lync Edge Servers with a Hardware Load Balancer
Having worked on a few large Lync deployments recently, I have realized that there is still a lot of confusion around properly architecting the network for load balancing Lync Edge Servers. Guidance on this subject has changed from OCS 2007 to OCS 2007 R2 and now to Lync Server 2010, and it's important that care is taken while planning the design. It's also important to know that although a certain architecture may seem to work, it could be very far from best practice. I'll explain what I mean by that below. The main purpose of Edge Services is to allow remote (whether they are corporate, anonymous, federated, etc) users to communicate with other external/internal users and vice versa. If you're looking to extend your Lync deployment to support communication with federated partners, public IM services, remote users and such, then you'll want to make sure you deploy your Edge Servers properly. This post will discuss some requirements and best practices for deploying Edge Servers, and then we'll go into some suggested architectures. For this discussion, let's assume that there are 3 device types within your DMZ; your firewall, your BIG-IP LTM, and your Lync Edge Server farm. Requirement 1: Your Edge Servers need at least 2 network interfaces; one or more dedicated to the external network, and one dedicated to the internal. The external and internal interfaces need to be on separate IP networks. The Edge Server will host 3 separate external services; Access, Web Conferencing, and Audio/Visual (A/V). If you plan on exposing all 3 services for remote users, you have a choice of using one IP for all 3 services on each server and differentiate them by TCP/UDP port value, or go with a separate IP for each service and use standard ports. Best Practice: This is more preference than best practice, but I like to use 3 separate IPs for these services. With alternative ports/port mapping, you can consolidate to a single IP, but unless you have a very specific reason for doing so, its best to stick with 3 separate IPs. You do burn more IPs by doing this, but you'll have to use non-standard ports for certain services if you use a single IP, and this could lead to issues with certain network devices that like certain traffic types on certain ports. Plus, troubleshooting, traffic statistics, logging are all cleaner if you are using 3 separate IPs. Requirement 2: Traffic that is load balanced to the Lync Edge servers needs to return through the load balancer. In other words, if the hardware load balancer sends traffic to an Edge Server, the return traffic from that Edge Server needs to flow back through the load balancer. There are 2 common ways to ensure that return traffic flows through the load balancer. You can… Use routing, and have the Edge Servers point to the load balancer as their default gateway. Enable SNAT on the load balancer, which rewrites the source IP of the connection to a local network address as the traffic passes through the load balancer. In this case, the Edge Servers will believe that a local client generated the connection and send the responses back to that local address. So there are your two options, which I will refer to as Routing and SNATting. With Routing, your Edge Server will rely on its routing table to route the return traffic out through the load balancer. No obscuring of the source IP address will happen on the load balancer, but you will have to make sure your default gateway & routing tables are correct. With SNATting, you can ensure return traffic goes back through the load balancer and not have to worry about the routing table to take care of this. The drawback to SNATting is that the load balancer will obscure the source IP of the packet as it passes through the load balancer. I will explain below why the SNAT idea is less than ideal, primarily for A/V traffic. Best Practice: You can SNAT traffic to the Web Conferencing and Access services on the Edge Server, but do not SNAT traffic to the A/V Edge Services. By obscuring the client's IP Address when using SNAT, you limit the ability for the A/V Services to connect clients directly to each other, and this is important when clients try to set up peer 2 peer communication, such as a phone call. When using SNAT, The A/V services will not see the client's true IP, so the likelihood of the Edge Server being able to orchestrate the 2 clients to communicate directly with each other is reduced to nil. You'll force the A/V services to utilize its fallback method, in which the P2P traffic will actually have to use the A/V server as a proxy between the 2 clients. Now this 'proxy' fallback mode will still happen from time to time even when your not SNATting at the BIG-IP (for example, multiparty calls will always use 'proxy'), but when you can, its best to minimize the times that users have to leverage this fallback method. So even though SNATting connections to the A/V Edge Service will seem to work, it is far from desirable from a network perspective! FYI - Every load balanced service in a Lync Environment (including Lync FE's, Directors, etc) can be SNAT'ed except for the A/V Edge Service. Requirement 3: Certain connections will need to be load balanced to the Edge Services, while certain connections will need to be made directly to those Edge Services. Best Practice: Make sure clients can connect to the Virtual IP(s) that are load balancing the Edge Services, as well as make sure that clients can connect directly to the Edge Servers themselves. Typically users will hit the load balancer on their first incoming connection and get load balanced, but if a user gets invited to a media session that has started on an Edge Server, the invite they receive will point them directly to that server. NAT awareness was built into Lync 2010 to help in environments in which Edge Servers are deployed behind NATs. By enabling the NAT awareness, Edge Servers will refer clients to their respective NAT address in order to route the users in correctly. Do I need to use routable IPs on the external interface of my Edge Servers? Microsoft says you do, and I would recommend doing so if you can. I have worked on deployments where non-routable IPs are being used (leveraging NATs to allow direct access) and not run into any issues. Just be sure that the Edge Servers are aware of their NAT address. Best Practice: Suggested Deployment "DNAT in, SNAT out" on the Load Balancer ”DSNAT in, SNAT out” was derived from discussions with a certain MSFT engineer who helped me build this guidance. I’d love to give him credit (he knows Lync networking better than anyone I have ever talked to!!), but if named this person, his/her phone would never stop ringing for architecture guidance !!. Back to the subject, if you keep to "DNAT in, and SNAT out” for external-side Lync Edge traffic, your deployment will work! It sums it up very well! So you're ready to architect your Edge Server Deployment. Lets take all the information from above and build a deployment. Keep these things mind….. External Side of the Edge Servers -Plan for VIPs on your BIG-IP to load balance the 3 external services that your Edge Server Provides (Access, WebConferencing, A/V) -Plan for direct (non-load balanced) access to your Edge Servers by external clients -Plan a method to allow Edge Servers to make outbound connections (forwarding VIP or SNAT on BIG-IP) -Point the Edge Server's Default Gateway to the Self IP of the BIG-IP -Point the BIG-IP's Default Gateway to the Router -Do not SNAT traffic to the A/V Services on the Edge Servers If you use non-routable IPs on the external Interfaces of the Edge Servers, create a NAT on the BIG-IP for each Edge Server. Make sure the Edge Servers are aware of these NAT addresses so they can hand them out to clients who need to connect directly to Edge Server. Internal Side of the Edge Servers -Plan for VIPs on your BIG-IP to load balance ports 443, 3478, 5061, and 5062 on the internal interfaces of your Edge Servers -Plan for direct (non-load balanced) access to your Edge Servers -Make sure your Edge Servers have routes to the internal network(s) -You can SNAT traffic to the internal interface of the Edge Servers I'll leave you with an example of a fully supported configuration (i.e. using routable IP Addresses all around). Keep in mind, this is not the only way to architect this, but if you have the available public IP address space, this will work. Wow… so much for a short post. I welcome any and all feedback, and I promise to update this post with new information as it comes in. I'll also augment this post with more details & deployments as I find time to write them up, so check back for updates. This may even end up as a guide some day! Version 1.0 date 7/14/2011 Version 1.1 date 2/15/2011 - Fixed a few typos. Fixed some heinous formatting1.3KViews0likes8CommentsThe Challenges of SQL Load Balancing
#infosec #iam load balancing databases is fraught with many operational and business challenges. While cloud computing has brought to the forefront of our attention the ability to scale through duplication, i.e. horizontal scaling or “scale out” strategies, this strategy tends to run into challenges the deeper into the application architecture you go. Working well at the web and application tiers, a duplicative strategy tends to fall on its face when applied to the database tier. Concerns over consistency abound, with many simply choosing to throw out the concept of consistency and adopting instead an “eventually consistent” stance in which it is assumed that data in a distributed database system will eventually become consistent and cause minimal disruption to application and business processes. Some argue that eventual consistency is not “good enough” and cite additional concerns with respect to the failure of such strategies to adequately address failures. Thus there are a number of vendors, open source groups, and pundits who spend time attempting to address both components. The result is database load balancing solutions. For the most part such solutions are effective. They leverage master-slave deployments – typically used to address failure and which can automatically replicate data between instances (with varying levels of success when distributed across the Internet) – and attempt to intelligently distribute SQL-bound queries across two or more database systems. The most successful of these architectures is the read-write separation strategy, in which all SQL transactions deemed “read-only” are routed to one database while all “write” focused transactions are distributed to another. Such foundational separation allows for higher-layer architectures to be implemented, such as geographic based read distribution, in which read-only transactions are further distributed by geographically dispersed database instances, all of which act ultimately as “slaves” to the single, master database which processes all write-focused transactions. This results in an eventually consistent architecture, but one which manages to mitigate the disruptive aspects of eventually consistent architectures by ensuring the most important transactions – write operations – are, in fact, consistent. Even so, there are issues, particularly with respect to security. MEDIATION inside the APPLICATION TIERS Generally speaking mediating solutions are a good thing – when they’re external to the application infrastructure itself, i.e. the traditional three tiers of an application. The problem with mediation inside the application tiers, particularly at the data layer, is the same for infrastructure as it is for software solutions: credential management. See, databases maintain their own set of users, roles, and permissions. Even as applications have been able to move toward a more shared set of identity stores, databases have not. This is in part due to the nature of data security and the need for granular permission structures down to the cell, in some cases, and including transactional security that allows some to update, delete, or insert while others may be granted a different subset of permissions. But more difficult to overcome is the tight-coupling of identity to connection for databases. With web protocols like HTTP, identity is carried along at the protocol level. This means it can be transient across connections because it is often stuffed into an HTTP header via a cookie or stored server-side in a session – again, not tied to connection but to identifying information. At the database layer, identity is tightly-coupled to the connection. The connection itself carries along the credentials with which it was opened. This gives rise to problems for mediating solutions. Not just load balancers but software solutions such as ESB (enterprise service bus) and EII (enterprise information integration) styled solutions. Any device or software which attempts to aggregate database access for any purpose eventually runs into the same problem: credential management. This is particularly challenging for load balancing when applied to databases. LOAD BALANCING SQL To understand the challenges with load balancing SQL you need to remember that there are essentially two models of load balancing: transport and application layer. At the transport layer, i.e. TCP, connections are only temporarily managed by the load balancing device. The initial connection is “caught” by the Load balancer and a decision is made based on transport layer variables where it should be directed. Thereafter, for the most part, there is no interaction at the load balancer with the connection, other than to forward it on to the previously selected node. At the application layer the load balancing device terminates the connection and interacts with every exchange. This affords the load balancing device the opportunity to inspect the actual data or application layer protocol metadata in order to determine where the request should be sent. Load balancing SQL at the transport layer is less problematic than at the application layer, yet it is at the application layer that the most value is derived from database load balancing implementations. That’s because it is at the application layer where distribution based on “read” or “write” operations can be made. But to accomplish this requires that the SQL be inline, that is that the SQL being executed is actually included in the code and then executed via a connection to the database. If your application uses stored procedures, then this method will not work for you. It is important to note that many packaged enterprise applications rely upon stored procedures, and are thus not able to leverage load balancing as a scaling option. Depending on your app or how your organization has agreed to protect your data will determine which of these methods are used to access your databases. The use of inline SQL affords the developer greater freedom at the cost of security, increased programming(to prevent the inherent security risks), difficulty in optimizing data and indices to adapt to changes in volume of data, and deployment burdens. However there is lively debate on the values of both access methods and how to overcome the inherent risks. The OWASP group has identified the injection attacks as the easiest exploitation with the most damaging impact. This also requires that the load balancing service parse MySQL or T-SQL (the Microsoft Transact Structured Query Language). Databases, of course, are designed to parse these string-based commands and are optimized to do so. Load balancing services are generally not designed to parse these languages and depending on the implementation of their underlying parsing capabilities, may actually incur significant performance penalties to do so. Regardless of those issues, still there are an increasing number of organizations who view SQL load balancing as a means to achieve a more scalable data tier. Which brings us back to the challenge of managing credentials. MANAGING CREDENTIALS Many solutions attempt to address the issue of credential management by simply duplicating credentials locally; that is, they create a local identity store that can be used to authenticate requests against the database. Ostensibly the credentials match those in the database (or identity store used by the database such as can be configured for MSSQL) and are kept in sync. This obviously poses an operational challenge similar to that of any distributed system: synchronization and replication. Such processes are not easily (if at all) automated, and rarely is the same level of security and permissions available on the local identity store as are available in the database. What you generally end up with is a very loose “allow/deny” set of permissions on the load balancing device that actually open the door for exploitation as well as caching of credentials that can lead to unauthorized access to the data source. This also leads to potential security risks from attempting to apply some of the same optimization techniques to SQL connections as is offered by application delivery solutions for TCP connections. For example, TCP multiplexing (sharing connections) is a common means of reusing web and application server connections to reduce latency (by eliminating the overhead associated with opening and closing TCP connections). Similar techniques at the database layer have been used by application servers for many years; connection pooling is not uncommon and is essentially duplicated at the application delivery tier through features like SQL multiplexing. Both connection pooling and SQL multiplexing incur security risks, as shared connections require shared credentials. So either every access to the database uses the same credentials (a significant negative when considering the loss of an audit trail) or we return to managing duplicate sets of credentials – one set at the application delivery tier and another at the database, which as noted earlier incurs additional management and security risks. YOU CAN’T WIN FOR LOSING Ultimately the decision to load balance SQL must be a combination of business and operational requirements. Many organizations successfully leverage load balancing of SQL as a means to achieve very high scale. Generally speaking the resulting solutions – such as those often touted by e-Bay - are based on sound architectural principles such as sharding and are designed as a strategic solution, not a tactical response to operational failures and they rarely involve inspection of inline SQL commands. Rather they are based on the ability to discern which database should be accessed given the function being invoked or type of data being accessed and then use a traditional database connection to connect to the appropriate database. This does not preclude the use of application delivery solutions as part of such an architecture, but rather indicates a need to collaborate across the various application delivery and infrastructure tiers to determine a strategy most likely to maintain high-availability, scalability, and security across the entire architecture. Load balancing SQL can be an effective means of addressing database scalability, but it should be approached with an eye toward its potential impact on security and operational management. What are the pros and cons to keeping SQL in Stored Procs versus Code Mission Impossible: Stateful Cloud Failover Infrastructure Scalability Pattern: Sharding Streams The Real News is Not that Facebook Serves Up 1 Trillion Pages a Month… SQL injection – past, present and future True DDoS Stories: SSL Connection Flood Why Layer 7 Load Balancing Doesn’t Suck Web App Performance: Think 1990s.2.3KViews0likes1CommentBig-IP and ADFS (SCRATCH THAT! Big-IP and SAML) with Office 365 – Part 5
The BIG-IP with APM has now become SAML, (claims) aware! “SAML” not “self-aware”. No need to start worrying about Skynet and Arnold Schwarzenegger kicking in your door, (except for you Sarah Connor). This is a good thing! If you need to federate your organization with Office 365, this is a very good thing. With the release of ver. 11.3, BIG-IP with APM, (Access Policy Manager) now includes full SAML support on the box. What does that mean? Well, rather than relying upon an external resource such as ADFS to issue or security tokens, (used to present/consume claims with a federation partner), the BIG-IP becomes the federation endpoint for the organization. Check out here for more information on federation. When it comes to Office 365, not only has the infrastructure required to federate your organization been dramatically reduced, the configuration required has been simplified. Available in our community codeshare forum is an iApp as well as guidance specifically designed for deploying the BIG-IP as a federation IdP, (identity provider) for Office 365. Now federating with Office 365 is as simple as answering a few questions and entering a few PowerShell commands to configure the Office 365 side. To gain a better understanding of how we arrived here, (replacing ADFS), as well as illustrating the benefit let’s take a look at the “Evolution of Solution”…development. Saying Goodbye to ADFS Ensuring a Highly Available Architecture Throughout this series, (links below), we’ve taken a look at how the F5 BIG-IP can add value and enhance to and ADFS, (Active Directory Federation Services). To get the ball rolling we looked at how the BIG-IP was able to provide for a highly-available and scalable ADFS infrastructure, (refer to Figure 1). This included ensuring the ADFS proxy farm, located in the perimeter network, as well as the internal ADFS farm was available and the traffic is optimized. BIG-IP enhancements to the ADFS federation process: • Intelligent traffic management • Advanced L7 health monitoring – (Ensures the ADFS service is responding) • Cookie-based persistence Enhancing Security and Streamlining ADFS Building upon the previous solution, (load balancing the ADFS and ADFS Proxy layers), we implemented APM, (Access Policy Manager), (refer to Figure 2). By implementing APM on the F5 appliance(s) we not only eliminated the need for these additional servers but, by implementing pre-authentication at the perimeter and advanced features such as client-side checks, (antivirus validation, firewall verification, etc.), arguably provided for a more secure deployment. Additional BIG-IP enhancements to the ADFS federation process: •Enhanced Security •Variety of authentication methods •Client endpoint inspection •Multi-factor authentication •Improved User Experience •SSO across on-premise and cloud-based applications •Single-URL access for hybrid deployments •Simplified Architecture •Removes the ADFS proxy farm layer as well as the need to load balance the proxy farm Eliminating the ADFS Infrastructure Available with version 11.3, APM includes full SAML support. This allows the BIG-IP to not only authenticate the client connections with Active Directory, but act as the IdP or SP in the federation process. No longer will an organization be required to deploy an ADFS infrastructure for federation. Rather, the BIG-IP’s role as an application delivery controller is expanded out to include cloud-based resources, (including Office 365), as well as on-premise applications. Additional BIG-IP enhancements to the ADFS federation process: •Ability to act as IDP, (Identity Provider) for access to external claims-based resources including Office 365 •Act as service provider, (SP) to facilitate federated access to on-premise applications •Streamlined architecture, (no need for the ADFS architecture) •Simplified iApp deployment Figure 3 shows a typical Office 365 client access process utilizing APM and SAML. Additional Links: Big-IP APM as SAML 2.0 IdP from Microsoft Office 365 SAML Federation with the BIG-IP Big-IP and ADFS Part 1 – “Load balancing the ADFS Farm” Big-IP and ADFS Part 2 – “APM–An Alternative to the ADFS Proxy” Big-IP and ADFS Part 3 – “ADFS, APM, and the Office 365 Thick Clients” Big-IP and ADFS Part 4 – “What about Single Sign-Out?” BIG-IP Access Policy Manager (APM) Wiki Home - DevCentral Wiki Latest F5 Information F5 News Articles F5 Press Releases F5 Events F5 Web Media F5 Technology Alliance Partners F5 YouTube Feed1.1KViews0likes3CommentsOne Time Passwords via an SMS Gateway with BIG-IP Access Policy Manager
One time passwords, or OTP, are used (as the name indicates) for a single session or transaction. The plus side is a more secure deployment, the downside is two-fold—first, most solutions involve a token system, which is costly in management, dollars, and complexity, and second, people are lousy at remembering things, so a delivery system for that OTP is necessary. The exercise in this tech tip is to employ BIG-IP APM to generate the OTP and pass it to the user via an SMS Gateway, eliminating the need for a token creating server/security appliance while reducing cost and complexity. Getting Started This guide was developed by F5er Per Boe utilizing the newly released BIG-IP version 10.2.1. The “-secure” option for the mcget command is new in this version and is required in one of the steps for this solution. Also, this solution uses the Clickatell SMS Gateway to deliver the OTPs. Their API is documented at http://www.clickatell.com/downloads/http/Clickatell_HTTP.pdf. Other gateway providers with a web-based API could easily be substituted. Also, there are steps at the tail end of this guide to utilize the BIG-IP’s built-in mail capabilities to email the OTP during testing in lieu of SMS. The process in delivering the OTP is shown in Figure 1. First a request is made to the BIG-IP APM. The policy is configured to authenticate the user’s phone number in Active Directory, and if successful, generate a OTP and pass along to the SMS via the HTTP API. The user will then use the OTP to enter into the form updated by APM before allowing the user through to the server resources. BIG-IP APM Configuration Before configuring the policy, an access profile needs to be created, as do a couple authentication servers. First, let’s look at the authentication servers Authentication Servers To create servers used by BIG-IP APM, navigate to Access Policy->AAA Servers and then click create. This profile is simple, supply your domain server, domain name, and admin username and password as shown in Figure 2. The other authentication server is for the SMS Gateway, and since it is an HTTP API we’re using, we need the HTTP type server as shown in Figure 3. Note that the hidden form values highlighted in red will come from your Clickatell account information. Also note that the form method is GET, the form action references the Clickatell API interface, and that the match type is set to look for a specific string. The Clickatell SMS Gateway expects the following format: https://api.clickatell.com/http/sendmsg?api_id=xxxx&user=xxxx&password=xxxx&to=xxxx&text=xxxx Finally, successful logon detection value highlighted in red at the bottom of Figure 3 should be modified to response code returned from SMS Gateway. Now that the authentication servers are configured, let’s take a look at the access profile and create the policy. Access Profile & Policy Before we can create the policy, we need an access profile, shown below in Figure 4 with all default settings. Now that that is done, we click on Edit under the Access Policy column highlighted in red in Figure 5. The default policy is bare bones, or as some call it, empty. We’ll work our way through the objects, taking screen captures as we go and making notes as necessary. To add an object, just click the “+” sign after the Start flag. The first object we’ll add is a Logon Page as shown in Figure 6. No modifications are necessary here, so you can just click save. Next, we’ll configure the Active Directory authentication, so we’ll add an AD Auth object. Only setting here in Figure 7 is selecting the server we created earlier. Following the AD Auth object, we need to add an AD Query object on the AD Auth successful branch as shown in Figures 8 and 9. The server is selected in the properties tab, and then we create an expression in the branch rules tab. To create the expression, click change, and then select the Advanced tab. The expression used in this AD Query branch rule: expr { [mcget {session.ad.last.attr.mobile}] != "" } Next we add an iRule Event object to the AD Query OK branch that will generate the one time password and provide logging. Figure 10 Shows the iRule Event object configuration. The iRule referenced by this event is below. The logging is there for troubleshooting purposes, and should probably be disabled in production. 1: when ACCESS_POLICY_AGENT_EVENT { 2: expr srand([clock clicks]) 3: set otp [string range [format "%08d" [expr int(rand() * 1e9)]] 1 6 ] 4: set mail [ACCESS::session data get "session.ad.last.attr.mail"] 5: set mobile [ACCESS::session data get "session.ad.last.attr.mobile"] 6: set logstring mail,$mail,otp,$otp,mobile,$mobile 7: ACCESS::session data set session.user.otp.pw $otp 8: ACCESS::session data set session.user.otp.mobile $mobile 9: ACCESS::session data set session.user.otp.username [ACCESS::session data get "session.logon.last.username"] 10: log local0.alert "Event [ACCESS::policy agent_id] Log $logstring" 11: } 12: 13: when ACCESS_POLICY_COMPLETED { 14: log local0.alert "Result: [ACCESS::policy result]" 15: } On the fallback path of the iRule Event object, add a Variable Assign object as show in Figure 10b. Note that the first assignment should be set to secure as indicated in image with the [S]. The expressions in Figure 10b are: session.logon.last.password = expr { [mcget {session.user.otp.pw}]} session.logon.last.username = expr { [mcget {session.user.otp.mobile}]} On the fallback path of the AD Query object, add a Message Box object as shown in Figure 11 to alert the user if no mobile number is configured in Active Directory. On the fallback path of the Event OTP object, we need to add the HTTP Auth object. This is where the SMS Gateway we configured in the authentication server is referenced. It is shown in Figure 12. On the fallback path of the HTTP Auth object, we need to add a Message Box as shown in Figure 13 to communicate the error to the client. On the Successful branch of the HTTP Auth object, we need to add a Variable Assign object to store the username. A simple expression and a unique name for this variable object is all that is changed. This is shown in Figure 14. On the fallback branch of the Username Variable Assign object, we’ll configure the OTP Logon page, which requires a Logon Page object (shown in Figure 15). I haven’t mentioned it yet, but the name field of all these objects isn’t a required change, but adding information specific to the object helps with readability. On this form, only one entry field is required, the one time password, so the second password field (enabled by default) is set to none and the initial username field is changed to password. The Input field below is changed to reflect the type of logon to better queue the user. Finally, we’ll finish off with an Empty Action object where we’ll insert an expression to verify the OTP. The name is configured in properties and the expression in the branch rules, as shown in Figures 16 and 17. Again, you’ll want to click advanced on the branch rules to enter the expression. The expression used in the branch rules above is: expr { [mcget {session.user.otp.pw}] == [mcget -secure {session.logon.last.otp}] } Note again that the –secure option is only available in version 10.2.1 forward. Now that we’re done adding objects to the policy, one final step is to click on the Deny following the OK branch of the OTP Verify Empty Action object and change it from Deny to Allow. Figure 18 shows how it should look in the visual policy editor window. Now that the policy is completed, we can attach the access profile to the virtual server and test it out, as can be seen in Figures 19 and 20 below. Email Option If during testing you’d rather send emails than utilize the SMS Gateway, then configure your BIG-IP for mail support (Solution 3664), keep the Logging object, lose the HTTP Auth object, and configure the system with this script to listen for the messages sent to /var/log/ltm from the configured Logging object: #!/bin/bash while true do tail -n0 -f /var/log/ltm | while read line do var2=`echo $line | grep otp | awk -F'[,]' '{ print $2 }'` var3=`echo $line | grep otp | awk -F'[,]' '{ print $3 }'` var4=`echo $line | grep otp | awk -F'[,]' '{ print $4 }'` if [ "$var3" = "otp" -a -n "$var4" ]; then echo Sending pin $var4 to $var2 echo One Time Password is $var4 | mail -s $var4 $var2 fi done done The log messages look like this: Jan 26 13:37:24 local/bigip1 notice apd[4118]: 01490113:5: b94f603a: session.user.otp.log is mail,user1@home.local,otp,609819,mobile,12345678 The output from the script as configured looks like this: [root@bigip1:Active] config # ./otp_mail.sh Sending pin 239272 to user1@home.local Conclusion The BIG-IP APM is an incredibly powerful tool to add to the LTM toolbox. Whether using the mail system or an SMS gateway, you can take a bite out of your infrastructure complexity by using this solution to eliminate the need for a token management service. Many thanks again to F5er Per Boe for this excellent solution!6.5KViews0likes23CommentsSingle-Sign-On mit Kerberos Constrained Delegation, Teil 2 - Debugging
Hallo liebe Leser, in meinem letzten Beitrag bin ich auf die Kerberos Constrained Delegation Konfiguration eingegangen und hatte darin bereits versprochen, in diesem Beitrag das Debugging als Thema zu wählen. Dadurch, dass wir Abhängigkeiten mit anderen Komponenten haben, wird das Debuggen sicher nicht einfacher. Grundsätzlich sollte im Fehlerfall aber überprüft werden, ob die BIG-IP denn die Active Directory (AD) Infrastruktur erfolgreich erreichen kann und ob die Zeit der BIG-IP auch gleich der des Key Distribution Center (KDC) ist. Hier hilft auf dem Command Line Interface (CLI) der Befehl „ntpq –pn“ um zu überprüfen, ob die Zeit richtig ist: Die Namensauflösung ist enorm wichtig bei Kerberos, da es davon abhängig ist. Ebenso auch die Reverse-DNS Auflösung, da dies auch verwendet wird um den SPN (Service Principal Name) für jeden Server nach der Loadbalancing Entscheidung zu bestimmen. Sollten die Namen nicht richtig im DNS eingetragen sein, so kann man diese auch auf der BIG-IP statisch hinterlegen. Das ist aber nur ein Workaround und sollte eigentlich vermieden werden. Hier ein Beispiel um einen Eintrag zu setzen: # tmsh sys global-settings remote-host add { server1 { addr 1.1.1.1 hostname sven } } Natürlich ist das auch über die GUI möglich. Hier nun ein paar Beispiele, wie man die Namensauflösung überprüfen kann. Der Befehl „nslookup“ hilft einem dabei: [root@bigip1-ve:Active] config # nslookup www.example.com Server: 10.0.0.25 Address: 10.0.0.25#53 Name: www.example.com Address: 10.0.0.250 [root@bigip1-ve:Active] config # nslookup 10.0.0.250 Server: 10.0.0.25 Address: 10.0.0.25#53 250.0.0.10.in-addr.arpa name = www.example.com. [root@bigip1-ve:Active] config # nslookup w2008r2.example.com Server: 10.0.0.25 Address: 10.0.0.25#53 ** server can't find w2008r2.example.com: NXDOMAIN [root@bigip1-ve:Active] config # nslookup 10.0.0.26 Server: 10.0.0.25 Address: 10.0.0.25#53 26.0.0.10.in-addr.arpa name = win2008r2.example.com. Da Kerberos SSO sich für die KDC-Ermittlung auf DNS verlässt (sofern hier keine Adresse in der SSO Konfiguration eingetragen wurde), sollte der DNS-Server auch SRV-Records haben, die auf den KDC-Server für den Realm der Domain zeigen. Wir erinnern uns hier, dass ich dies in der Konfiguration des letzten Blogs eingetragen habe. Die Begründung war, dass es dann schneller geht: Schließlich erspart man sich genau diese Auflöse-Prozedur an der Stelle. [root@bigip1-ve:Active] config # nslookup -type=srv _kerberos._tcp.example.com Server: 10.0.0.25 Address: 10.0.0.25#53 _kerberos._tcp.example.com service = 0 100 88 win2008r2.example.com. [root@bigip1-ve:Active] config # nslookup -type=srv _kerberos._udp.example.com Server: 10.0.0.25 Address: 10.0.0.25#53 _kerberos._udp.example.com service = 0 100 88 win2008r2.example.com. Sind diese grundlegenden Konfigurationen nun überprüft und korrekt, aber es funktioniert noch nicht, hilft ein Blick in das APM Logfile. Vorher sollte aber der Debug-Level höher eingestellt werden. Dies bitte nur während des debuggens machen und anschließend wieder zurück stellen. Im Menü kann man unter System/Logs/Configuration/Options den Level einstellen. „Informational“ ist hier ein guter Start. „Debug“ kann man sicher auch verwenden, aber der Level ist schon extrem gesprächig und in der Regel reicht „Informational“ vollkommen. Schauen wir uns doch mal einen Ausschnitt eines Anmeldeprozesses an. Oct 28 12:06:46 bigip1-ve debug /usr/bin/websso[400]: 01490000:7: <0xf1c75b90>:Modules/HttpHeaderBased/Kerberos.cpp:862 Initialized UCC:user1@EXAMPLE.COM@EXAMPLE.COM, lifetime:36000 kcc:0x8ac52f0 Oct 28 12:06:46 bigip1-ve debug /usr/bin/websso[400]: 01490000:7: <0xf1c75b90>:Modules/HttpHeaderBased/Kerberos.cpp:867 UCCmap.size = 1, UCClist.size = 1 Oct 28 12:06:46 bigip1-ve debug /usr/bin/websso[400]: 01490000:7: <0xf1c75b90>:Modules/HttpHeaderBased/Kerberos.cpp:1058 S4U ======> - NO cached S4U2Proxy ticket for user: user1@EXAMPLE.COM server: HTTP/win 2008r2.example.com@EXAMPLE.COM - trying to fetch Oct 28 12:06:46 bigip1-ve debug /usr/bin/websso[400]: 01490000:7: <0xf1c75b90>:Modules/HttpHeaderBased/Kerberos.cpp:1072 S4U ======> - NO cached S4U2Self ticket for user: user1@EXAMPLE.COM - trying to fetch Oct 28 12:06:46 bigip1-ve debug /usr/bin/websso[400]: 01490000:7: <0xf1c75b90>:Modules/HttpHeaderBased/Kerberos.cpp:1082 S4U ======> - fetched S4U2Self ticket for user: user1@EXAMPLE.COM Oct 28 12:06:46 bigip1-ve debug /usr/bin/websso[400]: 01490000:7: <0xf1c75b90>:Modules/HttpHeaderBased/Kerberos.cpp:1104 S4U ======> trying to fetch S4U2Proxy ticket for user: user1@EXAMPLE.COM server: HTTP/win2008r2.example.com@EXAMPLE.COM Oct 28 12:06:46 bigip1-ve debug /usr/bin/websso[400]: 01490000:7: <0xf1c75b90>:Modules/HttpHeaderBased/Kerberos.cpp:1112 S4U ======> fetched S4U2Proxy ticket for user: user1@EXAMPLE.COM server: HTTP/win2008r2.example.com@EXAMPLE.COM Oct 28 12:06:46 bigip1-ve debug /usr/bin/websso[400]: 01490000:7: <0xf1c75b90>:Modules/HttpHeaderBased/Kerberos.cpp:1215 S4U ======> OK! Oct 28 12:06:46 bigip1-ve debug /usr/bin/websso[400]: 01490000:7: <0xf1c75b90>:Modules/HttpHeaderBased/Kerberos.cpp:236 GSSAPI: Server: HTTP/win2008r2.example.com@EXAMPLE.COM, User: user1@EXAMPLE.COM Oct 28 12:06:46 bigip1-ve debug /usr/bin/websso[400]: 01490000:7: <0xf1c75b90>:Modules/HttpHeaderBased/Kerberos.cpp:278 GSSAPI Init_sec_context returned code 0 Oct 28 12:06:46 bigip1-ve debug /usr/bin/websso[400]: 01490000:7: <0xf1c75b90>:Modules/HttpHeaderBased/Kerberos.cpp:316 GSSAPI token of length 1451 bytes will be sent back Hilfreich ist es natürlich auch die Logfiles des IIS anzuschen. Hier kann man sich auch den Usernamen anzeigen lassen (C:\inetpub\logs\LogFiles\W3SVC1): #Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status time-taken 2011-10-27 21:29:23 10.0.0.25 GET / - 80 EXAMPLE\user2 10.0.0.28 Mozilla/5.0+(compatible;+MSIE+9.0;+Windows+NT+6.1;+Trident/5.0) 200 0 0 15 Eine weitere Fehleranalysemöglichkeit ist natürlich sich anzuschauen, was denn für Daten über die Leitung gehen. Tcpdump und Wireshark sind hierbei unsere Freunde, # tcpdump –i internal –s0 –n–w /tmp/kerberos.pcap host 10.0.0.25 -i: das VLAN, die es zu belauschen gilt. Wählt man hier „0.0“ wird auf allen Schnittstellen gesniffert und man sieht die Pakete entsprechend oft. bzw. auch die Veränderungen, die ein Paket ggf. beim Durchlaufen der BIG-IP erfährt. -s0: bedeutet, dass das gesamte Paket aufgezeichnet werden soll -n: keine Namensauflösung -w /tmp/kerberos.pcap: Die Aufzeichnungen in die Datei /tmp/kerberos.cap speichern host 10.0.0.25: nur Pakete mit der Quell- oder Ziel-IP 10.0.0.25 aufzeichnen. Im Wireshark sieht eine Aufzeichnung dann etwa so aus: Wireshark versteht das Kerberos Protokoll und gibt somit gute Hinweise auf mögliche Probleme. Da APM die Kerberos Tickets cached, kann dies natürlich beim Testen zu unerwünschten Effekten führen. Das bedeutet es macht durchaus Sinn, während der Tests die Ticket Lifetime von standardmässig 600 Minuten runter zu setzen. Zudem kann man auch den Cache mit folgenden Befehl leeren: # bigstart restart websso Zum guten Schluß möchte ich dann noch ein paar Fehlermeldungen erläutern, die man im Log bei Problemen finden kann: Kerberos: can't get TGT for host/apm.realm.com@REALM.COM - Cannot find KDC for requested realm (-1765328230) – Hier sollte man überprüfen ob DNS funktioniert und der DNS Server alle SRV/A/PTR Records der involvierten Realms hat. In der Datei /etc/krb5.conf auch bitte überprüfen, ob dns_lookup_kdc auf True gesetzt ist. Den Eintrag findet man in dem Bereich [libdefaults]. Kerberos: can't get TGT for host/apm.realm.com@REALM.COM - Preauthentication failed (-1765328360) – Das Delegation Account Passwort ist falsch. Kerberos: can't get TGT for host/apm.realm.com@REALM.COM - Client not found in Kerberos database (-1765328378) – Der Delegation Account existiert nicht im AD. Kerberos: can't get TGT for host/apm.realm.com@REALM.COM - Clients credentials have been revoked (-1765328366) – Der Delegation Account ist im AD abgeschaltet. Kerberos: can't get TGT for host/apm.realm.com@realm.com - KDC reply did not match expectations (-1765328237) – Der Realm Name in der SSO Konfiguration muss groß geschrieben sein. Kerberos: can't get TGT for host/apm.realm.com@REALM.COM - A service is not available that is required to process the request (-1765328355) – Die Verbindung mit dem KDC ist nicht möglich. Gründe können z.B. sein: Firewall, TGS Service auf dem KDC läuft nicht oder es ist der falsche KDC angegeben… Kerberos: can't get S4U2Self ticket for user a@REALM.COM - Client not found in Kerberos database (-1765328378) – Es gibt den User 'a' nicht in der Domain REALM.COM. Kerberos: can't get S4U2Self ticket for user qq@REALM.COM - Ticket/authenticator don't match (-1765328348) – Der Delegation Account hat die Form UPN/SPN und entspricht nicht der verwendeten REALM Domain. Achtung, wenn man hier mit Cross-Realms arbeitet! Kerberos: can't get S4U2Self ticket for user aa@realm.com - Realm not local to KDC (-1765328316) – Das KDC Feld muss leer gelassen werden in der SSO Konfiguration, wenn man mit Cross-Realm SSO arbeitet. Also wenn ein User einen Server in einem anderen Realm erreichen muss. Kerberos: can't get S4U2Proxy ticket for server HTTP/webserver.realm.com@REALM.COM - Requesting ticket can't get forwardable tickets (-1765328163) – Der Delegation Account ist nicht für Constrained Delegation und/oder Protocol Transition konfiguriert. Kerberos: can't get S4U2Proxy ticket for server HTTP/webserver.realm.com@REALM.COM - KDC can't fulfill requested option (-1765328371) – Der Delegation Account in REALM.COM hat keinen Service für webserver.real.com in seiner Konfiguration. Damit Sie Kerberos auf der Windows Seite debuggen können, hilft vielleicht dieser Artikel: • http://www.microsoft.com/downloads/details.aspx?FamilyID=7DFEB015-6043-47DB-8238-DC7AF89C93F1&displaylang=en So, ich hoffe natürlich, dass Sie keine Probleme bei der Konfiguration des SSO mit Constrained Delegation haben, aber falls doch, hilft Ihnen hoffentlich dieser Blog-Beitrag, um dem Problem schneller auf die Spur zukommen. Ihr F5-Blogger, Sven Müller654Views1like1CommentIntroducing PoshTweet - The PowerShell Twitter Script Library
It's probably no surprise from those of you that follow my blog and tech tips here on DevCentral that I'm a fan of Windows PowerShell. I've written a set of Cmdlets that allow you to manage and control your BIG-IP application delivery controllers from within PowerShell and a whole set of articles around those Cmdlets. I've been a Twitter user for a few years now and over the holidays, I've noticed that Jeffrey Snover from the PowerShell team has hopped aboard the Twitter bandwagon and that got me to thinking... Since I live so much of my time in the PowerShell command prompt, wouldn't it be great to be able to tweet from there too? Of course it would! HTTP Requests So, last night I went ahead and whipped up a first draft of a set of PowerShell functions that allow access to the Twitter services. I implemented the functions based on Twitter's REST based methods so all that was really needed to get things going was to implement the HTTP GET and POST requests needed for the different API methods. Here's what I came up with. function Execute-HTTPGetCommand() { param([string] $url = $null); if ( $url ) { [System.Net.WebClient]$webClient = New-Object System.Net.WebClient $webClient.Credentials = Get-TwitterCredentials [System.IO.Stream]$stream = $webClient.OpenRead($url); [System.IO.StreamReader]$sr = New-Object System.IO.StreamReader -argumentList $stream; [string]$results = $sr.ReadToEnd(); $results; } } function Execute-HTTPPostCommand() { param([string] $url = $null, [string] $data = $null); if ( $url -and $data ) { [System.Net.WebRequest]$webRequest = [System.Net.WebRequest]::Create($url); $webRequest.Credentials = Get-TwitterCredentials $webRequest.PreAuthenticate = $true; $webRequest.ContentType = "application/x-www-form-urlencoded"; $webRequest.Method = "POST"; $webRequest.Headers.Add("X-Twitter-Client", "PoshTweet"); $webRequest.Headers.Add("X-Twitter-Version", "1.0"); $webRequest.Headers.Add("X-Twitter-URL", "http://devcentral.f5.com/s/poshtweet"); [byte[]]$bytes = [System.Text.Encoding]::UTF8.GetBytes($data); $webRequest.ContentLength = $bytes.Length; [System.IO.Stream]$reqStream = $webRequest.GetRequestStream(); $reqStream.Write($bytes, 0, $bytes.Length); $reqStream.Flush(); [System.Net.WebResponse]$resp = $webRequest.GetResponse(); $rs = $resp.GetResponseStream(); [System.IO.StreamReader]$sr = New-Object System.IO.StreamReader -argumentList $rs; [string]$results = $sr.ReadToEnd(); $results; } } Credentials Once those were completed, it was relatively simple to get the Status methods for public_timeline, friends_timeline, user_timeline, show, update, replies, and destroy going. But, for several of those services, user credentials were required. I opted to store them in a script scoped variable and provided a few functions to get/set the username/password for Twitter. $script:g_creds = $null; function Set-TwitterCredentials() { param([string]$user = $null, [string]$pass = $null); if ( $user -and $pass ) { $script:g_creds = New-Object System.Net.NetworkCredential -argumentList ($user, $pass); } else { $creds = Get-TwitterCredentials; } } function Get-TwitterCredentials() { if ( $null -eq $g_creds ) { trap { Write-Error "ERROR: You must enter your Twitter credentials for PoshTweet to work!"; continue; } $c = Get-Credential if ( $c ) { $user = $c.GetNetworkCredential().Username; $pass = $c.GetNetworkCredential().Password; $script:g_creds = New-Object System.Net.NetworkCredential -argumentList ($user, $pass); } } $script:g_creds; } The Status functions Now that the credentials were out of the way, it was time to tackle the Status methods. These methods are a combination of HTTP GETs and POSTs that return an array of status entries. For those interested in the raw underlying XML that's returned, I've included the $raw parameter, that when set to $true, will not do a user friendly display, but will dump the full XML response. This would be handy, if you want to customize the output beyond what I've done. #---------------------------------------------------------------------------- # public_timeline #---------------------------------------------------------------------------- function Get-TwitterPublicTimeline() { param([bool]$raw = $false); $results = Execute-HTTPGetCommand "http://twitter.com/statuses/public_timeline.xml"; Process-TwitterStatus $results $raw; } #---------------------------------------------------------------------------- # friends_timeline #---------------------------------------------------------------------------- function Get-TwitterFriendsTimeline() { param([bool]$raw = $false); $results = Execute-HTTPGetCommand "http://twitter.com/statuses/friends_timeline.xml"; Process-TwitterStatus $results $raw } #---------------------------------------------------------------------------- #user_timeline #---------------------------------------------------------------------------- function Get-TwitterUserTimeline() { param([string]$username = $null, [bool]$raw = $false); if ( $username ) { $username = "/$username"; } $results = Execute-HTTPGetCommand "http://twitter.com/statuses/user_timeline$username.xml"; Process-TwitterStatus $results $raw } #---------------------------------------------------------------------------- # show #---------------------------------------------------------------------------- function Get-TwitterStatus() { param([string]$id, [bool]$raw = $false); if ( $id ) { $results = Execute-HTTPGetCommand "http://twitter.com/statuses/show/" + $id + ".xml"; Process-TwitterStatus $results $raw; } } #---------------------------------------------------------------------------- # update #---------------------------------------------------------------------------- function Set-TwitterStatus() { param([string]$status); $encstatus = [System.Web.HttpUtility]::UrlEncode("$status"); $results = Execute-HTTPPostCommand "http://twitter.com/statuses/update.xml" "status=$encstatus"; Process-TwitterStatus $results $raw; } #---------------------------------------------------------------------------- # replies #---------------------------------------------------------------------------- function Get-TwitterReplies() { param([bool]$raw = $false); $results = Execute-HTTPGetCommand "http://twitter.com/statuses/replies.xml"; Process-TwitterStatus $results $raw; } #---------------------------------------------------------------------------- # destroy #---------------------------------------------------------------------------- function Destroy-TwitterStatus() { param([string]$id = $null); if ( $id ) { Execute-HTTPPostCommand "http://twitter.com/statuses/destroy/$id.xml", "id=$id"; } } You may notice the Process-TwitterStatus function. Since there was a lot of duplicate code in each of these functions, I went ahead and implemented it in it's own function below: function Process-TwitterStatus() { param([string]$sxml = $null, [bool]$raw = $false); if ( $sxml ) { if ( $raw ) { $sxml; } else { [xml]$xml = $sxml; if ( $xml.statuses.status ) { $stats = $xml.statuses.status; } elseif ($xml.status ) { $stats = $xml.status; } $stats | Foreach-Object -process { $info = "by " + $_.user.screen_name + ", " + $_.created_at; if ( $_.source ) { $info = $info + " via " + $_.source; } if ( $_.in_reply_to_screen_name ) { $info = $info + " in reply to " + $_.in_reply_to_screen_name; } "-------------------------"; $_.text; $info; }; "-------------------------"; } } } A few hurdles Nothing goes without a hitch and I found myself pounding my head at why my POST commands were all getting HTTP 417 errors back from Twitter. A quick search brought up this post on Phil Haack's website as well as this Google Group discussing an update in Twitter's services in how they react to the Expect 100 HTTP header. A simple setting in the ServicePointManager at the top of the script was all that was needed to get things working again. [System.Net.ServicePointManager]::Expect100Continue = $false; PoshTweet in Action So, now it's time to try it out. First you'll need to . source the script and then set your Twitter credentials. This can be done in your Twitter $profile file if you wish. Then you can access all of the included functions. Below, I'll call Set-TwitterStatus to update my current status and then Get-TwitterUserTimeline and Get-TwitterFriendsTimeline to get my current timeline as well as that of my friends. PS> . .\PoshTweet.ps1 PS> Set-TwitterCredentials PS> Set-TwitterStatus "Hacking away with PoshTweet" PS> Get-TwitterUserTimeline ------------------------- Hacking away with PoshTweet by joepruitt, Tue Dec 30, 12:33:04 +0000 2008 via web ------------------------- PS> Get-TwitterFriendsTimeline ------------------------- @astrout Yay, thanks! by mediaphyter, Tue Dec 30 20:37:15 +0000 2008 via web in reply to astrout ------------------------- RT @robconery: Headed to a Portland Nerd Dinner tonite - should be fun! http://bit.ly/EUFC by shanselman, Tue Dec 30 20:37:07 +0000 2008 via TweetDeck ------------------------- ... Things Left Todo As I said, this was implemented in an hour or so last night so it definitely needs some more work, but I believe I've got the Status methods pretty much covered. Next I'll move on to the other services of User, Direct Message, Friendship, Account, Favorite, Notification, Block, and Help when I've got time. I'd also like to add support for the "source" field. I'll need to setup a landing page for this library that is public facing so the folks at Twitter will add it to their system. Once I get all the services implemented, I'll more forward in formalizing this as an application and submit it for consideration. Collaboration I've posted the source to this set of functions on the DevCentral wiki under PsTwitterApi. You'll need to create an account to get to it, but I promise it will be worth it! Feel free to contribute and add to if you have the time. Everyone is welcome and encouraged to tear my code apart, optimize it, enhance it. Just as long as it get's better in the process. B-).1.7KViews0likes10Comments