Small but complete Minus server
implemented as a BASH script
This fully complies with the Minus Protocol Specification.
Save this as mserver
and mark it executable with chmod
or your GUI file manager. This requires mini-inetd
, which you will probably find in a package called Tcputils
. This package also includes tcpconnect
which is mentioned below.
Start mserver
with mserver start
and stop it with mserver stop
.
You are encouraged to edit the values of indexfile
and requestlog
. If you do not, a new directory will be created in ${HOME}
called minus-contents
. You can edit your index file and your pages with an ordinary text editor.
To experiment with your new server (before you start serving it as a Tor Onion Service) you can use tcpconnect
. printf "" | tcpconnect -r -v 127.0.0.1 1990
will get your index.minus
page. This is like the index.html
page in HTTP. It should contain the URLs of your other pages and files.
The printf
command sends the specifier to the server. In the example above, a zero-length specifier is sent, so, in accordance with the Minus specification, the specifier defaults to index.minus
.
Please read the comments in mserver
. Comments to this post are welcome.
#!/bin/bash
# mserver 1.0
# Copyright (C) 2022 the author indicated below
# The author of mserver made an OpenPGP,
# RSA key pair. The fingerprint of this key pair is
# BA34F30AC917CB0714884A3DA6BDBF5757B731E9
# mserver is distributed under the terms of the GNU General
# Public License, version 3 (https://www.gnu.org/licenses/gpl.html).
# mserver is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY--without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# Only the path name in indexfile determines the file served. No part of user input is used as
# part of the path name of the file. This is much more secure than determining the path name directly from
# user input. A file can not be served simply because it is in a certain directory. Only listing the file in
# indexfile makes it available. Specifiers need not contain any part of the path names of the files they
# specify.
# Each line of indexfile is
# <specifier>|<path name of file>
# specifier may not contain any characters except "0123456789abcdefghijklmonpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-/_"
# because all other characters are removed from theinput.
# Path names that do not begin with / are relative to the directory of indexfile.
thisfile="$(readlink -e "${0}")"
if test "${1}" = "start"
then
if test -z "$(ps -o args -C mini-inetd | grep -F "${thisfile}")"
then
mini-inetd 127.0.0.1:1990 "${thisfile}" & # start serving
fi
exit 0
elif test "${1}" = "stop"
then
theID="$(ps -o pid,args -C mini-inetd | grep -F "${thisfile}" | sed "s/^[ \t]*//" | grep -o "^[0-9]*")"
if test -n "${theID}"
then
kill ${theID} # stop serving
fi
exit 0
fi
# mini-inetd listens for tcp connections on port 1990.
# For each connection, this file is started with standard input and standard output connected to the socket.
# When this file exits, the tcp connection is closed.
if test "$(ps -o args -C "$(basename "${thisfile}")" | grep -cF "${thisfile}")" -gt 12 # mitigate DoS attacks
then
exit 0
fi
read -t 30 -n 255 theinput # Read 1 line, but no more than 255 bytes. Timeout after 30 seconds to mitigate DoS attacks.
theinput="$(printf "%s" "${theinput}" | tr -dc "0-9A-Za-z\.\-/_" | sed "s/^\///")" # remove anything not allowed and initial /
# set indexfile and requestlog to desired values
indexfile="${HOME}/minus-contents/minus.index"
requestlog="/dev/null" # this can be /dev/null to prevent logging
indexdir="$(dirname "${indexfile}")"
if ! test -f "${indexfile}" # no index file
then
mkdir -p "${indexdir}"
printf "%s\n%s" "index.minus|index.minus" "other.minus|other.minus" > "${indexfile}"
printf "%s\n" "This is the home or index page." > "${indexdir}/index.minus"
printf "%s\n" "This is the other page." > "${indexdir}/other.minus"
fi
cd "${indexdir}"
if test -z "${theinput}" # if no input, default to index.minus
then
theinput="index.minus" # This is the home or index page. It should have links to the other pages.
fi
if test -n "$(grep -m 1 -o "^${theinput}|" "${indexfile}" | grep -F "${theinput}|")" # necessary because theinput may contain .
then
thefile="$(grep -m 1 "^${theinput}|" "${indexfile}" | sed "s/^[^|]*|//")" # use indexfile to find path name of the file
else
thefile=""
fi
if test -n "${thefile}"
then
cat "${thefile}" # return the file
printf "%s sent %s\n" "$(date "+%Y-%m-%d %I:%M:%S %p")" "${theinput}" >> "${requestlog}"
else
printf "\"%s\" does not specify a file that this server will serve.\nTry \"index.minus\".\n" "${theinput}" # return an error
printf "%s miss %s\n" "$(date "+%Y-%m-%d %I:%M:%S %p")" "${theinput}" >> "${requestlog}"
fi
exit 0
#internet #protocol #tcp #file-server #hypertext #minus #minus-protocol
There are no comments yet.