linux-fax-stack/README.md
2024-08-16 12:15:10 +02:00

348 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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).
Please do not follow this guide blindly.
Some used Opal versions are marked as being infected with malware by SourceForge.
**We are strongly discouraging, that you are using these versions.**
## Software stack
### 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 connection
### 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/
- t38modem (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 cast 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
- 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-2.18.6:/usr/local/lib/opal-3.18.6 # Adjust lib versions!
if [ -z "${1}" ]; then
>&2 echo "Config file path not set! Aborting..."
exit 1
fi
. "${1}"
command="t38modem --ptty +/dev/ttyT38-${T38MODEM_PTTY_ID} --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 --stun ${T38MODEM_STUN_SERVER} --route t38:.*=sip:<dn>@${T38MODEM_SIP_SERVER} --route sip:.*=t38:<dn>"
if [ "$T38MODEM_DISABLE_T38" = true ]; then
command="${command} --disable-t38-mode --audio"
fi
exec $command
```
And then we'll have to make it executable like this.
```bash
sudo chmod +x /etc/t38modem/bin/run
```
#### Quick script overview
- Using this script, it is possible to start t38modem with a config file as an argument
- `-t` enables debugging
- More `t`'s is deeper debugging (e.g. `-tttt`)
- 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/XX`
### Create the configuration file
Create a file using the following contents at `/etc/t38modem/config/XX`.
Replace `XX` with the modem number.
```bash
T38MODEM_PTTY_ID="XX" # /dev/ttyT38-XX
T38MODEM_SIP_USERNAME="USERNAME"
T38MODEM_SIP_PASSWORD="PASSWORD"
T38MODEM_SIP_SERVER="voip.example.com"
T38MODEM_STUN_SERVER="stun.example.com:1234"
T38MODEM_DISABLE_T38=false # enable if your SIP server prefers G.711
```
You should give only root access to the config.
```bash
sudo chown root:root -R /etc/t38modem/config/
sudo chmod 700 -R /etc/t38modem/config/
```
### Testing your setup
- You can now communicate with your modem `/dev/ttyT38-XX`, 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 template 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
AssertPathExists=/etc/t38modem/config/%i
[Service]
Type=simple
Restart=always
ExecStart=/etc/t38modem/bin/run /etc/t38modem/config/%i
[Install]
WantedBy=multi-user.target
```
Enable and start the service for your config file (`/etc/t38modem/config/XX`) using the following commands:
```bash
sudo systemctl daemon-reload
sudo systemctl enable t38modem@XX.service
sudo systemctl start t38modem@XX.service
```
<hr/>
## Install HylaFax
These instructions were tested using Hylafax version 6
- `sudo apt install hylafax-server`
- Set Postfix Configuration to **Local only** in dpkg-reconfigure menu
## Configure HylaFax
- Run `sudo faxsetup`
- Add new modem
- Enter correct modem port (`ttyT38-XX`)
- Enter dialing configuration (see Dial Rules for Eventphone EPVPN)
- 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
- If your call is cleared because it `Could not find common media capabilities` t38modem may not have been able to load PTLib or Opal. Check your library paths!
### 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
```
### Dial Rules for Eventphone EPVPN
If you want to use Eventhone EPVPN, you can apply the following dial settings onto your modems.
You can find the config at `/etc/hylafax/config.ttyT38-1`.
In this case `ttyT38-1` is the modem block device.
```
# /etc/hylafax/config.ttyXX
CountryCode: 1
AreaCode: 999
```
## Apply configuration
If HylaFax doesn't receive or send faxes, you can try restarting it.
This can be done using
```bash
sudo /etc/init.d/hylafax stop
sudo /etc/init.d/hylafax start
```
## FaxDispatch
- https://legacy.hylafax.org/content/Advanced_Permissions_with_6.0
# TODO
- **TODO: Test on Debian / RockPi / RaspberryPi**
- **TODO: Test on Eventphone Infra**
- **TODO: Package t38modem with service files and config**