FreeRADIUS InkBridge

Raduat

The raduat tool is for automated testing of RADIUS server configurations and functionality. Raduat is a shell script used for writing test suites as required by your organization’s eco-system. This tool reads test files and uses radclient to send the test requests. Server responses are compared against a response filter file that contains the expected output.

Raduat helps identify configuration and functionality issues ensuring that the FreeRADIUS server is operating correctly.

Getting Started

To use raduat successfully, follow these steps:

  1. Create the test files.

  2. Create the response filter files.

  3. Run the tests.

  4. Analyze the results.

  5. Fix any issues and update the relevant files.

  6. Re-run the tests.

Download the latest version of raduat from github.

The raduat tool supports PAP and CHAP authentications only (no EAP support). Raduat is often used by ISPs and carriers that require end to end testing involving complex business logic using basic authentication methods.

Create a test request

A test request consists of <attribute><op><value> pairs, separated by newlines.

Attribute

Every request must contain a Packet-Type=[Access-Request|Accounting-Request] pair, to set the type of test request.

In addition to Packet-Type it may contain any attribute (including VSAs) found in the FreeRADIUS dictionaries.

Commonly used attributes are:

  • User-Name

  • User-Password

  • NAS-IP-Address

  • Acct-Session-Id

  • NAS-Port-ID

  • Acct-Session-Time

Operators (op)

The operator (op) must be one of the assignment operators below.

Table 1. Assignment operators
Parameter Description

=

Sets the value of the attribute

:=

Replaces the value of the attribute

+=

Append the value of the attribute to the list

Value

Only static values are supported. In a future release, backtick (exec) expansion may be added.

Strings must be wrapped in single quotes, any other values remain unquoted.

Binary attributes values may be specified as an unquoted string with a 0x prefix e.g. 0xffffff

Tags

The following comment tags are supported. Tags are placed at the top of the request file.

  • # serial - Ensures this test is not executed in parallel with other tests

Comments

Any line starting with # is treated as a comment.

Example Test Request

This test file generates an Access-Request, with the attributes User-Name, User-Password and NAS-IP-Address.

# serial
# My test access request
Packet-Type=Access-Request
User-Name='test_user001@test.realm'
User-Password='testing123'
NAS-IP-Address=127.0.0.1

Create a response filter file

A response filter consists of <attribute><op><value> pairs, separated by newlines.

Response filters are used to verify that the response received from the server matches what’s expected.

The pairs in the response filter do not need to be in the same order as the server response. However, every attribute in the server response must be matched by a line in the response filter.

Attributes

Every response filter must contain a Response-Packet-Type=[Access-Accept|Access-Reject|Accounting-Response] pair to set the type of response expected.

In addition to Response-Packet-Type it may contain any attribute (including VSAs) found in the FreeRADIUS dictionaries.

Commonly used attributes are: * Reply-Message * User-Name * Class * Framed-IP-Address * Framed-Route * Session-Timeout

Operators (op)

The operator (op) must be one of the comparison operators below.

Table 2. Comparison operators
Parameter Description Parameter Description

<

Less than

>

Greater than

Less than or equal to

>=

Greater than or equal to

==

Equal to

!=

Not equal to

=~

Matches

!~

Does not match

=* ANY

Present

!* ANY

Not present

Value

Value format is the same as the request.

Example Test Response Filter

The test response filter expects an Access-Accept packet with the corresponding reply message.

Response-Packet-Type==Access-Accept
Reply-Message=='Welcome to foocorp'

Create a test suite

By default raduat looks for a folder relative to itself called tests.

If it finds one, raduat tries executing each of the test requests in lexicographical order. The raduat tool also works with with a directory hierarchy. In this case the tests are executed depth first then in lexicographical order. This is to allow easy organization of tests.

Only files with names that match the pattern test[0-9]{3}.* are processed. Each request file must also be paired with a response filter file. A response filter file uses the same name as the request file appended with an _expected suffix.

For example, the response filter file for test000_check_static_ip is test000_check_static_ip_expected.

Example

mkdir -p ./tests/static_ip

echo "Packet-Type=Access-Request
User-Name=test_user001@test.realm
User-Password=testing123" >> ./tests/static_ip/test000_check_static_ip

echo "Response-Packet-Type==Access-Accept
Framed-IP-address==192.168.0.1" >> ./tests/static_ip/test000_check_static_ip_expected

echo "Packet-Type=Access-Request
User-Name=test_user002@test.realm
User-Password=testing123" >> ./tests/static_ip/test001_check_static_ip

echo "Response-Packet-Type==Access-Accept
Framed-IP-address==192.168.0.2" >> ./tests/static_ip/test001_check_static_ip_expected

Run the tests

By default radaut will execute tests in parallel batches of 20. If you want to execute tests one at a time, either add # serial to the top of the file, or pass -p 1.

Arguments

Command line arguments can be found with raduat -h. They can be used to specify the server/port/secret to run the tests against. By default the server is 127.0.0.1 the port is automatically determined by Packet-Type and the secret is testing123.

Table 3. Command-line raduat options

-h

Display this help message

-H <host>[:port]

Send test packets to specified host and port. Defaults = 127.0.0.1

-v

Verbose mode

-p <number>

Run tests in parallel. Defaults = 20

-s <secret>

Shared secret

-c <cluster>

Specify cluster type one of ($cluster_types)

-r <type>

Specify server role one of ($role_types)

Environmental variables

  • TESTDIR - The directory containing the tests.

  • RADCLIENT - Path to the radclient binary.

  • FILTER_SUFFIX - The suffix added to the request file name to find response filters. Defaults to _expected.

  • DICTPATH - Path to alternative RADIUS dictionaries.

Example test execution

Running the above test requests/response filters against a dummy configuration:

authorize {
	switch User-Name {
		case 'test_user001@test.realm' {
			update reply {
				Framed-IP-Address := 192.168.0.1
			}
		}
		case 'test_user002@test.realm' {
			update reply {
				Framed-IP-Address := 192.168.0.3
			}
		}
	}
	update control {
		Auth-Type := Accept
	}
}

Produces the following output:

$ ./raduat
Executing 2 test(s) from ./tests
Executing specified tests
Use -v to see full list
Sent Access-Request Id 197 from 0.0.0.0:55331 to 127.0.0.1:1812 length 63
Sent Access-Request Id 149 from 0.0.0.0:55331 to 127.0.0.1:1812 length 63
Received Access-Accept Id 197 from 127.0.0.1:1812 to 0.0.0.0:0 length 26
Received Access-Accept Id 149 from 127.0.0.1:1812 to 0.0.0.0:0 length 26
(1) ./tests/static_ip/test001_check_static_ip: Response for failed filter: Attribute value "192.168.0.3" didn't match filter: Framed-IP-Address == 192.168.0.2
(Parallelized tests)

One or more tests failed (radclient exited with 1)
$ echo $?
1

Which is correct, as 192.168.0.3 != 192.168.0.2.

Adding -v gives us more verbose output, and also a summary of packets sent/received:

./raduat -v
Executing 2 test(s) from ./tests
Executing specified tests:
./tests/static_ip/test000_check_static_ip
./tests/static_ip/test001_check_static_ip
Executing: radclient  -f "/var/folders/5_/k_q1ccb94p3gcgk8r9yc8ssh0000gn/T/raduatXXX.f2cB3Kek:/var/folders/5_/k_q1ccb94p3gcgk8r9yc8ssh0000gn/T/raduatXXX.1RX7R8aL" -x -s -t "2" -r "3" -p "40" "127.0.0.1" auto "testing123"
Sent Access-Request Id 63 from 0.0.0.0:51512 to 127.0.0.1:1812 length 63
	Packet-Type = Access-Request
	User-Name = 'test_user001@test.realm'
	User-Password = 'testing123'
	Radclient-Test-Name := './tests/static_ip/test000_check_static_ip'
Sent Access-Request Id 147 from 0.0.0.0:51512 to 127.0.0.1:1812 length 63
	Packet-Type = Access-Request
	User-Name = 'test_user002@test.realm'
	User-Password = 'testing123'
	Radclient-Test-Name := './tests/static_ip/test001_check_static_ip'
Received Access-Accept Id 63 from 127.0.0.1:1812 to 0.0.0.0:0 length 26
	Framed-IP-Address = 192.168.0.1
(0) ./tests/static_ip/test000_check_static_ip: Response passed filter
Received Access-Accept Id 147 from 127.0.0.1:1812 to 0.0.0.0:0 length 26
	Framed-IP-Address = 192.168.0.3
(1) ./tests/static_ip/test001_check_static_ip: Response for failed filter: Attribute value "192.168.0.3" didn't match filter: Framed-IP-Address == 192.168.0.2
Packet summary:
	Accepted      : 2
	Rejected      : 0
	Lost          : 0
	Passed filter : 1
	Failed filter : 1
(Parallelised tests)

One or more tests failed (radclient exited with 1)

The tests to run can be filtered using glob patterns:

  • ./raduat — 'static_ip/test000*' would execute only the first test in the static_ip suite.

  • ./raduat — 'static_ip/*' would execute all the static_ip tests.

This can be used to drill down, and only run the failing tests.