Compare commits
4 Commits
Author | SHA1 | Date |
---|---|---|
Les De Ridder | 8e461051cd | |
Les De Ridder | 5eea8a71f1 | |
Les De Ridder | 95f3d8fabd | |
Les De Ridder | c77709a813 |
39
README.md
39
README.md
|
@ -1,19 +1,42 @@
|
|||
# salty-ircd
|
||||
|
||||
salty-ircd is an [Internet Relay Chat](https://en.wikipedia.org/wiki/Internet_Relay_Chat) daemon written in [D](https://dlang.org/).
|
||||
|
||||
## Goals
|
||||
The main goals of salty-ircd are strict RFC compliance and security.
|
||||
|
||||
### RFC compliance
|
||||
salty-ircd aims to be fully compliant with the IRC RFCs (in 'RFC mode'), specifically [RFC 1459](https://tools.ietf.org/html/rfc1459), [RFC 2811](https://tools.ietf.org/html/rfc2811), [RFC 2812](https://tools.ietf.org/html/rfc2812), and [RFC 2813](https://tools.ietf.org/html/rfc2813) (planned).
|
||||
Newer RFCs take precedence over older RFCs. Errata are respected by default, with newer errata (on the same RFC) taking precedence over older errata.
|
||||
salty-ircd aims to be fully compliant with the IRC RFCs (by default), specifically [RFC 1459](https://tools.ietf.org/html/rfc1459), [RFC 2811](https://tools.ietf.org/html/rfc2811), [RFC 2812](https://tools.ietf.org/html/rfc2812), and [RFC 2813](https://tools.ietf.org/html/rfc2813) (planned), including all errata.
|
||||
Newer RFCs take precedence over older RFCs.
|
||||
|
||||
Any additional features breaking RFC compliance will be made available through compile-time options (i.e. 'non-RFC modes').
|
||||
Any additional features breaking RFC compliance are available through compile-time options.
|
||||
|
||||
### Security (non-RFC modes)
|
||||
* salty-ircd will require TLS for all connections. An exception could be made to allow hosting a Tor hidden service.
|
||||
* salty-ircd will require TLS client certificates for authentication.
|
||||
### Security
|
||||
The following rules apply when any compile-time option is enabled (breaking strict RFC compliance):
|
||||
|
||||
* TLS is required for all connections, except connections from localhost (useful for running a Tor hidden service, which already has encryption)
|
||||
* TLS client certificates are required for oper and vhost authentication
|
||||
|
||||
## Building
|
||||
Build dependencies:
|
||||
* A D compiler
|
||||
* dub
|
||||
* fish
|
||||
* git
|
||||
|
||||
Build command:
|
||||
* RFC compliant: `dub build`
|
||||
* Modern (all additional features): `dub build -c=modern`
|
||||
|
||||
The 'modern' configuration aims to be mostly compatible with UnrealIRCd user modes/chars.
|
||||
|
||||
When `-d=ProxyV1` is added to the build command, salty-ircd can accept traffic through the PROXY protocol (version 1), e.g. from an UnrealIRCd server running with [a custom module](https://github.com/lesderid/unrealircd5_proxyv1_copy). Please see this module's readme for more information. Note that this is simply a development/debugging option and should not be used for a production server.
|
||||
|
||||
TODO: Add a method to supply a custom list of compile-time options.
|
||||
|
||||
## Running
|
||||
First, create the configuration file, `config.sdl`. You can find a template in `config.template.sdl`.
|
||||
|
||||
Then, simply run `./out/salty-ircd`.
|
||||
|
||||
## License
|
||||
The source code for salty-ircd is licensed under the [University of Illinois/NCSA Open Source License](LICENSE).
|
||||
[University of Illinois/NCSA Open Source License](LICENSE).
|
||||
|
|
4
dub.sdl
4
dub.sdl
|
@ -11,9 +11,9 @@ preBuildCommands "./generate-version-info.fish"
|
|||
versions "VibeDefaultMain"
|
||||
targetPath "out"
|
||||
|
||||
configuration "application" {
|
||||
configuration "compliant" {
|
||||
}
|
||||
|
||||
configuration "modern" {
|
||||
versions "BasicFixes" "SupportTLS"
|
||||
versions "Modern"
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import std.datetime;
|
|||
|
||||
import vibe.core.core;
|
||||
import vibe.core.net;
|
||||
import vibe.core.stream : IOMode;
|
||||
import vibe.stream.operations : readLine;
|
||||
|
||||
import ircd.versionInfo;
|
||||
|
@ -41,6 +42,9 @@ class Connection
|
|||
|
||||
string pass = null;
|
||||
|
||||
debug (ProxyV1)
|
||||
bool proxy;
|
||||
|
||||
@property auto channels()
|
||||
{
|
||||
return _server.channels.filter!(c => c.members.canFind(this));
|
||||
|
@ -122,7 +126,15 @@ class Connection
|
|||
{
|
||||
string messageString = message.toString;
|
||||
writeln("S> " ~ messageString);
|
||||
_connection.write(messageString ~ "\r\n");
|
||||
|
||||
auto messageBytes = cast(const(ubyte)[]) (messageString ~ "\r\n");
|
||||
auto bytesSent = _connection.write(messageBytes, IOMode.once);
|
||||
|
||||
if (bytesSent < 0)
|
||||
{
|
||||
writeln("client disconnected (write error)");
|
||||
closeConnection();
|
||||
}
|
||||
}
|
||||
|
||||
void sendNumeric(alias numeric)(string[] params...)
|
||||
|
@ -174,6 +186,13 @@ class Connection
|
|||
continue;
|
||||
}
|
||||
|
||||
debug (ProxyV1)
|
||||
if (message.command == "PROXY")
|
||||
{
|
||||
proxy = true;
|
||||
hostname = getHost(message.parameters[1]);
|
||||
}
|
||||
|
||||
//NOTE: The RFCs don't specify whether commands are case-sensitive
|
||||
version (BasicFixes)
|
||||
{
|
||||
|
@ -293,7 +312,7 @@ class Connection
|
|||
_server.updateCommandStatistics(message);
|
||||
}
|
||||
|
||||
onDisconnect();
|
||||
closeConnection();
|
||||
}
|
||||
|
||||
void onNick(Message message)
|
||||
|
@ -332,7 +351,7 @@ class Connection
|
|||
{
|
||||
sendWelcome();
|
||||
}
|
||||
else if (registrationAttempted)
|
||||
else if (!wasRegistered && registrationAttempted)
|
||||
{
|
||||
onIncorrectPassword();
|
||||
}
|
||||
|
@ -358,7 +377,8 @@ class Connection
|
|||
user = message.parameters[0];
|
||||
modes = modeMaskToModes(message.parameters[1]);
|
||||
realname = message.parameters[3];
|
||||
hostname = getHost();
|
||||
debug (ProxyV1) {}
|
||||
else hostname = getHost();
|
||||
|
||||
if (!wasRegistered && registered)
|
||||
{
|
||||
|
@ -1372,9 +1392,11 @@ class Connection
|
|||
closeConnection();
|
||||
}
|
||||
|
||||
string getHost()
|
||||
string getHost(string addressString = null)
|
||||
{
|
||||
auto address = parseAddress(_connection.remoteAddress.toAddressString);
|
||||
auto address = parseAddress(addressString != null ?
|
||||
addressString :
|
||||
_connection.remoteAddress.toAddressString);
|
||||
auto hostname = address.toHostNameString;
|
||||
if (hostname is null)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue