Duplicate packets are detected by one of two methods. The best method is to use the packet authenticator.The other method is to use a combination of the packet identifier, client address, and client port. Both methods are supported by the server. The former is much more reliable when used with RADIUS compliant clients. The latter can result in false positives and is susceptible to replay attacks. Some clients do not change their authenticator over Access-Challenge responses and therefore the first method will not work. The only known client with this behavior is from Cisco.
Using the authenticator is the preferred method as all good RADIUS clients will preserve the packet identifier and authenticator during retries.
The second method deserves some rational on why it's not very effective. The RADIUS RFC 2865 makes an off hand remark stating:
The RADIUS server can detect a duplicate request if it has the same client source IP address and source UDP port and Identifier within a short span of time.(italics added)
Note that this first suggestion has a small 'can' whereas the following statements about the authenticator has two SHOULD's, a MUST, and an OK supporting the authenticator method for duplicate detection.
Meanwhile there are several statements about the authenticator that are worth noting:
"The value SHOULD be unpredictable and unique over the lifetime of a secret..."
"The Request Authenticator value in an Access-Request packet SHOULD also be unpredictable..."
"The Request Authenticator value MUST be changed each time a new Identifier is used."
"Retransmission Hints ... it is OK to retransmit the packet to the alternate RADIUS server with the same ID and request Authenticator, because the content of the attributes haven't changed."
"If you change the contents of the User-Password attribute (or any other attribute), you need a new Request Authenticator and therefore a new ID."
The server is configured to use the authenticator duplication method by default. If you require the packet identifier / client address method the RADIUSServer.setDuplicateDetectionMethod(int detectionMethod). The detectionMethod value may be either DUPLICATE_DETECTION_AUTHENTICATOR or DUPLICATE_DETECTION_NASPORTID.
Which ever method is chosen will be used as the duplicate detection method for all clients. The NASPORTID method is slightly slower than using the authenticator.
Both detection methods offer control over how long the detector will remember duplicate packets. The RADIUSServer.setAcctDuplicateTTL(int seconds) and RADIUSServer.setAuthDuplicateTTL(int seconds) methods set time in seconds. This is used both to reject duplicate packets and rebuff simple replay attacks.
The AuthInfo class that offers helper methods for the AccessImpl class your code uses to perform authentications and provisioning can be used to track individual sessions during Access-Request / Access-Challenge exchanges.
The methods AuthInfo.setStateObject(Object o) and Authinfo.setStateObject(byte code, Object o) associate a State attribute with a java class. The former method will track a single object. The second method can track additional classes using the particular byte code to track a particular class. The byte code must be a negative value as the server uses positive values for it's own internal associations. Generally the first method is sufficient.
The method AuthInfo.isAccessChallengeResponse() checks to see if a State attribute is present. If so you can use the AuthInfo.getStateObject() or AuthInfo.getStateObject(byte code) to retrieve the object associated with the State attribute.
Internally this is accomplished by a separate thread that associates a key consisting of the byte code and an integer with the data object. The thread periodically deletes old, unused objects if they are not referenced in time. The method RADIUSServer.setStateTTL(int seconds) controls this time period. The default is 30 seconds. The State attribute contains the key to recover. Multiple keys may be present representing multiple State attribute class associations. Each State key association consumes 5 bytes of the State attribute limiting the number of State associations to 50. This should be more than sufficient.
The Proxy-State can have a Java class associated with it in a manner similar to the State attribute. This allows a packet passing through the ProxyImpl code to track session information on that packet. The methods ProxyInfo.setProxyStateObject(Object o) and ProxyInfo.getProxyStateObject() set and retrieve such information.
Like the State association Proxy-State object remain in existance for 30 seconds or until retrieved. The time limit cannot be changed.