Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ jobs:
if [[ -n "${{ matrix.goarch }}" ]]; then export GOARCH="${{ matrix.goarch }}" CC="${{ matrix.cc }}"; fi
# one self-contained binary per platform
out="dist/traffic66-${{ matrix.target }}/$exe"
kind=community; [[ "$GITHUB_REF" == refs/tags/* ]] && kind=official
# a tag push and a one-click release (a version entered by hand)
# are both releases; only the builds of every push stay community
kind=community; [[ "$GITHUB_REF" == refs/tags/* || -n "${{ inputs.version }}" ]] && kind=official
ldflags="-s -w -X main.version=${ver} -X main.buildKind=${kind}"
tags=""
export CGO_ENABLED=1
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
The release notes on GitHub are taken from this file: the section whose
heading is the version number.

## 2.4.1

- Overview: Inbound and Outbound now mean which way the bytes went — what arrived at your hosts, what they sent — instead of who opened the connection. On a network whose hosts only connect outwards, Inbound used to be empty (and said the data was still arriving), although most of its traffic is the replies it downloads.
- 95th-percentile billing is removed: the page, `/api/billing`, `/api/billing/series`, the five-minute rate table it was computed from and the `billed` mark on interface lines (an inventory line that still carries it loads as before). The interface page shows the same counters, and `/api/report` now takes its counter figures from them.
- The evaluation mark is a step darker and a size larger.
- Threat lists can be imported from the threat page — a file or a paste, one address or network per line — and removed there. An imported list is saved as `<data>/threats/<name>.txt` and is in use at once, without a restart; it applies to flows from then on.
- Rooms and racks is a picture instead of an asset ledger, and free: every device that sends flows, in its room and rack, with each port and the carrier and circuit ID it goes out to. Devices and ports come from the flows; the room, rack, carrier and circuit are typed in once and kept in `inventory.txt` (`room=`, `rack=` on device lines, `isp=`, `circuit=` on interface lines). The ledger it replaces is removed — device pages, ports, cabling, circuits, networks, paste and CSV import — and its `assets.duckdb` is no longer opened (it can be deleted).
- The names page is called Inventory again, in every language (台账 in Chinese).
- The sponsor strip shows one advertiser at a time: a long banner alone, a small 728x90 one three times side by side.
- Releases started by hand from Actions report themselves as official builds (2.4.0 said "community build").

## 2.4.0

- Top 66 opens on the two ends of each conversation (top clients and top servers side by side) instead of the grouped table; the table is still one click away and a shared link still lands where the sender was.
Expand Down
15 changes: 1 addition & 14 deletions cmd/traffic66/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"unicode/utf8"

"github.com/githubflyideas/traffic66/internal/api"
"github.com/githubflyideas/traffic66/internal/assets"
"github.com/githubflyideas/traffic66/internal/auth"
"github.com/githubflyideas/traffic66/internal/capture"
"github.com/githubflyideas/traffic66/internal/collector"
Expand Down Expand Up @@ -57,7 +56,7 @@ var version = ""
// CHANGELOG.md. TestDevVersionMatchesChangelog keeps the two in step: the
// default used to be a hardcoded 0.1.0-dev, and because nothing checked it
// it stayed that way for two major versions.
const devVersion = "2.4.0"
const devVersion = "2.4.1"

func init() {
if version == "" {
Expand Down Expand Up @@ -522,18 +521,6 @@ func serve(args []string, demo bool) {
if lic != nil {
go lic.Loop(ctx.Done(), 4*time.Hour)
}
// The asset ledger opens whatever the licence says, so that installing
// one later needs no restart and nothing already written down is out of
// reach. Who may read and change it is decided per request. Analysing
// capture files has no installation to keep a ledger for.
if offline == nil {
if al, err := assets.Open(f.data); err != nil {
log.Printf("asset ledger: %v", err)
} else {
srv.Assets = al
defer al.Close()
}
}
if offline != nil {
srv.SB = sandbox.NewWith(filepath.Join(f.data, "sandbox"), inv, asn, thr, sandbox.LocalLimits, 0.25)
srv.Offline = true
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.ar.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ or udp port 4739`: إن لم يظهر شيء فالمشكلة في التوجي

## 7. الأسماء والدول وقوائم التهديدات

انقر على أي عنوان واختر **تسمية…**، أو استخدم **الإعدادات ← الأسماء**.
انقر على أي عنوان واختر **تسمية…**، أو استخدم **السجل**.
تُحفظ الأسماء في `inventory.txt` داخل دليل البيانات:

```
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.bn.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ traffic66 আগে থেকেই ডিভাইস যে rate প্রয

## 7. নাম, দেশ ও threat list

যেকোনো address-এ ক্লিক করে **নাম দিন…** বেছে নিন, অথবা **সেটিংস → নাম**
যেকোনো address-এ ক্লিক করে **নাম দিন…** বেছে নিন, অথবা **ইনভেন্টরি**
ব্যবহার করুন। নামগুলো data directory-র `inventory.txt`-এ থাকে:

```
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.de.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ hinzu (`-l2-overhead`).
## 7. Namen, Länder und Bedrohungslisten

Klicken Sie auf eine beliebige Adresse und wählen Sie **Benennen…**, oder
verwenden Sie **Einstellungen → Namen**. Namen werden in `inventory.txt` im
verwenden Sie **Inventar**. Namen werden in `inventory.txt` im
Datenverzeichnis gespeichert:

```
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ Ethernet a NetFlow/IPFIX (`-l2-overhead`).
## 7. Nombres, países y listas de amenazas

Haga clic en cualquier dirección y elija **Ponerle nombre…**, o use
**Configuración → Nombres**. Los nombres se guardan en `inventory.txt`
**Inventario**. Los nombres se guardan en `inventory.txt`
dentro del directorio de datos:

```
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ minutes et ajoute 18 octets par paquet de surcoût Ethernet à NetFlow/IPFIX
## 7. Noms, pays et listes de menaces

Cliquez sur n'importe quelle adresse et choisissez **Nommer…**, ou utilisez
**Paramètres → Noms**. Les noms sont enregistrés dans `inventory.txt` dans
**Inventaire**. Les noms sont enregistrés dans `inventory.txt` dans
le répertoire de données :

```
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.hi.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ traffic66 पहले से डिवाइस द्वारा लगाय

## 7. नाम, देश और threat lists

किसी भी address पर क्लिक करें और **नाम दें…** चुनें, या **सेटिंग्स → नाम**
किसी भी address पर क्लिक करें और **नाम दें…** चुनें, या **इन्वेंटरी**
इस्तेमाल करें। नाम data directory में `inventory.txt` में रखे जाते हैं:

```
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.id.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ NetFlow/IPFIX (`-l2-overhead`).
## 7. Nama, negara, dan daftar ancaman

Klik alamat mana pun lalu pilih **Beri nama…**, atau gunakan
**Pengaturan → Nama**. Nama disimpan di `inventory.txt` di direktori data:
**Inventaris**. Nama disimpan di `inventory.txt` di direktori data:

```
net 10.10.0.0/16 Office LAN # your networks
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ traffic66 はすでに、機器が適用したレートを使い、不明なレ

## 7. 名前、国・地域、脅威リスト

任意のアドレスをクリックして **名前を付ける…** を選ぶか、**設定 → 名前** を使います。名前はデータディレクトリの `inventory.txt` に保存されます:
任意のアドレスをクリックして **名前を付ける…** を選ぶか、**台帳** を使います。名前はデータディレクトリの `inventory.txt` に保存されます:

```
net 10.10.0.0/16 Office LAN # your networks
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ traffic66은 이미 장비가 적용한 비율을 사용하고, 알 수 없는

## 7. 이름, 국가, 위협 목록

아무 주소나 클릭해 **이름 붙이기…**를 선택하거나, **설정 → 이름**을 사용하십시오. 이름은 데이터 디렉터리의 `inventory.txt`에 저장됩니다:
아무 주소나 클릭해 **이름 붙이기…**를 선택하거나, **대장**을 사용하십시오. 이름은 데이터 디렉터리의 `inventory.txt`에 저장됩니다:

```
net 10.10.0.0/16 Office LAN # your networks
Expand Down
36 changes: 12 additions & 24 deletions docs/MANUAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ adds 18 bytes per packet of Ethernet overhead to NetFlow/IPFIX

## 7. Names, countries/regions and threat lists

Click any address and choose **Name it…**, or use **Settings → Names**.
Click any address and choose **Name it…**, or use **Inventory**.
Names are kept in `inventory.txt` in the data directory:

```
Expand Down Expand Up @@ -505,29 +505,17 @@ they are the same records. The hourly and daily summaries record traffic by
application, host and dimension, never by interface, so they keep their
totals.

### Asset ledger (registered)

**Sites & racks**, **Devices & ports** and **IP addresses** record where the
equipment stands, what it is cabled to, and which address is whose. It is a
ledger, not a discovery tool: nothing in it is polled or guessed, so when it
and the network disagree it still says what was meant to be there. Racks are
drawn by the unit; a device cannot be placed where another already stands.
Addresses are stored canonically, so "already assigned" is a reliable answer,
and a report names what does not add up — an address in no recorded network,
one MAC on several addresses.

Entry is by hand, by paste or by spreadsheet. **Paste** reads what the device
already prints — `show lldp neighbors`, `show cdp neighbors`,
`show interface status`, `show ip arp`, `show mac address-table` — with
nothing installed on the device and no community string or password stored
anywhere; paste the ARP table before the MAC address table and together they
say which port a host is plugged into. **CSV** exports and imports every
kind; the `id` column ties a row back to its record, so a file that came from
here updates what it came from instead of doubling it.

Everyone signed in reads these pages; the administrator writes them, and can
hide a record from everyone else. The ledger keeps its own `assets.duckdb`
beside the flow data, so deleting traffic never touches it.
### Rooms and racks

A picture of where the flows come from: for every device that sends flows,
the room and rack it stands in, and for each of its ports the carrier and
circuit ID it goes out to. Devices and ports appear by themselves from the
flows; click ✎ to type in the room, rack, carrier and circuit. It is filled
in once and kept in `inventory.txt` beside the names
(`device 192.0.2.1 Core router room=Room_1 rack=A03`,
`iface 192.0.2.1 3 Uplink isp=China_Telecom circuit=SH-12345`; a space is
written as `_`). Nothing is looked up in it. Everyone signed in sees it; the
administrator edits it.

### Licence

Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.pt.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ seus minutos e soma 18 bytes de overhead Ethernet por pacote ao NetFlow/IPFIX
## 7. Nomes, países e listas de ameaças

Clique em qualquer endereço e escolha **Dar um nome…**, ou use
**Configurações → Nomes**. Os nomes ficam em `inventory.txt` no diretório
**Inventário**. Os nomes ficam em `inventory.txt` no diretório
de dados:

```
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ traffic66 уже использует частоту, применённую у
## 7. Названия, страны и списки угроз

Щёлкните любой адрес и выберите **Дать название…** или используйте
**Настройки → Названия**. Названия хранятся в `inventory.txt` в каталоге
**Реестр**. Названия хранятся в `inventory.txt` в каталоге
данных:

```
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.ur.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ traffic66 پہلے ہی وہ rate استعمال کرتا ہے جو ڈیوائس

## 7. نام، ممالک اور threat lists

کسی بھی address پر کلک کر کے **نام دیں…** چنیں، یا **ترتیبات → نام** استعمال
کسی بھی address پر کلک کر کے **نام دیں…** چنیں، یا **رجسٹر** استعمال
کریں۔ نام data directory میں `inventory.txt` میں رکھے جاتے ہیں:

```
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.vi.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ overhead Ethernet cho mỗi gói tin với NetFlow/IPFIX (`-l2-overhead`).
## 7. Tên, quốc gia và danh sách mối đe dọa

Nhấp vào bất kỳ địa chỉ nào và chọn **Đặt tên…**, hoặc dùng
**Cài đặt → Tên**. Tên được lưu trong `inventory.txt` ở thư mục dữ liệu:
**Sổ quản lý**. Tên được lưu trong `inventory.txt` ở thư mục dữ liệu:

```
net 10.10.0.0/16 Office LAN # your networks
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ traffic66 已经做了这些处理:使用设备实际生效的采样率,等

## 7. 名称、国家/地区与威胁情报列表

点击任意地址并选择 **起个名字…**,或使用 **设定 → 名称**。名称保存在数据目录下的 `inventory.txt` 中:
点击任意地址并选择 **起个名字…**,或使用 **台账**。名称保存在数据目录下的 `inventory.txt` 中:

```
net 10.10.0.0/16 Office LAN # your networks
Expand Down
47 changes: 47 additions & 0 deletions internal/api/admin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package api

import "net/http"

// isAdmin reports whether the signed-in user manages the others. With no
// password file there is no administrator, so nothing may be written by
// anyone.
func (s *Server) isAdmin(r *http.Request) bool {
// This machine's own token counts: the TUI and the local subcommands
// carry it, and whoever can read it from the data directory could
// have changed the files there directly.
if local(r) {
return true
}
if s.Accounts == nil {
return false
}
u := userOf(r)
return u != "" && u == s.Accounts.Admin()
}

// adminOnly guards h with requireAdmin.
func (s *Server) adminOnly(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if s.requireAdmin(w, r) {
h(w, r)
}
}
}

// requireAdmin answers 403 unless the caller may change the installation
// itself, and is the gate behind every call that deletes stored data or
// reconfigures the installation for everybody.
//
// It is deliberately not admin(): that one asks for a password file it
// can write and answers 409 "fixed" without one, which is right when the
// call is about the account list and wrong here. An installation started
// with -password, or without a data directory, still has an
// administrator — it simply cannot add users — so gating these calls on
// admin() would lock such an installation out of its own settings.
func (s *Server) requireAdmin(w http.ResponseWriter, r *http.Request) bool {
if s.isAdmin(r) {
return true
}
writeJSON(w, http.StatusForbidden, map[string]string{"error": "not_admin"})
return false
}
22 changes: 9 additions & 13 deletions internal/api/adminonly_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,15 @@ import (
// that writes has to go through adminAPI, and TestEveryWriteIsDecided
// fails when a new route is added without that decision being made.
var openWrites = map[string]string{
"POST /api/login": "signing in is how you stop being anonymous",
"POST /api/logout": "ending one's own session",
"POST /api/password": "one's own password; the old one is asked for again",
"POST /api/users": "admin()'s own gate, which also refuses a fixed password file",
"DELETE /api/users": "same",
"POST /api/resolve": "reverse DNS for the names on screen; stores nothing",
"POST /api/findings": "marking an alert handled is the everyday work, not administration",
"POST /api/sandbox/files": "offline analysis: uploading a capture to look at",
"POST /api/sandbox/active": "choosing which uploaded capture to look at",
"POST /api/assets/csv": "ledgerAdmin: the licence gate and the admin check together",
"POST /api/assets/paste": "same",
"POST /api/assets/{kind}": "same",
"DELETE /api/assets/{kind}": "same",
"POST /api/login": "signing in is how you stop being anonymous",
"POST /api/logout": "ending one's own session",
"POST /api/password": "one's own password; the old one is asked for again",
"POST /api/users": "admin()'s own gate, which also refuses a fixed password file",
"DELETE /api/users": "same",
"POST /api/resolve": "reverse DNS for the names on screen; stores nothing",
"POST /api/findings": "marking an alert handled is the everyday work, not administration",
"POST /api/sandbox/files": "offline analysis: uploading a capture to look at",
"POST /api/sandbox/active": "choosing which uploaded capture to look at",
}

// TestEveryWriteIsDecided reads the route table and fails on a writing
Expand Down
Loading
Loading