███╗ ██╗████████╗ ██████╗██████╗
████╗ ██║╚══██╔══╝██╔════╝██╔══██╗
██╔██╗ ██║ ██║ ██║ ██████╔╝
██║╚██╗██║ ██║ ██║ ██╔═══╝
██║ ╚████║ ██║ ╚██████╗██║
╚═╝ ╚═══╝ ╚═╝ ╚═════╝╚═╝
secure resumable file transfer
İki sunucu arasında hızlı, kesintisiz, kaldığı yerden devam eden, güvenli dosya ve klasör transferi. Tek dosya Go binary — stdlib only, dış bağımlılık yok.
# Alıcı (sadece bir kez)
curl -fsSL 3kr.org/install | sudo sh
sudo ntcp init # token modu seç (kalıcı / TTL)
# Gönderici
ntcp ./build/ 1.2.3.4 <token> /var/www/site/- ✦ Default port: 2396
- ✦ Resume artıkları:
.emr+.emr.bm - ✦ Wire: TLS 1.3 + TOFU pinning
- ✦ Default install dir:
/etc/ntcp/(Linux),~/Library/Application Support/ntcp/(macOS),C:\ProgramData\ntcp\(Windows)
| rsync over SSH | scp | rclone | ntcp | |
|---|---|---|---|---|
| Kaldığı yerden devam | ✓ | ✗ | ✓ | ✓ |
| TLS şifreleme | ✓ (SSH) | ✓ (SSH) | ✓ | ✓ (TLS 1.3) |
| Parola yerine token | ✗ | ✗ | ✓ | ✓ (TTL'li) |
| SSH erişimi gerekmez | ✗ | ✗ | ✓ | ✓ |
| Tek binary, dependency yok | ✗ | ✗ | ✗ | ✓ |
| Servis olarak kurulur | ✗ | ✗ | ✗ | ✓ |
| Animasyonlu progress bar | ✗ | ✓ (kısmen) | ✓ | ✓ |
| 4 MiB blok bitmap resume | ✗ | ✗ | ✗ | ✓ |
| Cross-platform tek dosya | ~ | ~ | ✓ | ✓ |
curl -fsSL 3kr.org/install | sudo shirm 3kr.org/install.ps1 | iexhttps://github.com/muslu/nettransfer/releases/latest adresinden işletim sistemine uygun binary'yi indir, çalıştırılabilir yap.
Desteklenen platformlar: linux/amd64+arm64, darwin/amd64+arm64, windows/amd64+386.
sudo ntcp install # servis kur + ilk token üret
sudo ntcp init # token modunu seç (interaktif)ntcp install ekrana bir kez token bastırır — kaydet, kaybedersen yeni token üret:
sudo ntcp token # mevcut moda göre üretir
sudo ntcp token --ttl 1h # özel süreli token# Tek dosya
ntcp ./build.tar 1.2.3.4 <token>
# Klasör
ntcp ./dist/ 1.2.3.4 <token>
# Port belirt
ntcp ./build.tar 1.2.3.4:2396 <token>
# Sunucuda HEDEF YOL belirt
ntcp ./site.tar 1.2.3.4 <token> /var/www/site/
# Başarılı transferden sonra lokali sil
ntcp ./build.tar 1.2.3.4 <token> --delete-afterAynı komutu tekrar çalıştırırsan: yarıda kalan transfer kaldığı yerden devam eder; başarıyla teslim edilmiş dosyalar tekrar gönderilmez (size+mtime ile tespit).
ntcp <local> <host> <token> [remote-dir] — [remote-dir] 4. opsiyonel argümandır. İki şey karara etkili:
- Lokal trailing slash → top dir adının dahil edilip edilmediği (rsync semantik)
- Hedef absolute / relative → sandbox altı veya dışı
| Lokal | [remote-dir] |
Sunucu sonucu |
|---|---|---|
src/ |
(yok) | <data>/<içerik> |
src |
(yok) | <data>/src/<içerik> |
src/ |
tgt/ |
<data>/tgt/<içerik> |
src |
tgt/ |
<data>/tgt/src/<içerik> |
src/ |
/opt/foo/ |
/opt/foo/<içerik> |
src |
/opt/foo/ |
/opt/foo/src/<içerik> |
src/ |
/opt/foo/src/ |
/opt/foo/src/<içerik> |
💡 En sezgisel formül: hedef olarak tam yolu yaz (
/opt/foo/src/). Sonra lokal'in slash'i ne olursa olsun aynı sonucu alırsın.
# Ne yaparsan yap /var/www/site/ altına gider:
ntcp ./build/ 1.2.3.4 TOKEN /var/www/site/
ntcp ./build 1.2.3.4 TOKEN /var/www/site/build/..her iki tarafta reddedilir (path traversal guard)- Relative hedef (
releases/v1/) → server data dizini altı (sandbox) - Absolute hedef (
/opt/foo/) → daemon UID'nin yazma izni olan herhangi bir yere
Default systemd unit'i ProtectSystem=full + ReadWritePaths=/etc/ntcp ile birlikte gelir:
| Yazılabilir varsayılan | Yazılamaz varsayılan |
|---|---|
/var/, /home/, /tmp/, /srv/, /opt/, /root/, /etc/ntcp/ |
/usr/, /boot/, /etc/<ntcp dışı> |
Yasaklı yerlere yazmak için /etc/systemd/system/ntcp.service içine ek ReadWritePaths=... satırı ekleyip systemctl daemon-reload && systemctl restart ntcp.
ntcp <local> <host[:port]> <token> [remote-dir] [--delete-after|--rm]
ntcp install
ntcp init [BASE_DIR]
ntcp token [--ttl <1h|24h|7d|0>] [BASE_DIR]
ntcp daemon [BASE_DIR]
ntcp uninstall
| Komut | Açıklama |
|---|---|
ntcp <local> <host[:port]> <token> |
Tek dosya veya klasör gönder (asgari kullanım) |
<token> sonrası [remote-dir] |
Sunucudaki hedef yol — relative veya absolute |
<token> sonrası --delete-after / --rm |
Başarılı transfer sonrası lokal kaynağı sil |
ntcp install |
Servis kur, ilk token üret, ekrana bastır |
ntcp init |
Token modu seç (interaktif: persistent / TTL) |
ntcp token [--ttl <duration>] |
Yeni token üret; TTL=0 → kalıcı (mode'u override eder) |
ntcp daemon |
Foreground daemon (servis entry point) |
ntcp uninstall |
Servisi kaldır (cert/keys/tokens kalır) |
ntcp init ile iki mod arasında seçim:
| Mod | Davranış | tokens.txt satırı |
|---|---|---|
| Kalıcı (persistent) | Token süresiz; manuel silinene kadar kullanılır | sha256:<hex> |
| Süreli (TTL) | Belirli süre (örn. 1h, 24h, 7d) sonunda otomatik geçersiz |
sha256:<hex> expires=<RFC3339> |
Süresi geçen tokenlar daemon tarafından her 10 dakikada bir otomatik temizlenir (atomic rewrite).
sudo ntcp init # interaktif mod seçimi
sudo ntcp token # mevcut moda göre yeni token
sudo ntcp token --ttl 30m # 30 dakikalık (mode override)
sudo ntcp token --ttl 0 # kalıcı (TTL modundayken bile)ntcp token veya ntcp init ile dışarıdan eklenen tokenlar daemon restart gerektirmez — sunucu her Verify() çağrısında tokens.txt mtime'ını kontrol edip değiştiyse otomatik yeniden yükler.
| Değişken | Default | Açıklama |
|---|---|---|
NTCP_PORT |
2396 |
Dinleme / bağlantı portu |
NTCP_BASE |
OS'a göre | Server BASE_DIR (cert + keys + tokens + data) |
NTCP_INSECURE |
(boş) | 1 ise TOFU pinning atlanır — sadece test/CI |
NTCP_FINGERPRINT |
(boş) | Beklenen sunucu sertifikasının SHA-256 fingerprint'i (pin) |
| OS | BASE_DIR |
|---|---|
| Linux | /etc/ntcp/ |
| macOS | /Library/Application Support/ntcp/ |
| Windows | C:\ProgramData\ntcp\ |
İçindekiler:
cert.pem # self-signed sertifika
key.pem # özel anahtar (mode 0600)
tokens.txt # SHA-256 hashleri (mode 0600)
mode.txt # mode=persistent|ttl + default_ttl=...
data/ # default transfer hedefi (relative remote-dir → bu altı)
~/.ntcp/known_hosts — <host>:<port> <sha256_fingerprint> satırları. Sunucu sertifikası değişirse manuel silinmesi gerekir.
| OS | Mekanizma | Yol |
|---|---|---|
| Linux | systemd | /etc/systemd/system/ntcp.service |
| macOS | launchd | /Library/LaunchDaemons/com.ntcp.daemon.plist |
| Windows | sc.exe | Service name: ntcp |
# Linux
sudo systemctl status ntcp
sudo journalctl -u ntcp -f
sudo systemctl restart ntcp
# macOS
sudo launchctl print system/com.ntcp.daemon
# Windows
sc query ntcp# Lokal dist/ → sunucudaki /var/www/site/ (rsync-style)
ntcp ./dist/ 1.2.3.4 TOKEN /var/www/site/tar czf /tmp/db-$(date +%F).tar.gz /var/lib/postgresql
ntcp /tmp/db-*.tar.gz 1.2.3.4 TOKEN /srv/backup/ --delete-after# İçerik değişirse (boyut aynı olsa bile) server mtime farkından
# yeniden gönderir; aynı içerik tekrar gönderilirse skip.
ntcp ./style.css 1.2.3.4 TOKEN /var/www/css/main.css# Plain-text token yerine GitHub Actions secret ile;
# pin out-of-band sağlanır ki MITM mümkün olmasın
export NTCP_FINGERPRINT=37c0eea50b4cc3213189d5746292436f3cdeb731ad385a8e4e36ebc013cb082d
ntcp ./build.tar 1.2.3.4 "$NTCP_TOKEN" /srv/releases/# Yarıda kesilirse yeniden çalıştır: kaldığı yerden devam eder
ntcp ./database-50GB.dump 1.2.3.4 TOKEN /srv/dumps/| Katman | Detay |
|---|---|
| TCP | keep-alive 30 sn, NoDelay, 2 MiB buffer |
| TLS | 1.3 zorunlu, self-signed sertifika, TOFU pin |
| Magic | 0x4E544635 ("NTF5") |
| Token | 32 byte random, base64url; sunucuda sadece SHA-256 hash |
| Manifest | [file_count u32] + N × (rel u16len_str, size u64, mtime_ns u64) |
| Resume reply | Her dosya için FsComplete / FsFresh / FsPartial (bitmap) |
| Chunk header | 20 byte: file_index u32, offset u64, length u32, crc32c u32 |
| Blok | 4 MiB sabit |
| End marker | file_index = 0xFFFFFFFF |
- Token: 32 byte rastgele, base64url ile gösterilir. Sunucuda asla raw saklanmaz — yalnız SHA-256 hash (
tokens.txt, mode 0600). - Constant-time verify:
subtle.ConstantTimeCompare, erken çıkış yok (timing attack koruması). - TOFU: ilk bağlantıda fingerprint pinlenir; sonraki bağlantılarda mismatch ise reddedilir (
~/.ntcp/known_hosts). - Rate limit: per-IP 60 deneme/dakika.
- Bağlantı tavanı: 100 eşzamanlı maks.
- Path confinement:
..ikisinde de reddedilir; relative path sandbox altı. - systemd hardening:
ProtectSystem=full,ProtectHome=true,NoNewPrivileges=true,ReadWritePaths=/etc/ntcp.
Token sahibi sunucuda daemon UID'nin (genelde root) yazma yetkisi olan her yere transfer atabilir. Düzgün sandbox için ya relative
[remote-dir]kullan, ya da systemd unit'indeReadWritePaths'i daralt.
git clone https://github.com/muslu/nettransfer.git
cd nettransfer
go vet .
go build -o ntcp ntcp.gofor tgt in linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64 windows/386; do
GOOS=${tgt%/*} GOARCH=${tgt#*/} CGO_ENABLED=0 \
go build -trimpath -ldflags='-s -w' \
-o ntcp-${tgt%/*}-${tgt#*/}$([ "${tgt%/*}" = "windows" ] && echo .exe) \
ntcp.go
doneNTCP_BASE=/tmp/ntcp-test NTCP_PORT=12396 ./ntcp daemon &
NTCP_BASE=/tmp/ntcp-test ./ntcp init # interaktif
NTCP_INSECURE=1 ./ntcp /tmp/file 127.0.0.1:12396 <token>.github/workflows/release.yml — v* tag push'unda 6 platform matrix build + GitHub Release.
.github/workflows/ci.yml — her push/PR'da go vet + build smoke.
git tag v0.4.0 && git push origin v0.4.0 # → Actions otomatik release| Sürüm | Tarih | Öne çıkan |
|---|---|---|
| v0.4.0 | 2026-06-03 | Absolute remote-dir, rsync-style trailing slash, --delete-after/--rm |
| v0.3.1 | 2026-06-03 | install.sh ANSI escape literal fix |
| v0.3.0 | 2026-06-03 | TTY-aware ANSI UI + animasyonlu progress bar + token store hot-reload |
| v0.2.0 | 2026-06-03 | Wire NTF5: manifest'e mtime_ns (içerik drift tespiti) + [remote-dir] arg |
| v0.1.1 | 2026-06-03 | systemd ReadWritePaths=/etc/ntcp fix |
| v0.1.0 | 2026-06-03 | İlk release: port 2396, .emr resume, TLS 1.3 + TOFU, TTL token modu |
MIT — bkz. LICENSE.
- Issue & PR: github.com/muslu/nettransfer
- Kısa URL:
3kr.org/install→ install.sh,3kr.org/install.ps1→ install.ps1