Authenticated Service
The goals of this assignment are to:
- Implement a password-authenticated network service
- Defend the service against denial-of-service attacks
- Defend the service against online password guessing attacks
Service Specification
For this assignment, your service will implement a simple protocol using protobuf v3 messages.1 In this protocol, each message is preceded by a two-byte, big-endian integer giving the length of the following protobuf message. Each TCP connection only supports one message exchange. The protocol is as shown below.
\[ \begin{align*} C \rightarrow S &: \mathsf{u16}(|\mathsf{Request}|) \cdot \mathsf{Request} \\ S \rightarrow C &: \mathsf{u16}(|\mathsf{Response}|) \cdot \mathsf{Response} \\ \end{align*} \]
The messages themselves are defined as follows.
syntax = "proto3";
message Request {
oneof request {
StopRequest stop = 1;
ResetBlockListsRequest reset = 2;
ExpressionRequest expr = 3;
}
}
message StopRequest {}
message ResetBlockListsRequest {}
message ExpressionRequest {
string username = 1;
string password = 2;
string expression = 3;
}
message Response {
oneof response {
StopResponse stop = 1;
ResetBlockListsResponse reset = 2;
ExpressionResponse expr = 3;
}
}
message StopResponse {}
message ResetBlockListsResponse {}
message ExpressionResponse {
bool authenticated = 1;
string result = 2;
}
The protocol runs on port 1400/tcp
.
StopRequest
is a meta-request intended to assist grading;
upon reception, the server must immediately terminate.
ResetBlockListsRequest
is also a meta-request; upon
reception, the server must immediately expunge all block list entries
and all detection state.
The application protocol that will be evaluated consists of
ExpressionRequest
and ExpressionResponse
exchanges; think of the service as a trivial example of outsourced
computation. Servers must implement user authentication by checking
usernames and passwords against a provided database. The database will
consist of a TOML document that
contains an array of user objects with username
and
password_hash
keys. Password hashes follow PHC
string format. Use an appropriate library to support the following
hash algorithms.
- SHA-256
- SHA-512
- bcrypt
- Argon2
An example user database is as follows:
[[users]]
username = "mario"
password_hash = "$argon2id$v=19$m=65536,t=3,p=1$g/CeU8p5733PmVOq9R6DkA$QB+aA9ry4vZMhgmCDdWWBc4Bo8SDTSwLV+H8UUSoGO4"
[[users]]
username = "luigi"
password_hash = "$5$rounds=535000$KXabkqjRS9WfMw2V$MEBaT9Hcbdvcg4f9s7LGCR.lUE2u8OeslxVlsaXZD29"
On successful authentication, the authenticated
field
must be set to true in the response. The server must also provide the
result of evaluating the Python expression contained in the request’s
expression
field in the response’s result
field. If authentication failed, authenticated
must be set
to false in the response and result
is undefined.
Expression evaluation must be implemented by executing a Python
interpreter on the expression. The result is the captured output of the
evaluation (stdout
only).
The service must be packaged as a container image that can be executed with the following invocation:
docker run -it --rm \
-p 1400:1400 \
-v ${host_path}/users.toml:/tmp/users.toml \
${image_name} /tmp/users.toml
Defending Against Attacks
The service must implement defenses against denial-of-service and password guessing attacks.
The server must provide concurrent service for multiple clients. Feel free to use any concurrency strategy you like to achieve this.2 However, your solution must not exceed 1 GB of memory usage.
The server must identify clients that send 3 or more invalid requests within the span of 30 seconds to the service, and permanently block those source IP addresses. Invalid requests are those that fail to parse, that do not contain a required field such as a username or password, that contain an invalid password, that contain an invalid expression, or have any other feature that prevents a successful response.
The server must identify and terminate expression evaluations that take longer than 5 seconds to compute. Users that submit such expressions must be permanently blocked.
The server defend against “Slowloris”-style attacks. This attack is defined as those clients that take more than 10 seconds to send a request. Source IP addresses for offending clients must be permanently blocked.
The server will be evaluated on its ability to block malicious clients (true positives) while preserving service to benign clients (avoiding false positives).
Public Tests
A partial test suite is available in Canvas as
netsec_authd_tests.img.xz
, and can be invoked against your
server as follows.
xzcat netsec_authd_tests.img.xz | docker load
docker run -it --rm -e RUST_LOG=info \
netsec_authd_tests ${server_address}:${server_port}
Submission Instructions
Package your solution as a gzipped TAR archive. Your solution should have the following structure.
$ tree -F authd
authd
├── Dockerfile
└── src/
The root directory must be named authd
, and the source
code to your solution should be contained in src/
. Your
Dockerfile
should produce an image that follows the
invocation instructions above.
Submit the solution archive to Canvas.