Preorder drugiego tomu książki sekuraka: Wprowadzenie do bezpieczeństwa IT. -15% z kodem: sekurak-book
Jak skonfigurować automatyczną wysyłkę / odbiór SMS-ów pod Linuksem?
Wstęp
Na jedno z moich szkoleń z bezpieczeństwa przygotowałem swego czasu ćwiczenie, polegające na wykorzystaniu pewnych błędów aplikacyjnych używając w tym celu realnych SMS-ów (to znaczy uczestnicy aby rozwiązać ćwiczenie muszą użyć swoich komórek – również tych szarych ;-). Jak jednak zorganizować niewielkim kosztem w LAB infrastrukturę umożliwiającą na żywo wysyłkę / odbiór SMS-ów, a także ich przetwarzanie i odpowiednie reagowanie jeśli zajdzie określona sytuacja?
Pierwsze co mi przyszło do głowy, to darmowe rozwiązanie gammu. Jakie ma możliwości to oprogramowanie? Sami twórcy opisują je tak:
Gammu command line utility provides access to wide range of phone features, however support level differs from phone to phone (…) Generally following features are supported:
- Call listing, initiating and handling
- SMS retrieval, backup and sending
- MMS retrieval
- Phonebook listing, export and import (also from standard formats such as vCard)
- Calendar and tasks listing, export and import (also from standard formats such as vCalendar or iCalendar)
- Retrieval of phone and network information
- Access to phone file system (note that some phones work also as USB storage devices and those are not accessible through Gammu)
Opcja dotycząca SMS-ów wydaje się być idealna pod nasze potrzeby. Co więcej w ramach gammu dostępny jest monitor komunikacji SMS o nazwie smsd:
Gammu SMS Daemon is a program that periodically scans GSM modem for received messages, stores them in defined storage and also sends messages enqueued in this storage. It is perfect tool for managing big amounts of received or sent messages and automatically process them.
Wskazanym w powyższym cytacie 'storage’ może być bazą danych (np. MySQL). Finalnie, kiedy więc przyjdzie na nasz numer wiadomość SMS, smsd automatycznie wpisuje odpowiedni rekord do bazy (zawierający dane SMS-a). Z kolei gdy chcemy SMS-a wysłać, po prostu robimy jednego INSERT-a do konkretnej tabeli – reszta dzieje się automatycznie. Proste? Wydaje się że tak :-) Architektura rozwiązania wygląda tak:
Zabieramy się do pracy
Akurat pod ręką miałem stary telefon Nokia 6300, który jest na liście wspieranego przez gammu sprzętu. Wyposażyłem go w prepaidową kartę SIM za 5 zł, dającą własny numer oraz możliwość wysłania w tej kwocie dość dużej liczby SMS-ów.
Po podłączeniu telefonu kablem USB do komputera zacząłem testy. Tu niestety napotkałem na pewne problemy. O ile działało wysyłanie SMS-ów z konsoli:
securitum-t1:~# echo "testowy sms" |gammu sendsms TEXT 123123123 If you want break, press Ctrl+C... Sending SMS 1/1....waiting for network answer..OK, message reference=107
…to z odbieraniem nie było już tak różowo. Ściągnąłem więc wersję deweloperską gammu, po skompilowaniu której… pomogło :-) W tym momencie byłem w stanie zarówno wysyłać jak i odbierać SMS-y. Wystarczyło tylko uruchomić oraz skonfigurować smsd.
Tutaj niestety pojawiły się kolejne schody (oszczędzę na razie szczegółów konfiguracyjnych) – smsd był w stanie tylko wysyłać SMS-y (bez możliwości odbioru). W końcu, po spędzeniu dłuższego czasu na listach dyskusyjnych gammu, stwierdziłem że prawdopodobnie jest to bug w obsłudze telefonu Nokia 6300 i prościej niż patchować smsd będzie poszukać innego sprzętu.
Stanęło tym razem na popularnym modemie Huavei E173, który akurat miałem pod ręką (jest dość popularnym urządzeniem w ofercie jednego z operatorów GSM). Sprzęt miał już z 2 lata więc miałem nadzieję, że jeszcze działa :-)
W systemie modem został wykryty:
root@securitum-t1:~# lsusb Bus 003 Device 003: ID 12d1:1446 Huawei Technologies Co., Ltd. E1552 (HSPA modem ) Bus 003 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 002 Device 004: ID 8087:07da Intel Corp. Bus 002 Device 003: ID 1bcf:288e Sunplus Innovation Technology Inc. Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Jak wydać powyżej parametry modemu to 12d1:1446 (tj. productID = 12d1, vendorID = 1446). Szczegóły wyglądają tak:
securitum-t1:~# lsusb -v -d 12d1:1446 Bus 003 Device 003: ID 12d1:1446 Huawei Technologies Co., Ltd. E1552 (HSPA modem) Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x12d1 Huawei Technologies Co., Ltd. idProduct 0x1446 E1552 (HSPA modem) bcdDevice 0.00 iManufacturer 3 HUAWEI Technology iProduct 2 HUAWEI Mobile iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 55 bNumInterfaces 2 bConfigurationValue 1 iConfiguration 1 Huawei Configuration bmAttributes 0xe0 Self Powered Remote Wakeup MaxPower 500mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 8 Mass Storage bInterfaceSubClass 6 SCSI bInterfaceProtocol 80 Bulk (Zip) iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x01 EP 1 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 8 Mass Storage bInterfaceSubClass 6 SCSI bInterfaceProtocol 80 Bulk (Zip) iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Device Qualifier (for other device speed): bLength 10 bDescriptorType 6 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 bNumConfigurations 1 Device Status: 0x0001 Self Powered
Problem w tym, że nie byłem go w żaden sposób zmusić do współpracy z gammu. Okazuje się, że domyślnie urządzenie to działa pod Linuksem w trybie storage USB – czyli jako pendrive, a nie jako potrzebny mi modem. Szybkie googlanie pokazało rozwiązanie problemu. Użyjmy więc polecanego wyżej narzędzia usb_modeswitch:
securitum-t1:~# apt-get install usb-modeswitch -y Reading package lists... Done Building dependency tree Reading state information... Done The following package was automatically installed and is no longer required: libgammu-i18n Use 'apt-get autoremove' to remove them. The following extra packages will be installed: usb-modeswitch-data Suggested packages: comgt wvdial The following NEW packages will be installed: usb-modeswitch usb-modeswitch-data 0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. Need to get 0 B/69.1 kB of archives. After this operation, 889 kB of additional disk space will be used. Selecting previously deselected package usb-modeswitch-data. (Reading database ... 50191 files and directories currently installed.) Unpacking usb-modeswitch-data (from .../usb-modeswitch-data_20100826-1+squeeze0_all.deb) ... Selecting previously deselected package usb-modeswitch. Unpacking usb-modeswitch (from .../usb-modeswitch_1.1.4-2_i386.deb) ... Processing triggers for man-db ... Setting up usb-modeswitch-data (20100826-1+squeeze0) ... Setting up usb-modeswitch (1.1.4-2) ...
I wykorzystajmy taki plik konfiguracyjny:
securitum-t1:~# cat usb_modeswitch.conf DisableSwitching=0 # Enable logging (results in a extensive report file in /var/log, named # "usb_modeswitch_<interface-name>" EnableLogging=0 DefaultVendor= 0x12d1 DefaultProduct= 0x1446 TargetVendor= 0x12d1 TargetProduct= 0x140c MessageContent="55534243000000000000000000000011060000000000000000000000000000" CheckSuccess=5
Pozostaje tylko wypróbować ustawienia:
securitum-t1:~# usb_modeswitch -c usb_modeswitch.conf Looking for target devices ... No devices in target mode or class found Looking for default devices ... Found devices in default mode or class (1) Accessing device 003 on bus 003 ... Using endpoints 0x01 (out) and 0x81 (in) Using endpoints 0x01 (out) and 0x81 (in) Inquiring device details; driver will be detached ... Looking for active driver ... OK, driver found ("usb-storage") OK, driver "usb-storage" detached SCSI inquiry data (for identification) ------------------------- Vendor String: HUAWEI Model String: Mass Storage Revision String: 2.31 ------------------------- USB description data (for identification) ------------------------- Manufacturer: HUAWEI Technology Product: HUAWEI Mobile Serial No.: not provided ------------------------- Setting up communication with interface 0 ... Using endpoint 0x01 for message sending ... Trying to send message 1 to endpoint 0x01 ... OK, message successfully sent Resetting response endpoint 0x81 Error resetting endpoint: -71 Resetting message endpoint 0x01 Error resetting endpoint: -71 Checking for mode switch (max. 5 times, once per second) ... Waiting for original device to vanish ... Original device can't be accessed anymore. Good. Searching for target devices ... Searching for target devices ... Searching for target devices ... Searching for target devices ... Searching for target devices ... Found correct target device Mode switch succeeded. Bye.
Ostatnia linijka wygląda zachęcająco, zobaczmy czy posiadamy już wirtualne urządzenie, przez które moglibyśmy się odwołać do modemu:
securitum-t1:~# dmesg |grep ttyUSB [ 203.442061] usb 3-1.1: GSM modem (1-port) converter now attached to ttyUSB0 [ 203.442436] usb 3-1.1: GSM modem (1-port) converter now attached to ttyUSB1 [ 203.442570] usb 3-1.1: GSM modem (1-port) converter now attached to ttyUSB2 [ 203.442640] usb 3-1.1: GSM modem (1-port) converter now attached to ttyUSB3
Spróbujemy więc przygotować odpowiednio .gammurc:
securitum-t1:~# cat .gammurc [gammu] port = /dev/ttyUSB3 model = E173 connection = at115200 synchronizetime = yes logfile = logformat = nothing use_locking = gammuloc =
Z tymi ustawieniami wysyłka SMSów…działa! :-)
securitum-t1:~# echo "testowy sms" |gammu sendsms TEXT 123123123 If you want break, press Ctrl+C... Sending SMS 1/1....waiting for network answer..OK, message reference=107
Teraz pozostaje nam konfiguracja i przetestowanie smsd. Do zbudowania bazy MySQL użyłem schematu dostępnego tutaj: gammu-1.32.0/docs/sql/mysql.sql
securitum-t1:~# mysql -u gammu -p gammu < ./gammu-1.32.0/docs/sql/mysql.sql
Z kolei moja konfiguracja smsd wygląda tak:
securitum-t1:~# cat /etc/gammu-smsdrc # Configuration file for Gammu SMS Daemon # Gammu library configuration, see gammurc(5) [gammu] # Please configure this! port = /dev/ttyUSB2 model = E173 connection = at115200 # Debugging logformat = textall # SMSD configuration, see gammu-smsdrc(5) [smsd] CommTimeout = 5 ReceiveFrequency = 5 service = sql driver = native_mysql user = gammu password = tutaj_haselko_do_db pc = localhost database = gammu logformat = textall logfile = /tmp/test.log deliveryreport = log # Increase for debugging information debuglevel = 3
Po starcie smsd, jego logi wyglądają zachęcająco:
securitum-t1:~# cat /tmp/test.log Sat 2013/06/22 15:07:13 gammu-smsd[4712]: Connected to Database: gammu on localhost Sat 2013/06/22 15:07:13 gammu-smsd[4712]: Execute SQL: SELECT `ID` FROM outbox LIMIT 1 Sat 2013/06/22 15:07:13 gammu-smsd[4712]: Execute SQL: SELECT `ID` FROM outbox_multipart LIMIT 1 Sat 2013/06/22 15:07:13 gammu-smsd[4712]: Execute SQL: SELECT `ID` FROM sentitems LIMIT 1 Sat 2013/06/22 15:07:13 gammu-smsd[4712]: Execute SQL: SELECT `ID` FROM inbox LIMIT 1 Sat 2013/06/22 15:07:13 gammu-smsd[4712]: Execute SQL: SELECT `Version` FROM gammu Sat 2013/06/22 15:07:13 gammu-smsd[4712]: Database structures version: 13, SMSD current version: 13 Sat 2013/06/22 15:07:13 gammu-smsd[4712]: Connected to Database native_mysql: gammu on localhost Sat 2013/06/22 15:07:13 gammu-smsd[4712]: Created POSIX RW shared memory at 0xb76fb000 Sat 2013/06/22 15:07:13 gammu-smsd[4712]: Starting phone communication...
Czas teraz na finalne testy:
securitum-t1:~# mysql -u gammu -p gammu Enter password: mysql> show tables; +------------------+ | Tables_in_gammu | +------------------+ | answers | | blacklist | | daemons | | gammu | | inbox | | outbox | | outbox_multipart | | pbk | | pbk_groups | | phones | | reset_pass | | sentitems | | users | +------------------+ 13 rows in set (0.00 sec) mysql> desc outbox; +-------------------+------------------------------------------------------------------------------------------------------------+------+-----+------------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +-------------------+------------------------------------------------------------------------------------------------------------+------+-----+------------------------+-----------------------------+ | UpdatedInDB | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | | InsertIntoDB | timestamp | NO | | 0000-00-00 00:00:00 | | | SendingDateTime | timestamp | NO | MUL | 0000-00-00 00:00:00 | | | SendBefore | time | NO | | 23:59:59 | | | SendAfter | time | NO | | 00:00:00 | | | Text | text | YES | | NULL | | | DestinationNumber | varchar(20) | NO | | | | | Coding | enum('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression') | NO | | Default_No_Compression | | | UDH | text | YES | | NULL | | | Class | int(11) | YES | | -1 | | | TextDecoded | text | NO | | NULL | | | ID | int(10) unsigned | NO | PRI | NULL | auto_increment | | MultiPart | enum('false','true') | YES | | false | | | RelativeValidity | int(11) | YES | | -1 | | | SenderID | varchar(255) | YES | MUL | NULL | | | SendingTimeOut | timestamp | YES | | 0000-00-00 00:00:00 | | | DeliveryReport | enum('default','yes','no') | YES | | default | | | CreatorID | text | NO | | NULL | | +-------------------+------------------------------------------------------------------------------------------------------------+------+-----+------------------------+-----------------------------+
Pokazana wyżej tabela outbox jest skanowana cyklicznie przez smsd w poszukiwaniu nowych rekordów. Jeśli takowy zostanie znaleziony – SMS jest wysyłany. Jak więc wysłać SMS-a? Na przykład tak:
mysql> INSERT INTO outbox (DestinationNumber, TextDecoded) VALUES ('+48123123123','testowy smsik'); Query OK, 1 row affected, 1 warning (0.00 sec)
Tak można z kolei odczytać SMS-y, które ktoś do nas przysłał (poniżej SMS o treści „Aaa”):
mysql> select * from inbox; +---------------------+---------------------+--------------+--------------+------------------------+-----+--------------+-------+-------------+-----+-------------+-----------+ | UpdatedInDB | ReceivingDateTime | Text | SenderNumber | Coding | UDH | SMSCNumber | Class | TextDecoded | ID | RecipientID | Processed | +---------------------+---------------------+--------------+--------------+------------------------+-----+--------------+-------+-------------+-----+-------------+-----------+ | 2013-06-22 15:13:33 | 2013-06-22 13:13:16 | 004100610061 | +48123123123 | Default_No_Compression | | +48790123123 | -1 | Aaa | 102 | | false | +---------------------+---------------------+--------------+--------------+------------------------+-----+--------------+-------+-------------+-----+-------------+-----------+
Pozostało mi już tylko wykonać skrypty łączące się bazą i realizujące logikę, którą zaplanowałem do realizacji jednego z ćwiczeń :-)
Całość w działaniu wygląda całkiem niepozornie…:
PS
Zmianę trybu można zautomatyzować poprzez stworzenie pliku: /etc/usb_modeswitch.d/12d1:1446 o zawartości:
# Huawei, newer modems DefaultVendor= 0x12d1 DefaultProduct=0x1446 TargetVendor= 0x12d1 TargetProductList="1001,1406,140b,140c,1412,141b,14ac" CheckSuccess=20 MessageContent="55534243123456780000000000000011062000000100000000000000000000"
–michal.sajdak<at>securitum.pl
Ja do tego uzywam Asteriska z chan_dongle (http://wiki.e1550.mobi/) swietnie sie sprawdza.
@Adam – wygląda ciekawie, choć nie widzę czegoś jak smsd (+ połączenie jego z bazą)?
–ms
Przy niektórych modemach zamiast usb_modeswitch można (a nawet trzeba) użyć polecenia… eject z odpowiednimi parametrami.
Hej
Fajnie to zrobiłeś też używam gammu w swoim projekcie http://nettemp.pl
`gammu-smsd` najlepiej do kompletu pilnować przy pomocy `monit`, bo jeśli jednocześnie używamy `gammu-smsd`i np. okazyjnie `wvdial` do wdzwaniania się do netu, `gammu-smsd` lubi się wysypać z powodu braku dostępu do /dev/ttyUSB0.
Mam pytanie. Robię tak jak w poradniku czyli przełączam mój ZTE w tryb modemu. Wywala error, ale się urządzenie przełącza w tryb modemu (zaczyna świecić na niebiesko). Ale wyświetla się jako ttyACM0, ttyACM1 i ttyACM2. To normalne?
A i da się to jakoś zautomatyzować po restarcie komputera? Czasem muszę robić to jeszcze raz a gdy usługa ma działać cały czas bez ingerencji muszę to jakoś albo scalić na stałe albo monitorwać. Macie jakiś pomysł?