From fa8fb63e79669faaa3f0227827b135e5c04e801b Mon Sep 17 00:00:00 2001 From: xfnw Date: Wed, 14 Jul 2021 22:54:14 -0400 Subject: [PATCH] init --- .gitignore | 1 + auth.j2 | 56 +++++++++++ class.j2 | 30 ++++++ connect.j2 | 27 +++++ dnsbl.j2 | 0 ircd.j2 | 281 ++++++++++++++++++++++++++++++++++++++++++++++++++++ motd.j2 | 19 ++++ openrc.j2 | 6 ++ operator.j2 | 0 solanum.yml | 99 ++++++++++++++++++ systemd.j2 | 10 ++ 11 files changed, 529 insertions(+) create mode 100644 .gitignore create mode 100644 auth.j2 create mode 100644 class.j2 create mode 100644 connect.j2 create mode 100644 dnsbl.j2 create mode 100644 ircd.j2 create mode 100644 motd.j2 create mode 100644 openrc.j2 create mode 100644 operator.j2 create mode 100644 solanum.yml create mode 100644 systemd.j2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6ff331c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +hosts diff --git a/auth.j2 b/auth.j2 new file mode 100644 index 0000000..63b64af --- /dev/null +++ b/auth.j2 @@ -0,0 +1,56 @@ +/* auth {}: allow users to connect to the ircd (OLD I:) + * auth {} blocks MUST be specified in order of precedence. The first one + * that matches a user will be used. So place spoofs first, then specials, + * then general access, then restricted. + */ +auth { + /* user: the user@host allowed to connect. Multiple IPv4/IPv6 user + * lines are permitted per auth block. This is matched against the + * hostname and IP address (using :: shortening for IPv6 and + * prepending a 0 if it starts with a colon) and can also use CIDR + * masks. + */ + user = "*@198.51.100.0/24"; + user = "*test@2001:db8:1:*"; + + /* password: an optional password that is required to use this block. + * By default this is not encrypted, specify the flag "encrypted" in + * flags = ...; below if it is. + */ + password = "letmein"; + /* spoof: fake the users user@host to be be this. You may either + * specify a host or a user@host to spoof to. This is free-form, + * just do everyone a favour and dont abuse it. (OLD I: = flag) + */ + spoof = "I.still.hate.packets"; + + /* Possible flags in auth: + * + * encrypted | password is encrypted with mkpasswd + * spoof_notice | give a notice when spoofing hosts + * exceed_limit (old > flag) | allow user to exceed class user limits + * kline_exempt (old ^ flag) | exempt this user from k/g/xlines, + * | dnsbls, and proxies + * proxy_exempt | exempt this user from proxies + * dnsbl_exempt | exempt this user from dnsbls + * spambot_exempt | exempt this user from spambot checks + * shide_exempt | exempt this user from serverhiding + * jupe_exempt | exempt this user from generating + * warnings joining juped channels + * resv_exempt | exempt this user from resvs + * flood_exempt | exempt this user from flood limits + * USE WITH CAUTION. + * no_tilde (old - flag) | don't prefix ~ to username if no ident + * need_ident (old + flag) | require ident for user in this class + * need_ssl | require SSL/TLS for user in this class + * need_sasl | require SASL id for user in this class + */ + flags = kline_exempt, exceed_limit; + class = "opers"; +}; + +auth { + user = "*@*"; + class = "users"; +}; + diff --git a/class.j2 b/class.j2 new file mode 100644 index 0000000..9ff45b2 --- /dev/null +++ b/class.j2 @@ -0,0 +1,30 @@ +/* class {} blocks MUST be specified before anything that uses them. That + * means they must be defined before auth {} and before connect {}. + */ +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 = 3000; + sendq = 400 kbytes; +}; + +class "opers" { + ping_time = 5 minutes; + number_per_ip = 100; + max_number = 1000; + sendq = 1 megabyte; +}; + +class "server" { + ping_time = 5 minutes; + connectfreq = 5 minutes; + max_autoconn = 10; + max_number = 100; + sendq = 4 megabytes; +}; + diff --git a/connect.j2 b/connect.j2 new file mode 100644 index 0000000..fb1032e --- /dev/null +++ b/connect.j2 @@ -0,0 +1,27 @@ +{% for host in ansible_play_hosts %} +{% if host != inventory_hostname %} +connect "{{ host }}" { + host = "{% if hostvars[host]['pahost'] is defined %}{{ hostvars[host]['pahost'] }}{% else %}{{ host }}{% endif %}"; + send_password = "{{ hostvars[host]['linkpass'] }}"; + accept_password = "{{ linkpass }}"; + port = {% if hostvars[host]['paport'] is defined %}{{ hostvars[host]['paport'] }}{% else %}6697{% endif %}; + class = "server"; +{% if hostvars[host]['ssl_exists']['stat']['exists'] %} + fingerprint = "{{ hostvars[host]['ssl_fingerprint']['stdout'] }}"; +{% endif %} + flags = {% if hostvars[host]['paport'] is not defined or hostvars[host]['paport'] != 6667 %}ssl, {% endif %}topicburst{% if autoconn is defined and autoconn == host %}, autoconn{% endif %}; +}; +{% endif %} +{% endfor %} + +{% if services is defined %} +connect "services." { + host = "127.0.0.1"; + send_password = "{{ services }}"; + accept_password = "{{ services }}"; + port = 6667; + class = "server"; + flags = topicburst; +}; +{% endif %} + diff --git a/dnsbl.j2 b/dnsbl.j2 new file mode 100644 index 0000000..e69de29 diff --git a/ircd.j2 b/ircd.j2 new file mode 100644 index 0000000..abdaa1b --- /dev/null +++ b/ircd.j2 @@ -0,0 +1,281 @@ + +/* Extensions */ +loadmodule "extensions/chm_nonotice"; +loadmodule "extensions/chm_operpeace"; +loadmodule "extensions/chm_operonly"; +loadmodule "extensions/extb_account"; +loadmodule "extensions/extb_canjoin"; +loadmodule "extensions/extb_channel"; +loadmodule "extensions/extb_combi"; +loadmodule "extensions/extb_extgecos"; +loadmodule "extensions/extb_hostmask"; +loadmodule "extensions/extb_oper"; +loadmodule "extensions/extb_realname"; +loadmodule "extensions/extb_server"; +loadmodule "extensions/extb_ssl"; +loadmodule "extensions/extb_usermode"; +loadmodule "extensions/helpops"; +loadmodule "extensions/hurt"; +loadmodule "extensions/m_extendchans"; +loadmodule "extensions/m_findforwards"; +loadmodule "extensions/m_identify"; +loadmodule "extensions/m_locops"; +loadmodule "extensions/sno_farconnect"; +loadmodule "extensions/sno_globalkline"; +loadmodule "extensions/sno_globalnickchange"; +loadmodule "extensions/sno_globaloper"; +loadmodule "extensions/override"; +loadmodule "extensions/override_kick_immunity"; + +serverinfo { + name = "{{ inventory_hostname }}"; + sid = "{{ sid }}"; + description = "{% if description is defined %}{{ description }}{% else %}solanum fox server{% endif %}"; + network_name = "vulpineawoo"; + +{% if ssl_exists.stat.exists %} + ssl_cert = "etc/ssl.pem"; + ssl_private_key = "etc/ssl.key"; + ssl_dh_params = "etc/dh.pem"; + ssld_count = 1; + +{% endif %} + default_max_clients = 1024; + nicklen = 30; +}; + +admin { + name = "xfnw"; + description = "friendly vulpine, requires payment in hugs."; + email = "xfnw@riseup.net"; +}; + +{% include 'class.j2' %} + +listen { + defer_accept = yes; + port = 6667; +{% if ssl_exists.stat.exists %} + sslport = 6697; + wsock = yes; + sslport = 7001; +{% endif %} +}; + +{% include 'auth.j2' %} + +privset "wombat" { + privs = oper:general, oper:kline, oper:unkline, oper:xline, oper:kill, oper:testline, oper:privs, + oper:resv, oper:cmodes, oper:mass_notice, oper:remoteban, usermode:helpops, oper:message, + auspex:oper, auspex:hostname, auspex:umodes, auspex:cmodes, oper:receive_immunity, oper:wallops; +}; + +privset "dingo" { + extends = "wombat"; + privs = oper:override, oper:ojoin, oper:operwall, + oper:dehelper, oper:massnotice, usermode:servnotice; +}; + +privset "shark" { + extends = "dingo"; + privs = oper:kline, oper:remoteban, snomask:nick_changes; +}; + +privset "bandicoot" { + extends = "dingo"; + privs = oper:routing; +}; + +privset "jellyfish" { + extends = "bandicoot"; + privs = oper:admin, oper:die, oper:rehash, oper:spy, oper:grant; +}; + +{% include 'operator.j2' %} + +{% include 'connect.j2' %} + +service { + name = "services."; +}; + +cluster { + name = "*"; + flags = kline, tkline, unkline, xline, txline, unxline, resv, tresv, unresv, all; +}; + +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 = 150; + max_chans_per_user_large = 300; + 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; + autochanmodes = "+nt"; + displayed_usercount = 3; + strip_topic_colors = no; + opmod_send_statusmsg = no; +}; + +serverhide { + flatten_links = yes; + links_delay = 5 minutes; + hidden = no; + disable_hidden = no; +}; + +{% include 'dnsbl.j2' %} + +alias "NickServ" { + target = "NickServ"; +}; + +alias "ChanServ" { + target = "ChanServ"; +}; + +alias "OperServ" { + target = "OperServ"; +}; + +alias "HostServ" { + target = "HostServ"; +}; + +alias "MemoServ" { + target = "MemoServ"; +}; + +alias "BotServ" { + target = "BotServ"; +}; + +alias "CatServ" { + target = "CatServ"; +}; + +alias "ALIS" { + target = "ALIS"; +}; + +alias "NS" { + target = "NickServ"; +}; + +alias "CS" { + target = "ChanServ"; +}; + +alias "OS" { + target = "OperServ"; +}; + +alias "HS" { + target = "HostServ"; +}; + +alias "MS" { + target = "MemoServ"; +}; + +alias "BS" { + target = "BotServ"; +}; + +general { + hide_error_messages = opers; + hide_spoof_ips = yes; + default_umodes = "+"; + + default_operstring = "is an IRC Operator"; + default_adminstring = "is a Server Administrator"; + servicestring = "is a Network Service"; + + sasl_service = "SaslServ"; + 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_with_reason = yes; + hide_tkdline_duration = no; + kline_reason = "K-Lined"; + identify_service = "NickServ@services."; + 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_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; + post_registration_delay = 0 seconds; + 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; + certfp_method = sha512; + hide_opers_in_whois = no; + tls_ciphers_oper_only = no; +}; + +modules { + path = "modules"; + path = "modules/autoload"; +}; + diff --git a/motd.j2 b/motd.j2 new file mode 100644 index 0000000..1955bb0 --- /dev/null +++ b/motd.j2 @@ -0,0 +1,19 @@ +Welcome to + + ▌ ▌▞▀▖ + ▚▗▘▙▄▌ vulpineawoo + ▝▞ ▌ ▌ running sandcat-approved software since 2019 + ▘ ▘ ▘ + +You are connected to {{ inventory_hostname }}{% if sponsor is defined %}, donated by {{ sponsor }}{% endif %} + + +Other servers on the network: +{% for host in ansible_play_hosts %} +{% if host != inventory_hostname %} + - {{ host }} +{% endif %} +{% endfor %} + +Pop in #vulpineawoo for help, or do /list for a list of channels. + diff --git a/openrc.j2 b/openrc.j2 new file mode 100644 index 0000000..d3ebda2 --- /dev/null +++ b/openrc.j2 @@ -0,0 +1,6 @@ +#!/sbin/openrc-run + +name="solanum ircd" +command="/home/ircd/ircd/bin/solanum -pidfile /var/run/solanum-ircd" +command_user="ircd" +pidfile="/var/run/solanum-ircd" diff --git a/operator.j2 b/operator.j2 new file mode 100644 index 0000000..e69de29 diff --git a/solanum.yml b/solanum.yml new file mode 100644 index 0000000..cdb05da --- /dev/null +++ b/solanum.yml @@ -0,0 +1,99 @@ +- hosts: testnet + + tasks: + - name: install dependencies for alpine + package: + name: sudo,musl-dev,libressl-dev,make,automake,gcc,curl,git,byacc,flex,libtool,sqlite-dev,autoconf,util-linux + state: present + when: ansible_distribution == 'Alpine' + + - name: install dependencies for debian + package: + name: sudo,buildessential,autotools-dev,automake,cmake,make,libtool,byacc,flex,openssl-dev,sqlite3 + state: present + when: ansible_distribution == 'Debian' + + - name: create ircd user + user: + name: ircd + + - name: download solanum + git: + repo: 'https://github.com/vulpineawoo/solanum' + dest: /home/ircd/solanum + become: yes + become_user: ircd + + - name: check if autogen needed + stat: + path: /home/ircd/solanum/configure + register: alreadyautogen + + - name: autogen + command: ./autogen.sh + args: + chdir: /home/ircd/solanum + become: yes + become_user: ircd + when: not alreadyautogen.stat.exists + + - name: configure + command: ./configure + args: + chdir: /home/ircd/solanum + become: yes + become_user: ircd + when: not alreadyautogen.stat.exists + + - name: make + make: + chdir: /home/ircd/solanum + become: yes + become_user: ircd + + - name: make install + make: + chdir: /home/ircd/solanum + target: install + become: yes + become_user: ircd + + - name: check for ssl cert + stat: + path: /home/ircd/ircd/etc/ssl.pem + register: ssl_exists + + - name: get ssl fingerprint + command: /home/ircd/ircd/bin/solanum-mkfingerprint sha512 /home/ircd/ircd/etc/ssl.pem + register: ssl_fingerprint + when: ssl_exists.stat.exists + + - name: create ircd.conf + template: + src: ircd.j2 + dest: /home/ircd/ircd/etc/ircd.conf + + - name: create ircd.motd + template: + src: motd.j2 + dest: /home/ircd/ircd/etc/ircd.motd + + - name: create openrc service + template: + src: openrc.j2 + dest: /etc/init.d/solanum + mode: 0755 + when: ansible_distribution == 'Alpine' + + - name: create systemd service + template: + src: systemd.j2 + dest: /etc/systemd/system/solnum.service + mode: 0755 + when: ansible_distribution == 'Debian' + + - name: enable service + service: + name: solanum + state: reloaded + enabled: yes diff --git a/systemd.j2 b/systemd.j2 new file mode 100644 index 0000000..d3207bd --- /dev/null +++ b/systemd.j2 @@ -0,0 +1,10 @@ +[Unit] +Description=solanum ircd + +[Service] +Type=forking +User=ircd +ExecStart=/home/ircd/ircd/bin/solanum + +[Install] +WantedBy=default.target