355 lines
11 KiB
Markdown
355 lines
11 KiB
Markdown
# Linux Fax Stack Setup (HylaFax & SIP)
|
||
|
||
Linux Fax Stack using Hylafax and t38modem.
|
||
|
||
***THIS GUIDE IS WIP***
|
||
|
||
This guide was created using information from the opalvoid wiki (http://wiki.opalvoip.org/index.php?n=Main.HomePage)
|
||
|
||
## Softwarestack
|
||
|
||
### ptlib
|
||
(legacy) library for doing a little bit of everything.
|
||
|
||
### Opal
|
||
Voice codec used by e.g. mumble.
|
||
|
||
### t38modem
|
||
Emulates a serial modem from SIP connetion
|
||
|
||
### Hylafax
|
||
Enterprise grade software, managing physical and emulated modems.
|
||
|
||
Has some problems: https://github.com/lexbailey/compilerfax/blob/main/hylafax_is_broken
|
||
|
||
## Operating Systems
|
||
Unfortunately this software stack uses a lot of legacy software. Because of this, this guide was only tested on specific software versions
|
||
|
||
### Debian 12 Bookworm
|
||
For Debian 12, we´ll only install dependencies which are hard requirements.
|
||
For this guide we'll use ptlib 2.18.6 and opal 3.18.6.
|
||
|
||
#### Installing Requirements
|
||
First we'll need some packages
|
||
```bash
|
||
apt-get install build-essential git wget pkg-config libssl-dev libsrtp2-dev libspandsp-dev -y
|
||
```
|
||
#### Download sourcecode
|
||
Versions:
|
||
- libpt (2.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
|
||
- opal (3.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
|
||
- t38mdem (4.6.2) https://github.com/hehol/t38modem/releases/tag/4.6.2
|
||
|
||
#### ptlib
|
||
```bash
|
||
./configure
|
||
make
|
||
make install
|
||
```
|
||
|
||
#### opal
|
||
```bash
|
||
./configure
|
||
make -j5
|
||
make runtest
|
||
make install
|
||
```
|
||
|
||
#### t38modem
|
||
If you are getting error about `-1` not being able to be casted to a `long unsigned int` due to `-Wnarrowing` inside `dle.cxx`, you can add `-Wno-narrowing` after the `CPPFLAGS` in the Makefile to disable this error
|
||
|
||
```bash
|
||
git clone https://github.com/hehol/t38modem
|
||
cd t38modem
|
||
make
|
||
```
|
||
|
||
If running the t38modem executable, you should run these commands
|
||
```bash
|
||
cp /usr/local/lib/libpt.so.2.18.6 /lib
|
||
cp /usr/local/lib/libopal.so.3.18.6 /lib
|
||
```
|
||
|
||
To install t38modem run
|
||
```bash
|
||
cp ./t38modem /usr/local/bin
|
||
```
|
||
|
||
### Ubuntu 20.04 LTS
|
||
Was tested on Ubuntu 20.04 LTS VM (VirtualBox, LXC?)
|
||
|
||
You can relies heavily on http://wiki.opalvoip.org/index.php?n=Main.HomePage
|
||
|
||
Versions:
|
||
- libpt (2.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
|
||
- opal (3.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
|
||
- t38mdem (4.6.2) https://github.com/hehol/t38modem/releases/tag/4.6.2
|
||
|
||
Follow http://wiki.opalvoip.org/index.php?n=Main.BuildingPTLibUnix and http://wiki.opalvoip.org/index.php?n=Main.HomePage **but**
|
||
- Don't use `libavformat-dev` -> Compile error in Opal
|
||
- Configure script needs `pkg-config` to be installed to find ptlib install
|
||
- On SourceForge downloads `.tar.bz2` files for *nix
|
||
|
||
#### Build PTLib
|
||
|
||
- Version 2.18.6
|
||
- Dependency of Opal, bundled with Opal source code (SourceForge)
|
||
- http://wiki.opalvoip.org/index.php?n=Main.BuildingPTLibUnix
|
||
- **TODO: Remove dependencies, most of them are optional**
|
||
|
||
```bash
|
||
sudo apt install \
|
||
g++ git make autoconf libpcap-dev libexpat1-dev libssl-dev libsasl2-dev libldap2-dev \
|
||
unixodbc-dev liblua5.3-dev libv8-dev libncurses-dev libsdl2-dev \
|
||
libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev pkg-config
|
||
```
|
||
|
||
- PTLib will be installed in the `/usr/local` tree -> set `PKG_CONFIG_PATH` to be findable (compile time)
|
||
- Set `LD_LIBRARY_PATH` to find PTLib at compile and run time
|
||
- Set `PTLIBPLUGINDIR` (compile and run time)
|
||
- (To compile as static library: `./configure --disable-shared`)
|
||
|
||
```bash
|
||
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig # compile time
|
||
export LD_LIBRARY_PATH=/usr/local/lib # compile and run time
|
||
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-x.y.z # compile and run time
|
||
|
||
cd ptlib-x.y.z/
|
||
./configure
|
||
make
|
||
sudo make install
|
||
```
|
||
|
||
#### Build Opal
|
||
|
||
- Version 3.18.6
|
||
- http://wiki.opalvoip.org/index.php?n=Main.BuildingOpalUnix
|
||
- Dont use `libavcodec-dev` -> Compile error
|
||
- **TODO: Remove dependencies, most of them are optional**
|
||
|
||
```bash
|
||
sudo apt install \
|
||
libsrtp2-dev libgsm1-dev libspeex-dev libopus-dev libx264-dev \
|
||
libvpx-dev libtheora-dev libspandsp-dev dahdi
|
||
```
|
||
|
||
- (To compile as static library: `./configure --disable-shared`)
|
||
|
||
```bash
|
||
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig # compile time
|
||
export LD_LIBRARY_PATH=/usr/local/lib # compile and run time
|
||
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-x.y.z:/usr/local/lib/opal-a.b.c # compile and run time
|
||
|
||
cd opal-a.b.c/
|
||
./configure
|
||
make
|
||
sudo make install
|
||
```
|
||
|
||
#### t38modem
|
||
|
||
- https://github.com/hehol/t38modem, Version 4.6.2
|
||
- https://github.com/T38Modem/t38modem could also be used, but seems to be not as maintained
|
||
- If you are getting error about `-1` not being able to be casted to a `long unsigned int` due to `-Wnarrowing` inside `dle.cxx`, you can add `-Wno-narrowing` after the `CPPFLAGS` in the Makefile to disable this error
|
||
|
||
```bash
|
||
cd t38modem-x.y.z/
|
||
make
|
||
sudo cp ./t38modem /usr/local/bin
|
||
```
|
||
|
||
- t38modem can only find Opal if `LD_LIBRARY_PATH` and `PTLIBPLUGINDIR` are environment variables to the program
|
||
|
||
<hr/>
|
||
|
||
## Configuring t38modem
|
||
### Init script
|
||
|
||
- To automatically start t38modem, you need to create Systemd services, as well as start and stop scripts
|
||
- script is adapted from https://web.archive.org/web/20111231021042/https://www.foriamroot.org/hylafax-6-0-debian-or-ubuntu-t38modem-1-0-asterisk-1-6/
|
||
|
||
First we'll create the configuration directory under `/etc` using `sudo mkdir -p /etc/t38modem/bin/`.
|
||
|
||
Then create a file named `/etc/t38modem/bin/run` using the following content.
|
||
It will be the script to manage the current status of t38modem.
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# /etc/t38modem/bin/run
|
||
|
||
export LD_LIBRARY_PATH=/usr/local/lib
|
||
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-x.y.z:/usr/local/lib/opal-a.b.c # Adjust lib versions!
|
||
|
||
case "$1" in
|
||
start)
|
||
. /etc/t38modem/config
|
||
# defines
|
||
# - T38MODEM_SIP_USERNAME
|
||
# - T38MODEM_SIP_PASSWORD
|
||
# - T38MODEM_SIP_SERVER
|
||
|
||
COMMAND="t38modem -u T38modem --ptty +/dev/ttyT38-1 --sip-proxy ${T38MODEM_SIP_USERNAME}:${T38MODEM_SIP_PASSWORD}@${T38MODEM_SIP_SERVER} --sip-register ${T38MODEM_SIP_USERNAME}@${T38MODEM_SIP_SERVER},${T38MODEM_SIP_PASSWORD} --sip-listen udp\$:5060 --route t38:.*=sip:<dn>@${T38MODEM_SIP_SERVER} --route sip:.*=t38:<dn>"
|
||
echo "${COMMAND}"
|
||
exec $COMMAND > /dev/null 2>&1 &
|
||
PID=$!
|
||
echo "Starting t38modem with pid $PID (pidfile /run/t38modem.pid)"
|
||
echo $PID > /run/t38modem.pid
|
||
;;
|
||
stop)
|
||
if [ ! -f "/run/t38modem.pid" ]; then
|
||
echo "t38modem is not running! (/run/t38modem.pid does not exist)"
|
||
exit 1
|
||
fi
|
||
|
||
echo -n "Stopping t38modem pid: "
|
||
PID=`cat /run/t38modem.pid`
|
||
kill -9 $PID
|
||
rm /run/t38modem.pid
|
||
echo "${PID} Done"
|
||
;;
|
||
*)
|
||
echo "Usage: $0 {start|stop}"
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
exit 0
|
||
```
|
||
|
||
And then we'll have to make it executable like this.
|
||
|
||
```bash
|
||
sudo chmod +x /etc/t38modem/bin/run
|
||
```
|
||
|
||
#### Quick script overview
|
||
- Using that script, it is possible to `start` or `stop` the emulated modem.
|
||
- `-t` enables debugging
|
||
- More `t`'s is deeper debugging (e.g. `-tttt`)
|
||
- You can of course run the t38modem command without this init script
|
||
- If t38modem says it was able to create the virtual modem but `/dev/ttyT38-1` is not available, you do not have sufficient permissions
|
||
- Configuration is specified in `/etc/t38modem/config`
|
||
|
||
### Create the configuration file
|
||
Create a file using the following contents at `/etc/t38modem/config`.
|
||
|
||
```bash
|
||
# /etc/t38modem/config
|
||
T38MODEM_SIP_USERNAME="USERNAME"
|
||
T38MODEM_SIP_PASSWORD="PASSWORD"
|
||
T38MODEM_SIP_SERVER="voip.example.com"
|
||
```
|
||
|
||
You should give only root access to the config.
|
||
|
||
```bash
|
||
sudo chown root:root /etc/t38modem/config
|
||
sudo chmod 700 /etc/t38modem/config
|
||
```
|
||
|
||
### Testing your setup
|
||
- You can now communicate with your modem `/dev/ttyT38-1`, just as if it was a real Hayes compatible modem (https://www.computerhope.com/atcom.htm)
|
||
- Test using minicom, configure it to point to our modem. Each command is initiated by a Return
|
||
- Dial a number:
|
||
- Get the attention of the modem: `at` -> `OK`
|
||
- Dial: `atd[NUMBER]`, replace '[NUMBER]' using the number, you want to call
|
||
- If all works correctly you should be able to answer the phone and hear a single beep
|
||
- Answer a call:
|
||
- Get the attention of the modem: `at` -> `OK`
|
||
- *Call the number of your modem*
|
||
- -> `RING`
|
||
- Answer the call: `ata` -> `CONNECT`
|
||
- You should now hear your modem "talking" to you
|
||
- Pitfalls:
|
||
- If you are already connected to your SIP server it may not give proper response codes. My provider returns `500 Internal Server Error`
|
||
- Test the command before running the init script!
|
||
- Do not try to used `ATO` to switch to a data connection, t38modem will return `ERROR`.
|
||
Thats hardcoded in `pmodeme.cxx` in `void ModemEngineBody::HandleCmdRest(PString &resp)`.
|
||
Dont let that hodld you back.
|
||
|
||
### systemd service
|
||
If you want to run a fax server, you can create a systemd service to let your emulated fax modem start automatically on system boot.
|
||
To do this you have to copy paste the following into `/etc/systemd/system/t38modem.service`.
|
||
|
||
```toml
|
||
# /etc/systemd/system/t38modem.service
|
||
[Unit]
|
||
Description=t38modem
|
||
After=network-online.target
|
||
Wants=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
ExecStart=/etc/t38modem/bin/run start
|
||
ExecStop=/etc/t38modem/bin/run stop
|
||
PIDFile=/run/t38modem.pid
|
||
KillMode=none
|
||
Restart=always
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
Enable and start the service using the following commands:
|
||
|
||
```bash
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable t38modem.service
|
||
sudo systemctl start t38modem.service
|
||
```
|
||
|
||
<hr/>
|
||
|
||
## Install HylaFax
|
||
|
||
- Version 6
|
||
- `sudo apt install hylafax-server`
|
||
|
||
- Set Postfix Configuration to **Local only** in dpkg-reconfigure menu
|
||
- Run `sudo faxsetup`
|
||
|
||
- Add new modem
|
||
- Enter correct modem port (`ttyT38-1`)
|
||
- Enter dialing configuration
|
||
- Accept default configuration for everything else
|
||
- It should automatically detect it to be a `T38FAX` modem
|
||
- Look at `man sendfax` to send faxes
|
||
- `fgetty` (the service to receive faxes) should be enabled automatically
|
||
- Bugs:
|
||
|
||
- If you get some protocol errors, just let HylaFax do its thing.
|
||
Fax over SIP is not stable at all in my experience
|
||
|
||
|
||
## Cron
|
||
|
||
- Alias your fax admin account as `FaxMaster` (`/etc/aliases`)
|
||
|
||
```bash
|
||
# /etc/aliases
|
||
# [...]
|
||
# HylaFax
|
||
FaxMaster: $USER # replace with fax admin account
|
||
```
|
||
|
||
- Add standard tasks to crontab file: `crontab -e`
|
||
|
||
```bash
|
||
0 * * * * /usr/sbin/faxqclean
|
||
25 23 * * * sh /usr/sbin/faxcron | mail FaxMaster
|
||
```
|
||
|
||
## FaxDispatch
|
||
|
||
- https://legacy.hylafax.org/content/Advanced_Permissions_with_6.0
|
||
|
||
## Dial Rules for Eventphone
|
||
|
||
```
|
||
CountryCode: 1
|
||
AreaCode: 999
|
||
```
|
||
|
||
## TODO
|
||
- **TODO: Test on Debian / RockPi / RaspberryPi**
|
||
- **TODO: Test on Eventphone Infra**
|
||
- **TODO: Package t38modem with service files and config**
|