04 / Blog

A SIM Just for Verification Codes

More and more services force 2FA via SMS, and as a result it feels like every other provider ends up with my phone number. Since I’d rather not find that number in the next data breach and get buried in spam afterwards, I use a separate SIM just for these codes. For a number that only ever receives, though, I don’t want a second phone lying around permanently, and I’d rather keep my second SIM slot free for travel SIMs. So an old USB GSM modem attached to a small container does the job, and incoming SMS land straight in a Telegram chat.

How it works

The heart of it is gammu-smsd, a Linux daemon that talks to GSM modems via AT commands. It polls the modem, decodes incoming SMS, and can launch a program on every message received. That hook is the whole trick:

[smsd]
service = files
RunOnReceive = /opt/sms-telegram

gammu passes the message along through environment variables (SMS_1_NUMBER, SMS_1_TEXT, and for long messages DECODED_PARTS). sms-telegram is a Go binary that reads these variables, reassembles the parts, and sends them via the Telegram Bot API.

Which port is the modem?

A USB modem often shows up as several serial devices (ttyUSB0 through ttyUSB2), and which of them is the AT command port isn’t fixed. Instead of hard-wiring that, my entrypoint tries the candidates one by one with gammu --identify and takes the first one that responds. If the modem ever disappears, it simply searches again.

The container

The image is deliberately lean: a distroless base image with just the gammu binaries and their libraries plus my two Go helpers, with no package manager or other ballast. All of the code can be found in my GitLab.

Keeping the SIM alive

A prepaid SIM that only receives eventually gets deactivated by the provider for inactivity. A systemd timer that sends a keepalive SMS once a month takes care of that:

[Timer]
OnCalendar=*-*-01 10:00:00
Persistent=true

Persistent=true makes sure the message is sent later if the machine happened to be off on the first of the month.

Conclusion

Since then the whole thing runs unattended on my home server with the modem plugged in. Incoming SMS show up as a Telegram message within a few seconds, and the SIM stays active on its own. And hopefully no more annoying spam.