Pylink Install Guide
PyLink is a relay that can help connect channels across multiple networks together.
Advantages:
Can link up channels on multiple networks quickly
Shows all users on the home server
Disadvantages:
Bloated and insecure
Buggy and unstable, crashes frequently
Requires channel owner to op the bot to link
Bad spam defenses
PyLink should eventually be replaced with a more reliable relay written in pure C.
Installation
First we install all python related dependencies:
$ doas pkg_add python%253.8 py3-pip git
$ doas useradd -m -g =uid -c pylink -d /home/pylink -s /bin/ksh pylink
$ doas su pylink
$ cd
$ git clone https://github.com/jlu5/PyLink && cd PyLink
$ pip3.8 install setuptools --user
$ pip3.8 install pyyaml --user
$ pip3.8 install cachetools --user
$ pip3.8 install passlib --user
$ pip3.8 install Unidecode --user
$ pip3.8 install psutil --user
$ cd PyLink
$ python3 setup.py install --user
PyLink does not appear very secure, so we will create a chroot for it. We run the following commands as root:
mkdir -p /home/pylink/usr/local/bin
mkdir -p /home/pylink/usr/local/lib
mkdir -p /home/pylink/usr/local/include/
mkdir -p /home/pylink/usr/local/lib/pkgconfig/
mkdir -p /home/pylink/usr/local/share/doc/
mkdir -p /home/pylink/usr/lib
mkdir -p /home/pylink/usr/libexec
mkdir -p /home/pylink/var/run/
mkdir -p /home/pylink/usr/local/man/man1/
mkdir -p /home/pylink/usr/local/share/aclocal-1.11/am/
mkdir -p /home/pylink/etc/ssl/
cp /usr/local/bin/python3 /home/pylink/usr/local/bin/
cp /usr/local/bin/python3.8-config /home/pylink/usr/local/bin/
cp /usr/local/bin/python3-config /home/pylink/usr/local/bin/
cp /usr/local/bin/python3.8 /home/pylink/usr/local/bin/
cp /usr/local/lib/libpython3.8.so.0.0 /home/pylink/usr/local/lib/
cp /usr/local/lib/libintl.so.7.0 /home/pylink/usr/local/lib/
cp /usr/lib/libpthread.so.26.1 /home/pylink/usr/lib/
cp /usr/lib/libutil.so.15.0 /home/pylink/usr/lib/
cp /usr/lib/libm.so.10.1 /home/pylink/usr/lib/
cp /usr/lib/libc.so.96.0 /home/pylink/usr/lib/
cp /usr/local/lib/libiconv.so.7.0 /home/pylink/usr/local/lib/
cp /usr/libexec/ld.so /home/pylink/usr/libexec/
cp /var/run/ld.so.hints /home/pylink/var/run/
cp -R /usr/local/include/python3.8 /home/pylink/usr/local/include/
cp /usr/local/lib/pkgconfig/python-3.8.pc /home/pylink/usr/local/lib/pkgconfig/
cp /usr/local/lib/pkgconfig/python3.pc /home/pylink/usr/local/lib/pkgconfig/
cp /usr/local/lib/pkgconfig/python-3.8-embed.pc /home/pylink/usr/local/lib/pkgconfig/
cp /usr/local/lib/pkgconfig/python3-embed.pc /home/pylink/usr/local/lib/pkgconfig/
cp -R /usr/local/lib/python3.8 /home/pylink/usr/local/lib/
cp /usr/local/man/man1/python3.1 /home/pylink/usr/local/man/man1/
cp /usr/local/man/man1/python3.8.1 /home/pylink/usr/local/man/man1/
cp -R /usr/local/share/doc/python3.8 /home/pylink/usr/local/share/doc/
cp /usr/local/share/aclocal-1.11/python.m4 /home/pylink/usr/local/share/aclocal-1.11/
cp /usr/local/share/automake-1.11/am/python.am /home/pylink/usr/local/share/aclocal-1.11/am/
cp /etc/resolv.conf /home/pylink/etc/
cp /etc/ssl/cert.pem /home/pylink/etc/ssl/
cp /usr/local/bin/pip3.8 /home/pylink/usr/local/bin/
cp -R /usr/lib/ /home/pylink/usr/
cp -R /usr/local/lib/ /home/pylink/usr/local/
chroot -u pylink -g pylink /home/pylink pip3.8 install setuptools --user
chroot -u pylink -g pylink /home/pylink pip3.8 install pyyaml --user
chroot -u pylink -g pylink /home/pylink pip3.8 install cachetools --user
chroot -u pylink -g pylink /home/pylink pip3.8 install passlib --user
chroot -u pylink -g pylink /home/pylink pip3.8 install unidecode --user
(:if false:)
chroot -u pylink -g pylink /home/pylink pip3.8 install psutil --user
(:ifend:)
Afterwards, we run the following as the user pylink:
$ cd ~/PyLink
$ cp example-conf.yml pylink.yml
We then edit pylink.yml:
pylink:
nick: BotNick
ident: BotIdent
realname: Relay
serverdesc: Relay
prefix: "&"
spawn_services: false
In order for ident to display properly, you must install and configure oidentd.
You will want to run this as the user pylink to generate a password hash:
/home/pylink/PyLink/pylink-mkpasswd
Password:
$pbkdf2-sha256$29000$AeBcKwWA0HqvNUYIgbBWqg$9EPkgnfsLsZHJk9YJy16MKqTEKCvZohdT1MyAbXQTjQ
The login section below lets us pick a username and password for administering the bot. Use the password hash you generated above:
login:
accounts:
username:
password: "$6$rounds=81447$WlVlZYCgbnjPmVqy$28Tu/Zl0xNpePqimax2wABKn5GCoWomYEI1Pu5jqYyQNULazR4BxQmscZ0MgBHqBCCke.3u5eOtBSZwL3WwVf0"
encrypted: true
#require_oper: true
#hosts: ["*!*@localhost", "*!*@trusted.isp"]
permissions:
"username":
- "*"
For extra security, we recommend you uncomment #require_oper and set it to true, so that only opers can login. We also recommend you uncomment #hosts and set it to properly match your vhost. This will make it harder for someone to steal your relay.
In the permissions block, you can replace username with a full hostmask for more security.
Now we specify the server running on our VPS:
servers:
your:
ip: 127.0.0.1
port: 16667
recvpass: "abcdefghijklmnopqrstuvwxyz"
sendpass: "abcdefghijklmnopqrstuvwxyz"
bindhost: 10.0.0.1
netname: "YourNet"
hostname: "relay.example.com"
sid: "0PY"
sidrange: "8##"
protocol: "ngircd"
maxnicklen: 16
ssl: false
autoconnect: 10
For the short network name (here named your
), pick something 3-5 letters that represents your network. Keep it short. ip should remain 127.0.0.1 in order to connect to localhost. We want to use port 16667 (ports 16667 and 16697 are reserved for server to server links). Note that we do not need to use SSL because we are connecting to localhost. recvpass and sendpass are the server passwords we must specify in /etc/ngircd/ngircd.conf in the [Server] block. The netname is YourNet, the hostname depends upon your team's domain. You can leave sid and sidrange unchanged.
For each server you want to connect, add a new block like below:
oftc:
ip: irc.oftc.net
port: 6697
netname: "OFTC"
protocol: "clientbot"
pylink_nick: BotNick
pylink_ident: BotIdent
pylink_altnicks: ["BotNick`", "BotNick-"]
ssl: true
autoconnect: 30
throttle_time: 1.0
This block is for OFTC.
plugins:
- commands
- networks
- ctcp
- relay
- relay_clientbot
- servprotect
- antispam
- raw
We are going to uncomment the relay and relay_clientbot plugins so we can relay in client mode.
Next, we set up logging:
logging:
console: INFO
channels:
# your:
# "#services":
# loglevel: INFO
# "#pylink-notifications":
# loglevel: WARNING
files:
"errors":
loglevel: ERROR
"commands":
loglevel: INFO
If you want to log to a channel, uncomment those lines, then replace your
with your shortened network name and replace with your channel names. I prefer to just have error messages go to console and files.
We delete the changehost plugin, then add clientbot_styles to the relay plugin in order to make the relay less noisy:
relay:
allow_free_oper_links: true
tag_nicks: true
forcetag_nicks:
- "*Serv"
separator: "/"
allow_clientbot_pms: true
hideoper: true
show_netsplits: false
accept_weird_senders: false
whois_show_accounts: all
whois_show_server: opers
clientbot_styles:
ACTION: ""
JOIN: ""
KICK: ""
MESSAGE: "<$sender> $text"
MODE: ""
NICK: ""
NOTICE: "<$sender> $text"
PART: ""
PM: "PM from $sender on $netname: $text"
PNOTICE: "<$sender> $text"
QUIT: ""
SJOIN: ""
SQUIT: ""
I delete the games and global plugin. Then, for automode and stats:
automode:
nick: Automode
joinmodes: 'o'
prefix: "@"
stats:
time_format: "%25c"
Now we configure antispam to block mass highlights, part/quit floods, and profanity. You can adjust the word lists (the word shibboleth is used as a test phrase):
antispam:
masshighlight:
enabled: true
punishment: block
reason: "Mass highlight spam is prohibited"
min_length: 50
min_nicks: 5
textfilter:
enabled: true
punishment: block
reason: "Spam is prohibited"
watch_pms: true
textfilter_globs:
- "*shibboleth*"
partquit:
You'll need to add this to /etc/ngircd/ngircd.conf:
[Server]
Name = relay.example.com
Host = 127.0.0.1
Bind = 38.81.163.143
Port = 16667
MyPassword = fyLnwwxSvxc2gpn3AM994FMitD
PeerPassword = fyLnwwxSvxc2gpn3AM994FMitD
;Group = 123
Passive = no
SSLConnect = no
Replace 38.81.163.143 with your IP address.
We reload ngircd.conf:
$ doas rcctl reload ngircd
Then we start PyLink by running it inside a chroot:
$ doas su
# export HOME=/
# chroot -u pylink -g pylink /home/pylink python3.8 PyLink/pylink PyLink/pylink.yml
Logging in
/msg <botnick> login username password
/msg <botnick> create #channel
/msg <botnick> remote <other> link <your> #channel
15:39 -botnick(botident@f6e1cdd3)- Joining '#channel' now to check for op status; please run this command again after I join.
Now op the bot, then run the command again:
/msg <botnick> remote <other> link <your> #channel
15:39 -botnick(botident@f6e1cdd3)- Done.
Finally, to prevent pylink from accidentally de-opping other users:
/msg <botnick> claim #channel -
Troubleshooting
Sometimes PyLink may crash, and when you attempt to restart it, it says that the PID file already exists:
$ doas su
# export HOME=/
# chroot -u pylink -g pylink /home/pylink python3.8 PyLink/pylink PyLink/pylink.yml
2021-02-12 00:19:39,495 [ERROR] PID file 'pylink.pid' exists; aborting!
Simply remove the file:
# rm /home/pylink/pylink.pid
# rm /home/pylink/PyLink/pylink.pid
If the bot ever gets stuck and you can't kill it:
$ ps ax | grep pylink
22986 p7 S+ 0:03.08 python3.8 PyLink/pylink PyLink/pylink.yml
$ doas kill -KILL 22986
Replace 22986 with whatever process ID python has.
Or use an simpler command:
cd /home/pylink
doas kill -KILL `cat pylink.pid`