Orchil is a web client for SkotOS and Genesis games. It was created by Wyrhtan and expanded by @saraht45.
The orchil client contains a few bits of code inherited from Skotos' Zealotry and Zealous clients, as well as a few snippets of generic code from StackExchange.
Orchil is licensed under the Creative Commons Attribution-ShareAlike license.
The HTML client allows users to connect to SkotOS games (and Genesis games!) using a modern HTML5 framework. It works as follows:
- A connection comes in to the client, which is stored on your web server.
- The
profiles.js
in the client directory forwards the connection on to yournginx
using port 8080 and a/location
suffix nginx
adjusts the connection and forwards it on awebsocket-to-tcp-tunnel
using a port number such as 8081, stored under anupstream
section, as defined in thedefault
site fornginx
.- The
websocket-to-tcp-tunnel
listens for that port, based on its ownconfig.json
.
You should plan out your ports in advance, so that you know how to write your config files.
Fill out the following worksheet, using the default values given in parentheses, or your own values, as you prefer:
Port-A: `apache` Port: __________ (80) Port-N: `nginx` Port: __________ (8080) Port-N1: `nginx` Suffix: _________ (/game) Port-T: Tunnel Game Port: __________ (8081) Port-TW: Tunnel Woe Port: __________ (8082)
The rest of this doc describes how to set up this series of tubes.
__Game:__ Client (apache @ Port-A) -> Nginx (@Port-N/Port-N1) -> Tunnel (@Port-T) __Woe:__ Client (apache @ Port-A) -> Tunnel (@Port-TW)
Note that it's possible to configure this with a "top level" web server of your choice, including a single NGinX configuration that handles top-level web pages and proxying to the tunnels. This guide is written as though Apache is your top-level web server -- as it is for ChatTheatre. It isn't easy to avoid NGinX for the proxy layer, though, because NGinX has unusually good support for websockets.
These docs use Stretch (Debian 9) as a foundation. It's likely that any other modern Linux would work about the same.
$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
NAME="Debian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
If you are not using stretch or better, you will need to upgrade.
Nginx is a web proxy that will allow you to grab web connections intended for the client (and Woe).
Make sure your cache is up to date before doing any linux installs:
$ apt-get update
Then install the nginx package:
$ apt-get install nginx-full
By default, nginx will try to bind to port 80, and may well fail depending on your site's setup. No worries, you'll be setting it to a less privileged port.
Edit /etc/nginx/sites-available/default.
SkotOS Example:
# lazarus.conf
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream lazarus {
server 127.0.0.1:8081;
}
server {
listen *:8080;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location /lazarus {
proxy_pass http://lazarus;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
Genesis Example:
# eternal_city.conf
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream tec {
server 127.0.0.1:8081;
}
server {
listen *:8080;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location /tec {
proxy_pass http://tec;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
This example will answer connections sent to "8080/lazarus" (in the SkotOS example) or "8080/tec" (in the Genesis example) and send them on to a tunnel program sitting at port 8081 of the local machine. This is the standard alternate port for HTML, and is the best place to put nginx
, but if you chose a different value for Port-N, use that instead.
Change the name "lazarus" or "tec" for the name of your game, using the value you set for Port-N1. The location
is the one that matters, because your client will use that to talk to nginx
; you'll set it again there. But, you should also change proxy_pass
and upstream
for consistency.
Change the port "8081" to match the port that you set for Port-T. You'll see it again when you create the configuration for the tunnel. If you are connecting to a SkotOS machine, you may note that there is no connection for the Tree of Woe here. That is correct: the connection for the game goes from the client to nginx
to the tunnel, but the connection for Woe goes straight from the client to the tunnel.
If you have a firewall, you must open port 8080 (or your alternate Port-N) so that nginx
can respond to non-local connections:
-A INPUT -p tcp --dport 8080 -j ACCEPT
Afterward, be sure to restart your firewall, with a command such as:
iptables-restore < /etc/iptables.firewall.rules
(The specifics will vary based on your setup. This example presumes that your firewall rules are kept in /etc/iptables.firewall.rules
.)
You can now start nginx
. It should now also correctly auto-start on reboot:
# /etc/init.d/nginx stop
# /etc/init.d/nginx start
The tunnel translates the HTML-style connection of the client into WebSockets. It's a standalone piece of code written by a player that will always be running on the game server.
The tunnel is installed on Github, so for easy updates, we'll be installing git
, and using that to clone the current code.
Install git:
$ apt-get install git
The tunnel is written in node.js
, so that needs to be installed as well:
$ curl -sL https://deb.nodesource.com/setup_9.x | bash -
$ apt install nodejs
Some newer versions of Debian "helpfully" install Nodejs when you ask for 9, and this does not seem to work.
If you have this problem, you need to put:
Package: *
Pin: origin deb.nodesource.com
Pin-Priority: 600
In: /etc/apt/preferences.d/nodesource
And then purge and install noedjs again.
Warning: NodeJS 9 is now out of date. But, the tunnel looks like it needs to be updated.
Clone the repo:
$ git clone https://github.com/skotostech/websocket-to-tcp-tunnel /usr/local/websocket-to-tcp-tunnel
You also need to install specific node.js
packages:
$ cd /usr/local/websocket-to-tcp-tunnel/
$ npm install
$ chmod a+x *.sh
Finally, adjust the permissions of the tunnel to be owned by your web server user:
$ chown -R www-data.www-data /usr/local/websocket-to-tcp-tunnel/
Create a /usr/local/websocket-to-tcp-tunnel/config.json
file.
SkotOS Example:
{
"pidFileDirectory": "./",
"logDirectory": "/var/log/tunnel/",
"websocketHeartbeat": 30,
"shutdownDelay": 60,
"servers": [
{
"name": "lazarus",
"listen": 8081,
"send": 443,
"host": "lazarus-game.skotos.net",
"sendTunnelInfo": false
},
{
"name": "Lazarus Tree of Woe",
"listen": 8082,
"send": 2090,
"host": "lazarus-game.skotos.net",
"sendTunnelInfo": false
}
]
}
Note that for a SkotOS game, you're running two tunnels, one for the client (at a port defined in the nginx
) and one for the Tree of Woe (at a port defined in the client).
The host
should be the game's hostname, while the send
port should be its standard port (for SkotOS games, usually 443, and for SkotOS WOE, usually XX90). The listen
ports should be set to Port-T and Port-TW_.
Note that sendTunnelInfo
is always false
for SkotOS machines: they can't handle it.
Genesis Example:
{
"pidFileDirectory": "./",
"logDirectory": "/var/log/tunnel/",
"websocketHeartbeat": 30,
"shutdownDelay": 60,
"servers": [
{
"name": "tec",
"listen": 8081,
"send": 6730,
"host": "tec.skotos.net",
"sendTunnelInfo": true
}
]
}
Again, listen
port should be Port-T, which should match the upstream port from nginx
and host
should be the game's hostname, while the send
port should be its standard port (6730 for TEC). Note that sendTunnelInfo
is true
for Genesis games: they can handle it.
At this point you may need to open more ports, for the ports referenced by the tunnel (Port-T and possibly Port-TW):
SkotOS Example:
-A INPUT -p tcp --dport 8081 -j ACCEPT
-A INPUT -p tcp --dport 8082 -j ACCEPT
Genesis Example:
-A INPUT -p tcp --dport 8081 -j ACCEPT
The may relates to which IP addresses you are using to connect from the client and nginx
to the tunnel, and whether those addresses are local or not. But, you'll often need to do this. When in doubt, do it, and then you can test later if you can remove them.
Afterward, be sure to restart your firewall, with a command such as:
iptables-restore < /etc/iptables.firewall.rules
(The specifics will vary based on your setup. This example presumes that your firewall rules are kept in /etc/iptables.firewall.rules
.)
Make a directory for your logs that matches the logDirectory
in the preferences and be sure it's owned by your web server user.
$ mkdir /var/log/tunnel
$ chown www-data.www-data /var/log/tunnel
You should be able to start the tunnel from the appropriate user by running the process that checks if the tunnel is running:
$ sudo -u www-data /usr/local/websocket-to-tcp-tunnel/search-tunnel.sh
Finally, update your crontab for your www-data
or other web server user to start the tunnel at bootup and to check that it's running every minute:
$ crontab -u www-data -e
@reboot /usr/local/websocket-to-tcp-tunnel/start-tunnel.sh
* * * * * /usr/local/websocket-to-tcp-tunnel/search-tunnel.sh
If you are running the client on the same server as a SkotOS game, then you will need to procure a second IP address for your web server, since SkotOS games already run on ports 80 and 443. (Skip this step if you are using a separate machine for your web serving, including the client, or if you are running a Genesis game.)
The exact methodology for this will vary from site to site. At Linode, you need to enter a service request, carefully explain why a second port is required, convince them that it really is required, and then "Add Public IPv4" from the "Networking" page afterward.
Once you've got a new IP on your machine, you can add it to your interfaces
:
$ cat >> /etc/network/interfaces
# ====================================================================
# Web IP
# ====================================================================
iface eth0:1 inet static
address YOUR-NEW-IP
netmask 255.255.255.0
Then, restart your networking
# /etc/init.d/networking restart
# ifup eth0:1
(On some machines, you may instead need to reboot the whole machine, to get access to the new address, depending on its physical or virtual setup.)
Obviously, you'll also need to use DNS to link YOUR-NEW-IP to a domain name, if you haven't already done so. This can be done on your name server or at your name registrar, depending on your individual setup.
Note that the new server's domain must be the same as the domain that serves your authentication, else your authentication COOKIE will not carry across, and users will be forced to re-login.
The client is the actual HTML5 program which allows players to play your game. It goes through nginx
and the tunnel so that it can convert from HTML to WebSockets, but the hard work is all done here.
You're now ready to install the client, which also comes from GitHub:
$ git clone https://github.com/skotostech/orchil /var/www/html/client
You will probably need to adjust profiles.js
to include the connections for your client and your WOE. Here you're going to need to match Port-N (for port
), Port-N1 (for path
), and on a SkotOS machine Port-TW (for woe_port). Obviously, the
serverwill match where
nginx` is running.
SkotOS Example:
var profiles = {
"portal_lazarus":{
"method": "websocket",
"protocol": "ws",
"server": "lazarus.skotos.net",
"port": 8080,
"woe_port": 8082,
"path": "/lazarus",
"extra": "",
"reports": false,
"chars": true
}
};
Genesis Example:
var profiles = {
"portal_tec":{
"method": "websocket",
"protocol": "ws",
"server": "tec.skotos.net",
"port": 8080,
"path": "/tec",
"extra": "tec",
"reports": true,
"chars": false
}
}
Apache is needed to serve the client.
Install the package using apt-get
.
$ apt-get install apache2
If you're installing on a SkotOS machine, you'll probably see errors in the install. They just have to do with apache2
not being able to start because port 80 is already in use; no worries, you'll resolve that in the next step.
You'll need to set up an apache site for the client (unless you're planning to access it through your main web site). This will require creating a /etc/apache2/sites-available/client.conf
file that looks something like this:
<VirtualHost YOUR-NEW-IP:80>
ServerName YOUR-CLIENT-DNS
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html/client
<Directory /var/www/html/client/>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Then enable it:
$ a2ensite client
Enabling site client.
It would be very unusual to not be using port 80 for Port-A, because that's the standard for web browsers. But, if you had to change that for some reason, you'd do it here and in the later sections.
If you're using a secondary IP address, you'll also need to change /etc/apache2/ports.conf
, add your IP address in front of the port numbers 80 and 443 on the Listen
lines, followed by a colon:
Listen YOUR-NEW-IP:80
<IfModule ssl_module>
Listen YOUR-NEW-IP:443
</IfModule>
<IfModule mod_gnutls.c>
Listen YOUR-NEW-IP:443
</IfModule>
If you already have other IP addresses on this apache
, just add the new one as a separate line.
You can now start apache
:
$ /etc/init.d/apache2 start
Integrate the client in the game's startup files (for SkotOS) or its web files (for Genesis).
SkotOS Example:
Add something like the following to the character portal page:
<z name="$(UDat.name)" udat="$(UDat.Dat)">$[$username = $name; $dat = $udat;]</z>
$[$bodies = Udat::query_bodies_in_roster($user: $username); ]
<for var="thisbody" val="$(bodies)">
<tr>
<td><b>$[Describe($thisbody)]</b></td>
<td>[<a href="javascript:bareWin('http://client.lazarus.skotos.net/lazarus/lazarus.htm?charName=$[name($thisbody)[15..strlen(name($thisbody))-1]]', '_blank', 720, 480);">Orchil</a> (experimental)]</td>
</tr>
</for>
Genesis Example:
Create a web page that links to the client:
<p><b>General Clients:</b>
<ul>
<li><a href="http://client.tec.skotos.net/tec/tec.htm">Orchil client</a> (modern browsers)
</ul>
And your client is now ready to go!
At some time you may hear that the client or the web tunnel was updated. If so, you'll need to go to the directory that has that repo installed and update it. This is how to update the client:
$ cd /var/www/html/client
$ git pull