How To Setup Your Own IRC Network
This material is proposed for deletion ... Charybdis is no longer maintained since 2021; All development efforts have moved to solanum instead.
(Discuss) |
This doc aims to assist you on setup your own irc network with Alpine Linux.
We will configure two irc daemons and a simple ajax webirc client.
The irc daemons will work together sharing the channel, users and other informations.
From charybdis point of view, this configuration is called "cluster", but this word should not be understood with the common meaning of "cluster".
We assume that, as example, we want create Alpine Linux IRC Network.
We have irc1 and irc2 servers, called respectively irc1.alpinelab.lan and irc2.alpinelab.lan.
Prerequisites
Prerequisites are two PC with Alpine Linux installed (v2.5).
Packages that we are going to install are:
- Charybdis
- atheme-iris
Both of those packages are in edge. Charybdis is in main, atheme-iris in testing.
You can easily use this pinning edge repo:
vi /etc/apk/repositories
Add the line:
@edgem https://dl-cdn.alpinelinux.org/alpine/edge/main/
@edget https://dl-cdn.alpinelinux.org/alpine/edge/testing/
Then:
apk update
apk add charybdis@edgem
apk add atheme-iris@edget
Configure Charybdis
cp /etc/charybdis/example.conf /etc/charybdis/ircd.conf
vi /etc/charybdis/ircd.conf
Modify the file starting from /etc/charybdis/reference.conf (that is well documented).
loadmodule "extensions/chm_operonly.so"; loadmodule "extensions/extb_account.so"; loadmodule "extensions/extb_canjoin.so"; loadmodule "extensions/extb_channel.so"; loadmodule "extensions/extb_extgecos.so"; loadmodule "extensions/extb_oper.so"; loadmodule "extensions/extb_realname.so"; loadmodule "extensions/m_identify.so"; loadmodule "extensions/m_mkpasswd.so"; loadmodule "extensions/m_webirc.so"; loadmodule "extensions/sno_farconnect.so"; loadmodule "extensions/sno_globalkline.so"; loadmodule "extensions/sno_globaloper.so"; serverinfo { name = "irc1.alpinelab.lan"; sid = "01A"; description = "Alpine Linux IRC Server"; network_name = "Alpine Linux Network"; network_desc = "Alpine Linux IRC network."; hub = yes; default_max_clients = 10000; nicklen = 30; }; admin { name = "admin"; description = "Alpine Linux IRC network administrator"; email = "ircadmin@alpinelab.lan"; }; log { fname_userlog = "logs/userlog"; #fname_fuserlog = "logs/fuserlog"; fname_operlog = "logs/operlog"; #fname_foperlog = "logs/foperlog"; fname_serverlog = "logs/serverlog"; #fname_klinelog = "logs/klinelog"; fname_killlog = "logs/killlog"; fname_operspylog = "logs/operspylog"; #fname_ioerrorlog = "logs/ioerror"; }; class "users" { ping_time = 2 minutes; number_per_ident = 10; number_per_ip = 10; number_per_ip_global = 50; cidr_ipv4_bitlen = 24; cidr_ipv6_bitlen = 64; number_per_cidr = 200; max_number = 100; sendq = 400 kbytes; }; class "opers" { ping_time = 5 minutes; number_per_ip = 10; max_number = 1000; sendq = 1 megabyte; }; class "server" { ping_time = 5 minutes; connectfreq = 5 minutes; max_number = 10; sendq = 4 megabytes; }; listen { defer_accept = yes; port = 5000, 6665 .. 6669; sslport = 6697; }; auth { user = "*@*"; class = "users"; }; privset "local_op" { privs = oper:local_kill, oper:operwall; }; privset "server_bot" { extends = "local_op"; privs = oper:kline, oper:remoteban, snomask:nick_changes; }; privset "global_op" { extends = "local_op"; privs = oper:global_kill, oper:routing, oper:kline, oper:unkline, oper:xline, oper:resv, oper:mass_notice, oper:remoteban; }; privset "admin" { extends = "global_op"; privs = oper:admin, oper:die, oper:rehash, oper:spy; }; operator "ircadmin" { user = "*@*"; password = "MyStrongPassword"; snomask = "+Zbfkrsuy"; flags = ~encrypted; privset = "admin"; }; connect "irc2.alpinelab.lan" { host="10.0.2.10"; send_password = "Password_To_Server"; accept_password = "Password_From_Server"; port = 6666; hub_mask = "*"; class = "server"; flags = compressed, topicburst, autoconn; }; service { name = "services.int"; }; cluster { name = "*.alpinelab.lan"; flags = kline, tkline, unkline, xline, txline, unxline, resv, tresv, unresv; }; shared { oper = "*@*", "*"; flags = all, rehash; }; channel { use_invex = yes; use_except = yes; use_forward = yes; use_knock = yes; knock_delay = 5 minutes; knock_delay_channel = 1 minute; max_chans_per_user = 15; max_bans = 100; max_bans_large = 500; default_split_user_count = 0; default_split_server_count = 0; no_create_on_split = no; no_join_on_split = no; burst_topicwho = yes; kick_on_split_riding = no; only_ascii_channels = no; resv_forcepart = yes; channel_target_change = yes; disable_local_channels = no; }; serverhide { flatten_links = yes; links_delay = 5 minutes; hidden = no; disable_hidden = no; }; blacklist { host = "rbl.efnetrbl.org"; type = ipv4; reject_reason = "${nick}, your IP (${ip}) is listed in EFnet's RBL. For assistance, see https://efnetrbl.org/?i=${ip}"; /* Example of a blacklist that supports both IPv4 and IPv6 */ }; alias "NickServ" { target = "NickServ"; }; alias "ChanServ" { target = "ChanServ"; }; alias "OperServ" { target = "OperServ"; }; alias "MemoServ" { target = "MemoServ"; }; alias "NS" { target = "NickServ"; }; alias "CS" { target = "ChanServ"; }; alias "OS" { target = "OperServ"; }; alias "MS" { target = "MemoServ"; }; general { hide_error_messages = opers; hide_spoof_ips = yes; default_umodes = "+i"; default_operstring = "is an IRC Operator"; default_adminstring = "is a Server Administrator"; servicestring = "is a Network Service"; disable_fake_channels = no; tkline_expire_notices = no; default_floodcount = 10; failed_oper_notice = yes; dots_in_ident=2; min_nonwildcard = 4; min_nonwildcard_simple = 3; max_accept = 100; max_monitor = 100; anti_nick_flood = yes; max_nick_time = 20 seconds; max_nick_changes = 5; anti_spam_exit_message_time = 5 minutes; ts_warn_delta = 30 seconds; ts_max_delta = 5 minutes; client_exit = yes; collision_fnc = yes; resv_fnc = yes; global_snotices = yes; dline_with_reason = yes; kline_delay = 0 seconds; kline_with_reason = yes; kline_reason = "K-Lined"; identify_service = "NickServ@services.int"; identify_command = "IDENTIFY"; non_redundant_klines = yes; warn_no_nline = yes; use_propagated_bans = yes; stats_e_disabled = no; stats_c_oper_only=no; stats_h_oper_only=no; stats_y_oper_only=no; stats_o_oper_only=yes; stats_P_oper_only=no; stats_i_oper_only=masked; stats_k_oper_only=masked; map_oper_only = no; operspy_admin_only = no; operspy_dont_care_user_info = no; caller_id_wait = 1 minute; pace_wait_simple = 1 second; pace_wait = 10 seconds; short_motd = no; ping_cookie = no; connect_timeout = 30 seconds; default_ident_timeout = 5; disable_auth = no; no_oper_flood = yes; max_targets = 4; client_flood_max_lines = 20; use_whois_actually = no; oper_only_umodes = operwall, locops, servnotice; oper_umodes = locops, servnotice, operwall, wallop; oper_snomask = "+s"; burst_away = yes; nick_delay = 0 seconds; # 15 minutes if you want to enable this reject_ban_time = 1 minute; reject_after_count = 3; reject_duration = 5 minutes; throttle_duration = 60; throttle_count = 4; max_ratelimit_tokens = 30; away_interval = 30; }; modules { path = "/usr/lib/charybdis/modules"; path = "/usr/lib/charybdis/modules/autoload"; };
Relevant part of the config file are:
serverinfo { . . sid = "01A"; <----------- This must be unique. You can choose two cipher and one letter. hub = yes; <----------- This works as an hub. Allows other irc server to connects. . . } listen { port = 5000, 6665 .. 6669; <---- Port where charybdis is listening. You can also bind to a specific ip adding "host" directive. If not specifyied charybdis listen on all interfaces. sslport = 6697; <---- Port for SSL connection. You need a certificate in order to use this feature. }; operator "ircadmin" { user = "*@*"; <----------- This is a masq used to match who can become operator. This support CIDR. If you want to allows only 10.0.0.0/24, you can choose "*@10.0.0.*". password = "MyStrongPassword"; <---- Password used to become IRC Operator. flags = ~encrypted; <---- Tilde "~" means not. So the password used in this block is not encrypted. Without "~", you need to write the password in this block encrypted. privset = "admin"; }; connect "irc2.alpinelab.lan" { <----------- Descriptive name of the server you want to connect to. host="10.0.2.10"; <----------- IP or HOST. They MUST be valid. If hostname, it MUST be an A record. send_password = "Password_To_Server"; <------- Password you sent TO irc2. In irc2 this is "accept_password". accept_password = "Password_From_Server"; <------- Password you expect to receive FROM irc2. In irc2 this is "send_password" flags = compressed, topicburst, autoconn; <------- Autoconn means that irc1 will try automatically to connect to irc2. }; cluster { name = "*.alpinelab.lan"; <----------- Masq to indicate what servers can share the information. Those information are written in the following "flags" entry. flags = kline, tkline, unkline, xline, txline, unxline, resv, tresv, unresv; <--- Check IRC documentation to understand the meaning of those flags. }; shared { oper = "*@*", "*"; <----------- The user@host and the server must be on in order to set klines. flags = all,rehash; <----------- flags: list of what to allow them to place. All oper will receive this. };
You can even remove the *Serv entries. Charybdis itselfs does not have this features, you should use externa programs that works as bot for that (atheme services for example).
In the other server, irc2, configuration is pretty similar.
Those are the only difference of /etc/charybdis/ircd.conf:
serverinfo { sid = "02A"; hub = yes; } operator "ircadmin" { user = "*@*"; password = "MyStrongPassword"; flags = ~encrypted; privset = "admin"; }; connect "irc1.alpinelab.lan" { host="10.0.1.10"; send_password = "Password_From_Server"; accept_password = "Password_To_Server"; flags = compressed, topicburst; };
In flags directive, connect{} block, we do not set "autoconn". This means that irc1 will automatically connect to irc2, but not the contrary.
Charybdis has a lot of other cool features, like ssl connection, spam blacklisting and so on. Look at documentation here: [1]
After having modifyied the ircd.conf in both server, fix the permissions:
chown ircd /etc/charybdis/ircd.conf
chmod 400 /etc/charybdis/ircd.conf
Configure Atheme-iris
Atheme-iris is a nice webchat written in AJAX and Python. It's a fork of the famous qwebirc.
Configuration in pretty simple.
By default, atheme-iris will listen on all interfaces. If you want modify this behaviour, change /etc/conf.d/atheme-iris and set the IP address where atheme will bind.
[execution] args: -n -p 3989 syslog_addr: syslog_port: 514 [irc] server: localhost port: 6667 ssl: false bind_ip: 127.0.0.1 realname: https://irc1.alpinelab.lan ident: nick ident_string: webchat webirc_mode: webirc webirc_password: fish [athemeengine] # Leave this unset to disable all Atheme integration. xmlrpc_path: chan_list_enabled: true chan_list_max_age: 120 chan_list_count: 3 [feedbackengine] from: moo@moo.com to: moo@moo.com smtp_host: 127.0.0.1 smtp_port: 25 [frontend] base_url: <nowiki>http://irc1.alpinelab.lan:9090</nowiki< network_name: AlpineLinux app_title: %(network_name)s Web IRC extra_html: initial_nick: prompt: true chan_prompt: true chan_autoconnect: true static_base_url: / dynamic_base_url: / [atheme] # Even if we don't use nickserv, disabling it cause atheme-iris to not work. # Look at https://github.com/atheme/iris/issues/12 nickserv_login: true chan_list_on_start: true chan_list_cloud_view: false [ui] dedicated_msg_window: false dedicated_notice_window: false hide_joinparts: false simple_color: false fg_color: DDDDDD fg_sec_color: 999999 bg_color: 111111 lastpos_line: true nick_click_query: false nick_colors: false nick_status: false flash_on_mention: false beep_on_mention: false [adminengine] hosts: 127.0.0.1 [proxy] forwarded_for_header: forwarded_for_ips: 127.0.0.1 [tuneback] update_freq: 0.5 maxbuflen: 100000 maxsubscriptions: 1 maxlinelen: 600 dns_timeout: 5 http_ajax_request_timeout: 30 http_request_timeout: 5
In the [execution] block, parameters are overridden by /etc/conf.d/atheme-iris settings.
Replicate the same configuration in irc2.alpinelab.lan.
But in irc2 server, change the entry irc1.alpinelab.lan with irc2.alpinelab.lan.
Atheme-iris will connect to charybdis on 127.0.0.1 ip, according with this directive:
server: localhost
That's all.
Now, you can go with one browser to http://irc1.alpinelab.lan:9090 and another in http://irc2.alpinelab.lan:9090.
Login with two different users in the same channel.
You should view both users on both webclients.
Happy chatting.
Note:
When you login into webchat, you will see "webchat@127.0.0.1".
If you're wondering how change 127.0.0.1 with a spoofed address, you need another auth{} block in charybdis. Look at /etc/charybdis/reference.conf for details.
If you want the real ip address of the client, you need to setup cgi:irc with atheme-iris, and Charybdis will use the module called _mwebirc to "glue" himself with atheme-iris. Cgiirc is available in edge/testing repository.
If you want to remove the button "Menu" which appears in the top-left position into webchat, then:
vim /var/lib/atheme-iris/css/qui.mcss
Look for .dropdown-tab and then add "display: none;" as follows:
.qwebirc-qui .outertabbar .dropdown-tab { float: left; width: 24px; cursor: pointer; cursor: hand; display: none; <---- This is what you need to add. }
Enjoy!
Useful links
IRC Commands
https://en.wikipedia.org/wiki/List_of_Internet_Relay_Chat_commands
*-Line flags