Security fixes, ready-to-deploy image, and rewritten docs

Audit fixes:

- Wallet names were used unvalidated as file paths, so a name like
  "../<other-id>/x" reached another user's wallet directory or overwrote
  bot_settings.json. Names are now validated and every path is resolved and
  confirmed to sit inside the caller's own directory, which also blocks a
  planted symlink from escaping.
- Tor mode leaked: the mempool.space fee check opened a direct clear-net
  connection, tying the server's IP to its Bitcoin activity. It now goes
  through Tor's SOCKS proxy to mempool's onion service, DNS included.
- The xpub message was left in the chat forever. It reveals the wallet's whole
  address and balance history, so it is now deleted like the password is.
- Inline buttons stay live on old messages, so a user removed from the
  allow-list could keep using them. Callbacks re-check authorisation, and
  auth_check now works for callback queries instead of raising on a null
  message.
- Wallet names echoed back in callback_data are confirmed against the user's
  real wallet list.
- Settings are written via temp file + atomic rename; a crash mid-write used
  to truncate the file and lose every user's wallet selection.
- Replies were sent against messages that had just been deleted; deletion is
  now best-effort and cannot abort the flow.

Deployment:

- Allow-list can come from ALLOWED_USERS instead of a bind-mounted file, so a
  deployment needs no files on disk. Both sources merge when both are present.
- A missing bind-mounted allowed_users.txt made Docker create a directory in
  its place and silently lock everyone out; the entrypoint now detects that
  and stops with an explanation.
- Standard mode honours ELECTRUM_SERVER, which previously only worked in Tor
  mode despite being documented.
- Added VERSION, push.sh, docker-compose.deploy.yml and .env.deploy.example
  for a two-file deploy off the published image.

Docs rewritten in English and Persian around the name Telegtrum, leading with
the security model and what it does not protect against.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
goyban
2026-09-01 16:34:26 +00:00
parent 468111a52a
commit b7a0a86be2
10 changed files with 615 additions and 438 deletions
+170 -187
View File
@@ -1,243 +1,226 @@
# ربات کیف‌پول آنلاین
# تله‌گتروم (Telegtrum)
یک ربات تلگرام خودمیزبان برای مدیریت کیف‌پول‌های بیت‌کوین با استفاده از Electrum. طراحی‌شده برای کیف‌پول‌های فقط-تماشا (xpub) با پشتیبانی از امضای آفلاین (air-gapped).
**تلگرام + الکترום** — یک ربات تلگرام خودمیزبان برای مدیریت کیف‌پول‌های بیت‌کوین با Electrum.
## قابلیت‌ها
تله‌گتروم برای **کیف‌پول‌های فقط-تماشا (xpub) با امضای آفلاین (air-gapped)** ساخته شده است. کلیدهای خصوصی شما هرگز روی سرور قرار نمی‌گیرند. ربات می‌تواند موجودی را ببیند، آدرس دریافت بسازد و تراکنش **امضانشده** بسازد؛ امضا فقط روی دستگاه آفلاین شما انجام می‌شود.
- کیف‌پول جداگانه برای هر کاربر
- بازیابی کیف‌پول فقط-تماشا از xpub
- نمایش موجودی (تأییدشده / تأییدنشده)
- دریافت آدرس
- ساخت تراکنش امضانشده (PSBT) با انتخاب کارمزد
- تغییر واحد: BTC / mBTC / ساتوشی
- پشتیبانی از زبان فارسی و انگلیسی
- کیبورد ثابت در پایین چت
- پشتیبانی اختیاری از Tor (اتصال از طریق .onion به سرور عمومی یا نود شخصی)
---
## مدل امنیتی — این بخش را حتماً بخوانید
| | |
|---|---|
| **سرور هیچ کلید خصوصی ندارد** | شما فقط **xpub** وارد می‌کنید. قابلیت تماشا دارد، نه خرج کردن. |
| **خرج کردن نیازمند دستگاه آفلاین است** | ربات تراکنش امضانشده می‌سازد؛ شما آن را جای دیگر امضا و برای انتشار برمی‌گردانید. |
| **دسترسی به‌صورت پیش‌فرض بسته است** | فقط شناسه‌های تلگرامی که شما تعیین کنید اجازه دارند. فهرست خالی یعنی هیچ‌کس اجازه ندارد. |
| **اطلاعات حساس از چت پاک می‌شوند** | رمز کیف‌پول و xpub بلافاصله پس از خوانده‌شدن حذف می‌شوند. |
| **کیف‌پول هر کاربر جداست** | هر کاربر پوشهٔ مخصوص خود را دارد و نام‌ها اعتبارسنجی می‌شوند تا کسی به فایل‌های دیگری دسترسی پیدا نکند. |
**در برابر چه چیزهایی محافظت نمی‌کند.** هر کسی که به حساب تلگرام شما دسترسی داشته باشد می‌تواند موجودی و آدرس‌ها را ببیند و تراکنش بسازد (اما نمی‌تواند امضا کند). هر کسی که دسترسی root روی سرور داشته باشد می‌تواند فایل‌های کیف‌پول را بخواند و در لحظهٔ اجرای دستور Electrum رمز کیف‌پول را در فهرست پردازه‌ها ببیند — پس سرور را قابل‌اعتماد نگه دارید و فهرست مجاز را کوتاه. xpub شما یک راز حریم خصوصی است: هر کس آن را داشته باشد تمام تاریخچهٔ تراکنش‌های شما را برای همیشه می‌بیند.
---
## راه‌اندازی سریع (پیشنهادی)
بدون کلون کردن مخزن و بدون build. فقط دو فایل و یک دستور.
```bash
mkdir telegtrum && cd telegtrum
curl -O https://git.goyban.com/goyban/telegtrum_bot/raw/branch/main/docker-compose.deploy.yml
curl -o .env https://git.goyban.com/goyban/telegtrum_bot/raw/branch/main/.env.deploy.example
nano .env # توکن ربات و شناسه کاربری تلگرام خود را وارد کنید
docker compose -f docker-compose.deploy.yml up -d
docker compose -f docker-compose.deploy.yml logs -f
```
فایل `.env` به دو مقدار نیاز دارد:
```dotenv
TELEGRAM_BOT_TOKEN=123456:ABC... # از @BotFather
ALLOWED_USERS=123456789 # از @userinfobot، برای چند نفر با کاما جدا کنید
```
اگر `ALLOWED_USERS` تنظیم نشده باشد، compose اجرا نمی‌شود — به‌جای اینکه رباتی بالا بیاید که هیچ‌کس نتواند از آن استفاده کند.
باید پیام `Electrum daemon started. Launching bot...` را ببینید. سپس در تلگرام به ربات پیام دهید و **Add Wallet** را بزنید.
### به‌روزرسانی
```bash
docker compose -f docker-compose.deploy.yml pull
docker compose -f docker-compose.deploy.yml up -d
```
اطلاعات کیف‌پول در ولوم `telegtrum-data` باقی می‌ماند و با به‌روزرسانی از بین نمی‌رود.
---
## پیش‌نیازها
- یک سرور لینوکسی با Docker و Docker Compose نصب‌شده
- توکن ربات تلگرام (از [@BotFather](https://t.me/BotFather))
- شناسه کاربری تلگرام شما (از [@userinfobot](https://t.me/userinfobot))
- یک سرور لینوکسی با Docker و Docker Compose
- توکن ربات تلگرام — [@BotFather](https://t.me/BotFather)
- شناسه کاربری تلگرام شما — [@userinfobot](https://t.me/userinfobot)
---
## راه‌اندازی سرور (گام‌به‌گام)
## ساخت از روی سورس
### ۱. کلون کردن مخزن
فقط اگر می‌خواهید ربات را تغییر دهید.
```bash
git clone https://git.goyban.com/goyban/telegtrum_bot.git
cd telegtrum_bot
```
### ۲. ساخت فایل `.env`
```bash
cp .env.example .env
nano .env
```
مقادیر را پر کنید:
```
ELECTRUM_VERSION=4.7.2
TELEGRAM_BOT_TOKEN=توکن_ربات_شما
```
### ۳. افزودن شناسه کاربری تلگرام به لیست کاربران مجاز
```bash
nano allowed_users.txt
```
یک خط به این فرمت اضافه کنید:
```
123456789, علی
```
شناسه کاربری خود را می‌توانید با ارسال پیام به [@userinfobot](https://t.me/userinfobot) در تلگرام پیدا کنید.
### ۴. ساخت و راه‌اندازی کانتینر
```bash
cp .env.example .env && nano .env
docker compose up -d --build
```
این دستور:
- ایمیج Docker با Electrum نصب‌شده را می‌سازد
- دیمن Electrum را راه‌اندازی می‌کند
- ربات تلگرام را اجرا می‌کند
در این حالت فایل `bot.py` به‌صورت read-only مانت می‌شود، پس می‌توانید آن را ویرایش کنید و فقط `docker compose restart` بزنید.
### ۵. بررسی لاگ‌ها
### فهرست کاربران مجاز: فایل یا متغیر محیطی
```bash
docker compose logs -f
هر دو کار می‌کنند؛ اگر هر دو را استفاده کنید، با هم ادغام می‌شوند.
**متغیر محیطی** (ساده‌ترین راه — نیازی به مانت فایل نیست):
```dotenv
ALLOWED_USERS=123456789,987654321
```
باید پیام `Electrum daemon started. Launching bot...` را ببینید.
**فایل** — `allowed_users.txt`، هر کاربر در یک خط، به شکل `id, Name`:
```bash
cp allowed_users.txt.example allowed_users.txt
```
```
123456789, Alice
```
> اگر `allowed_users.txt` را مانت کنید ولی فایل وجود نداشته باشد، داکر بی‌سروصدا یک **پوشه** به‌جای آن می‌سازد و هیچ‌کس نمی‌تواند وارد شود. اکنون کانتینر این حالت را تشخیص می‌دهد و با پیام روشن متوقف می‌شود.
### انتشار ایمیج جدید
```bash
./push.sh # نسخه از فایل VERSION خوانده می‌شود
./push.sh 1.0.1 # یا نسخه را مستقیم بدهید
```
---
## حالت Tor
## حالت‌های اتصال
حالت Tor، Electrum را از طریق شبکه Tor اجرا می‌کند. از یک فایل Docker Compose و Dockerfile جداگانه استفاده می‌کند تا راه‌اندازی استاندارد تحت تأثیر قرار نگیرد.
### استاندارد — سرورهای عمومی Electrum
### راه‌اندازی
حالت پیش‌فرض. برای اتصال فقط به یک سرور مشخص:
```dotenv
ELECTRUM_SERVER=192.168.1.100:50001:t
```
### محلی / Umbrel — نود شخصی شما
```bash
cp .env.example .env # مقادیر TELEGRAM_BOT_TOKEN و UMBREL_IP را تنظیم کنید
docker compose -f docker-compose.local.yml up -d --build
```
> آدرس `umbrel.local` داخل کانتینر **کار نمی‌کند** — mDNS فقط روی خود میزبان در دسترس است. از IP واقعی استفاده کنید، مثلاً `192.168.1.100`.
در اولین اجرا فایل `./electrum-data/config` با همان سرور نوشته می‌شود. اگر فایل از قبل باشد دست نمی‌خورد، پس تغییرات دستی شما باقی می‌مانند.
> اگر وصل نشد، بررسی کنید رشتهٔ سرور در `./electrum-data/config` هنوز به `:t` (یعنی TCP) ختم شود. گاهی Electrum آن را به `:s` (SSL) تغییر می‌دهد. کانتینر را متوقف کنید، برگردانید و دوباره اجرا کنید.
### Tor
```bash
cp .env.tor.example .env
nano .env
docker compose -f docker-compose.tor.yml up -d --build
```
`TELEGRAM_BOT_TOKEN` را پر کنید و یکی از حالت‌های اتصال را انتخاب کنید:
**گزینه الف — نود Electrum شخصی از طریق Tor:**
```
یا نود onion خودتان را بدهید:
```dotenv
ELECTRUM_SERVER=yournode123.onion:50001:t
```
…یا خالی بگذارید تا از سرور onion عمومی استفاده شود (`electrums3lojbuj.onion:50001:t`، قابل تغییر با `ELECTRUM_ONION_SERVER`).
**گزینه ب — سرور عمومی .onion (پیش‌فرض، نیاز به تنظیم اضافه ندارد):**
`ELECTRUM_SERVER` را خالی بگذارید. ربات به `electrums3lojbuj.onion:50001:t` وصل می‌شود. برای تغییر از `ELECTRUM_ONION_SERVER` استفاده کنید.
### راه‌اندازی
```bash
docker compose -f docker-compose.tor.yml up -d --build
```
### نکات
- Tor داخل همان کانتینر اجرا می‌شود — نیازی به سرویس جداگانه نیست.
- کانتینر صبر می‌کند تا SOCKS proxy آماده شود، سپس Electrum را راه‌اندازی می‌کند.
- داده‌های کیف‌پول در یک volume جداگانه (`electrum-tor-data`) ذخیره می‌شود.
- حرف `t` در آدرس سرور به معنای TCP است — رمزنگاری توسط لایه Tor انجام می‌شود نه SSL.
نکته‌ها:
- Tor داخل همان کانتینر اجرا می‌شود؛ entrypoint قبل از اجرای Electrum منتظر آماده‌شدن پروکسی SOCKS می‌ماند.
- **استعلام کارمزد هم از Tor عبور می‌کند.** از سرویس onion سایت mempool.space استفاده می‌شود، بنابراین بررسی کارمزد نمی‌تواند IP سرور شما را به فعالیت بیت‌کوینی‌تان ربط دهد.
- اطلاعات کیف‌پول در ولوم جداگانه (`electrum-tor-data`) نگهداری می‌شود.
- `:t` یعنی TCP — رمزنگاری را خود Tor انجام می‌دهد و SSL لازم نیست.
---
## به‌روزرسانی ربات
## کار با ربات
فایل `bot.py` به‌صورت volume سوار شده، پس بدون نیاز به rebuild می‌توانید آن را تغییر دهید:
یک کیبورد ثابت در پایین چت نمایش داده می‌شود.
```bash
# ویرایش bot.py، سپس:
docker compose restart
# یا برای حالت Tor:
docker compose -f docker-compose.tor.yml restart
```
برای به‌روزرسانی Electrum یا پکیج‌های سیستم:
```bash
docker compose up -d --build
# یا برای حالت Tor:
docker compose -f docker-compose.tor.yml up -d --build
```
---
## افزودن یا حذف کاربران مجاز
فایل `allowed_users.txt` را ویرایش کرده و ریستارت کنید:
```bash
nano allowed_users.txt
docker compose restart
```
---
## ذخیره‌سازی داده‌ها
داده‌های کیف‌پول در یک volume نام‌دار Docker در مسیر `/root/.electrum` داخل کانتینر ذخیره می‌شود و در ریستارت‌ها و rebuild‌ها باقی می‌ماند.
| حالت | نام volume |
| دکمه | کاری که انجام می‌دهد |
|---|---|
| استاندارد | `electrum-data` |
| Tor | `electrum-tor-data` |
| **Add Wallet** | افزودن کیف‌پول فقط-تماشا: نام ← xpub ← رمز. پیام حاوی xpub پس از خواندن حذف می‌شود. |
| **List** | فهرست کیف‌پول‌های شما. |
| **Load** | فعال‌کردن یک کیف‌پول (رمز می‌خواهد). برای Balance / Receive / Send لازم است. |
| **Balance** | موجودی تأییدشده و تأییدنشده. دکمه‌های شیشه‌ای واحد را بین BTC / mBTC / ساتوشی عوض می‌کنند. |
| **Receive** | یک آدرس دریافت استفاده‌نشدهٔ تازه. |
| **Send** | ساخت تراکنش **امضانشده** — پایین‌تر توضیح داده شده. |
| **Close** | خارج‌کردن کیف‌پول فعال از دیمن. |
| **🌐 Language** | تغییر بین فارسی و انگلیسی. |
برای پشتیبان‌گیری (حالت استاندارد):
نام کیف‌پول می‌تواند شامل حروف، اعداد، فاصله، نقطه، خط تیره و زیرخط باشد (۱ تا ۶۴ کاراکتر) و باید با حرف یا عدد شروع شود. رمز باید حداقل ۸ کاراکتر و شامل حرف بزرگ، حرف کوچک و عدد باشد.
### ارسال
۱. **Send** ← انتخاب منبع کارمزد: **Electrum** یا **mempool.space** (زنده)
۲. نرخ کارمزد را بر حسب sat/vB وارد کنید
۳. رمز کیف‌پول را وارد کنید *(پیام بلافاصله حذف می‌شود)*
۴. آدرس مقصد را وارد کنید
۵. مبلغ را وارد کنید یا **Send Max** را بزنید
۶. تراکنش امضانشده را هم به‌صورت متن و هم فایل `.txt` دریافت می‌کنید
۷. آن را آفلاین امضا کنید — الکترومِ اندروید: *Send ← Paste from clipboard*؛ نسخهٔ دسکتاپ: *Send ← آیکون ابزار ← Read text from file*
۸. **Send ← Broadcast** و تراکنش امضاشده را بچسبانید
---
## پشتیبان‌گیری
همه چیز — کیف‌پول‌ها، تنظیمات و هدرهای بلاک‌چین — در یک ولوم است.
```bash
docker run --rm -v electrum-data:/data -v $(pwd):/backup debian:bookworm-slim \
tar czf /backup/electrum-backup.tar.gz -C /data .
# حالت راه‌اندازی سریع
docker run --rm -v telegtrum-data:/data -v "$PWD":/backup debian:bookworm-slim \
tar czf /backup/telegtrum-backup.tar.gz -C /data .
```
---
| حالت | ولوم |
|---|---|
| راه‌اندازی سریع | `telegtrum-data` |
| ساخت از سورس | `electrum-data` |
| Tor | `electrum-tor-data` |
| محلی / Umbrel | `./electrum-data` (bind mount) |
## راهنمای استفاده از ربات
### شروع کار
ربات را در تلگرام باز کنید و هر پیامی ارسال کنید. یک کیبورد ثابت در پایین چت با تمام دکمه‌ها نمایش داده می‌شود.
### افزودن کیف‌پول (Add Wallet)
وارد کردن کیف‌پول فقط-تماشا از xpub:
1. روی **Add Wallet** بزنید
2. نام کیف‌پول را وارد کنید
3. xpub خود را پیست کنید
4. رمز عبور تعیین کنید (حداقل ۸ کاراکتر، شامل حرف بزرگ، کوچک و عدد)
### لیست (List)
نمایش تمام کیف‌پول‌های شما.
### بارگذاری (Load)
بارگذاری یک کیف‌پول برای فعال‌سازی:
1. روی **Load** بزنید
2. کیف‌پول را انتخاب کنید (اگر فقط یک کیف‌پول دارید، خودکار انتخاب می‌شود)
3. رمز عبور کیف‌پول را وارد کنید
### موجودی (Balance)
نمایش موجودی تأییدشده و تأییدنشده کیف‌پول فعال.
با دکمه‌های inline زیر موجودی می‌توانید بین **BTC**، **mBTC** و **ساتوشی** تغییر دهید.
### دریافت (Receive)
نمایش آدرس دریافت جدید برای کیف‌پول فعال.
### ارسال (Send)
ساخت تراکنش امضانشده (PSBT) برای امضای آفلاین:
1. روی **Send** بزنید
2. منبع کارمزد را انتخاب کنید: **Electrum** (پیشنهادی) یا **mempool.space** (زنده)
3. نرخ کارمزد را به صورت sat/vB وارد کنید
4. رمز عبور کیف‌پول را وارد کنید
5. آدرس گیرنده را وارد کنید
6. مقدار را وارد کنید (بر اساس واحد انتخابی)
7. تراکنش امضانشده را به‌صورت کد و فایل `.txt` دریافت کنید
8. آن را با کیف‌پول آفلاین خود امضا کنید، سپس از **Broadcast** استفاده کنید
### بستن (Close)
کیف‌پول فعال را از دیمن Electrum خارج می‌کند.
### زبان
روی **🌐 Language** بزنید تا بین فارسی و انگلیسی تغییر دهید.
پشتیبان جای عبارت بازیابی (seed) را نمی‌گیرد. اینها کیف‌پول فقط-تماشا هستند؛ چیزی که واقعاً دارایی شما را برمی‌گرداند، seed روی دستگاه آفلاین شماست.
---
## عیب‌یابی
## رفع اشکال
**ربات پاسخ نمی‌دهد:** لاگ‌ها را با `docker compose logs -f` بررسی کنید. مطمئن شوید توکن ربات درست است و کانتینر در حال اجراست.
**ربات پاسخ نمی‌دهد** — با `docker compose logs -f` لاگ را ببینید. توکن را بررسی کنید و مطمئن شوید کانتینر مدام ری‌استارت نمی‌شود.
**"شما مجاز نیستید":** شناسه کاربری تلگرام شما در `allowed_users.txt` نیست. آن را اضافه کرده و ریستارت کنید.
**«شما مجاز به استفاده از این ربات نیستید»** — شناسهٔ شما در `ALLOWED_USERS` یا `allowed_users.txt` نیست. اضافه و ری‌استارت کنید.
**خطای کیف‌پول بارگذاری‌نشده:** قبل از بررسی موجودی، دریافت یا ارسال، از **Load** استفاده کنید.
**همه رد می‌شوند** — اگر هر دو منبع خالی باشند، کانتینر هنگام اجرا پیام `no allowed users configured` را ثبت می‌کند.
**دیمن شروع نمی‌شود:** کانتینر lockfile را هنگام راه‌اندازی خودکار حذف می‌کند. اگر مشکل ادامه داشت، `docker compose restart` را امتحان کنید.
**«کیف‌پولی بارگذاری نشده»** — اول **Load** را بزنید؛ Balance و Receive و Send همگی به کیف‌پول فعال نیاز دارند.
**حالت Tor — Electrum وصل نمی‌شود:** bootstrap اولیه Tor تا ۳۰ ثانیه طول می‌کشد. لاگ‌ها را با `docker compose -f docker-compose.tor.yml logs -f` بررسی کنید.
**نام کیف‌پول نامعتبر** — فقط حروف، اعداد، فاصله، نقطه، خط تیره و زیرخط.
**دیمن اجرا نمی‌شود** — entrypoint در هر اجرا فایل قفل قدیمی را پاک می‌کند. اگر باز هم بود، `docker compose restart` بزنید.
**Tor وصل نمی‌شود** — راه‌اندازی اولیهٔ Tor ممکن است حدود ۳۰ ثانیه طول بکشد.
---
## اطمینان از چیزی که اجرا می‌کنید
ایمیج، Electrum را از روی تاربالِ رسمی می‌سازد و **امضای GPG آن را با اثرانگشت‌های پین‌شدهٔ کلیدهای انتشار** (ThomasV و sombernight و Emzy) بررسی می‌کند. اگر امضا نباشد یا اثرانگشت نخواند، build شکست می‌خورد و کیف‌پول تأییدنشده منتشر نمی‌شود.
می‌توانید خودتان با `./push.sh` بازتولیدش کنید — یا فایل [`install.sh`](install.sh) را بخوانید، فقط ۶۰ خط است.