Neuereatec GSM Gateway
Download

Android · one call per SIM · version 1.2.2 · built-in Headscale tunnel

Cellular calls, straight into the phone system.

Put a SIM in a spare Android phone and leave it on the charger. When someone calls that number, the app answers. It then calls an extension on the office PBX and joins the two calls, so the call can be routed like any other.

New in 1.2.2: fixes the app freezing and being closed by Android ("not responding") when the tunnel stops or reconnects, and adds a tunnel health check: if the office server stops answering through the tunnel, the app shows "Stalled" and rebuilds the tunnel by itself instead of showing a stale "Online".

New in 1.2.0: optional OTP SMS sender for office login codes (separate from call handling). Set it up by scanning the “OTP SMS sender” QR on the office QR page, then allow SMS. The status card shows SMS sent/failed.

Download gsm-gateway.apk Get setup QR code Magisk priv-app module 2.1 MB · Android 8.0+ · release build · SHA-256 fd8f8f40…1b752b9d

Overview

CPBX is an Asterisk phone system that runs in Docker on the office PC (PC01). It has three containers: cpbx-asterisk (the PBX), cpbx-admin (the web admin) and cpbx-coturn (TURN relay for browser calls).

 Office phones (LAN) ----+
                         |   192.168.1.106:5060
 SIPDesk / GSM Gateway --+--> PC01: Docker
   (Headscale tailnet)   |     cpbx-asterisk (PBX)
   100.64.0.1:5060       |     cpbx-admin  :3000
                         |     cpbx-coturn :3478
 JavisLink (browser) ----+
   wss://sip.neuereatec.org/ws

 Caller -> SIM in gateway phone -> ext 150 -> ext 105

Extensions

Extensions 101, 102 and 103 are also set up in the PBX config.

How to use them

Softphone downloads and links

Assigning an extension to each softphone

Adding an extension and its QR

  1. On PC01, open CPBX Admin at http://localhost:3000. From another office computer, use http://192.168.1.106:3000.
  2. Create the extension and save it.
  3. Open the setup QR page (office LAN only) and enter the PIN 418043. The new extension's QR shows up within about 30 seconds.
  4. Scan it in SIPDesk (Settings → Scan QR code) or in the GSM Gateway app (Scan QR). For JavisLink, scan the second JavisLink QR with the phone camera.
  5. Tap New key on the QR page if you need a fresh code.

To make a new extension work outside the office, add its number to CPBX_TAILNET_EXTS in docker-compose.yml. Then run docker compose up -d and save any one extension in admin.

Remote use via Headscale

When the network changes

Use this when PC01's office IP changes, for example after a new router, a new DHCP lease or an office move.

  1. On PC01, open Command Prompt and run ipconfig. Note the IPv4 address.
  2. Double-click Change-PBX-IP.bat on the Desktop. You do not need Run as administrator.
  3. Type the new IP and press Enter. The script checks the IP is valid and backs up docker-compose.yml. It changes only CPBX_ADVERTISE_IP and restarts with docker compose up -d. Then it shows SUCCESS or the error.
  4. After SUCCESS, open CPBX Admin and save any one extension.
  5. Dial 600 to test.

The script has not been run for real yet. The Headscale settings are not touched.

PBX troubleshooting

Staff quick guide

Setup QR codes

Get setup QR code

The QR page only opens on the office network, and it asks for the office PIN (ask the administrator). Use the GSM gateway · 150 code: it holds the SIP login, a fresh Headscale key and the server. Nothing secret is published on this page.

Before you install: rooted phones and normal phones sound different

On a normal phone, Android does not let an app read or feed the audio of a cellular call. So the app turns on the speakerphone. The phone's microphone hears the caller and the loudspeaker plays the extension. It works, but there is echo and room noise. Keep the phone somewhere quiet. The status screen shows Speakerphone (lower quality).

On a rooted phone (Magisk), install the module as well. Android then treats the app as a system app and lets it use call audio directly. On Android 13 and newer, audio is clean in both directions. On older Android, the caller's side is clean, but the extension's side still goes out by speakerphone. The status screen shows the mode in use.

How the bridge works

Callermobile or landline
→
Gateway phoneSIM · auto-answer
⇄
CPBXSIP · 100.64.0.1:5060
→
Ring list100 → 105 → …
  1. The app stays registered to the PBX as an ordinary SIP extension. It runs as a foreground service and starts again after a reboot.
  2. A cellular call rings. If SIP is registered, the app answers it after a short delay (1.5 s by default).
  3. The app sends a SIP INVITE to the first extension in the ring list (or to the PBX route gsmgw), then the next one on no answer. It puts the caller's number in the display name, in P-Asserted-Identity and in X-GSM-Caller.
  4. Audio runs both ways as G.711 (PCMU/PCMA). If the PBX sends keypad presses (RFC 2833), the app plays them as tones to the caller. Keys the caller presses reach the PBX as in-band tones.
  5. When either side hangs up, the other call ends too.

Gateway setup, step by step

  1. Install the APK. Download gsm-gateway.apk on the gateway phone (the one with the SIM), open it, and allow installing from this source if Android asks.
  2. No Tailscale app needed. Version 1.1 has the Headscale (WireGuard) client built in. The QR carries the join key; the app brings the tunnel up first, then registers SIP over it. Android asks once to allow the VPN: tap OK. If the Tailscale app is installed, turn it off (only one VPN can run).
  3. Scan the gateway QR. Open the setup QR page on an office screen, enter the PIN, find GSM Gateway — 150. In the app tap Scan QR. SIPDesk softphone codes are refused on purpose.
  4. Choose who rings. The app asks Which extension should incoming cellular calls ring? Type the main extension, e.g. 100, and add more separated by commas (100, 105): the PBX rings them in that order, 20 s each, skips anyone busy or offline, then goes to the first one's voicemail. Numbers are used exactly as typed. Leave it blank for the PBX default (100). Change it later under Bridge → Change ring order.
  5. Permissions. Tap Permissions and allow the microphone, phone, call logs, answering calls and notifications. Tap Battery and choose Unrestricted (battery optimisation off). Default phone app: version 1.0 can't take the default phone app role and doesn't need it, because it answers calls with the “Answer phone calls” permission. Keep your normal dialer as the default.
  6. Check the status. The top panel should read Tunnel: Online with a 100.64.x.x tailnet IP, SIP: Registered and Gateway: Idle.
  7. Test. Call the SIM from another mobile. The gateway answers in about 2 s and the first extension in your list rings with the mobile's number. Answer it and talk both ways. Press keys on the desk phone and listen for the tones on the mobile. Hang up on the mobile and check the desk phone drops. Call again, hang up on the desk phone, and check the mobile drops.
  8. Rooted phone only: add the Magisk priv-app module for cleaner audio.

Gateway troubleshooting

Level bar stays at 0 during a callThe phone is blocking call audio. Tick Force speakerphone mode, tap Save & restart, and call again.
Not registeredLook at Tunnel first. Key used up / NeedsLogin = the key was spent or expired: make a New key for 150 on the QR page and scan again. Stopped = VPN permission missing or another VPN app is on. Once the tunnel is Online, SIP registers by itself.
Phone rings but is not answeredSIP must be Registered (the app won't answer otherwise), and “Answer phone calls” must be allowed.
Stops working after a while or after a rebootSet Battery to Unrestricted. The tunnel and gateway restart after a reboot by themselves; if the status shows VPN permission missing, open the app once.

What to configure

HeadscaleURL and key come from the QR. Blank URL = no tunnel (LAN use).
SIP server100.64.0.1 over the built-in tunnel, or a LAN address such as 192.168.x.x.
Port5060 (UDP)
ExtensionThe gateway's own SIP extension (from the administrator)
PasswordThat extension's SIP password
Ring orderExtensions in order, e.g. 100, 105. Sent to the PBX on every call; the PBX hunts (20 s each, skips busy/offline, then voicemail). Blank = PBX default 100.
Answer afterDelay before answering, in milliseconds (1500)
Audio modeChosen automatically: Rooted: call audio interception, Rooted: VOICE_CALL capture or Speakerphone (lower quality). Tick “Force speakerphone mode” to override.

Setup link format: gsmgw://setup?server=&port=&ext=&pw=&hs=&hskey=&target=&ring=&route=. The real code with the password and key is only on the office QR page.

Rooted phone: Magisk priv-app

  1. Install and set up the APK first (above).
  2. In Magisk, open Modules → Install from storage and pick gsm-gateway-magisk.zip. Reboot the phone.
  3. The module copies the app to /system/priv-app/NeuereatecGsmGateway/. It also adds a permission allow-list for CAPTURE_AUDIO_OUTPUT, CALL_AUDIO_INTERCEPTION and MODIFY_PHONE_STATE.
  4. Open the app. The audio mode should start with Rooted:. If it still says Speakerphone, check the result with adb shell dumpsys package org.neuereatec.gsmgateway | grep -E "CAPTURE_AUDIO|INTERCEPTION". Both should show granted=true.
  5. To update later, install the new APK normally. It stays privileged because it is signed with the same key. To undo, remove the module in Magisk and reboot.

Some phone makers lock call audio in their own audio code. On those phones, even root gives silence. If the capture level stays at 0 during a call, tick “Force speakerphone mode”.

SIPDesk: a desk phone on the same PBX

SIPDesk is our Android desk-phone app. It uses the same QR page.

  1. Download SIPDesk from bbscalton.github.io/sipdesk-android and install it.
  2. Connect it to Headscale (https://hs.neuereatec.org) with the auth key from the office.
  3. Open SIPDesk Settings → Scan QR code and scan that user's extension QR from the setup QR page (office PIN from the administrator). Then tap Save & Connect.
  4. Test: dial 600 (echo test) and check you hear yourself. Then call 104, the JavisLink softphone, and talk both ways.

Open the SIPDesk download page