Skip to content

Commit 7703647

Browse files
committed
automatic firewall
1 parent 433cf2e commit 7703647

File tree

4 files changed

+66
-53
lines changed

4 files changed

+66
-53
lines changed

README.md

+36-23
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ Idea to create a easy-to-use wrapper over [tinc vpn](https://www.tinc-vpn.org).
1717

1818
tinc-boot run
1919

20-
2120
**node 2**
22-
21+
2322
follow command from previous operation
2423

2524
### Custom token
@@ -32,28 +31,38 @@ follow command from previous operation
3231

3332
tinc-boot run -t MYSECRET --join http://<node1>:8665
3433

34+
### Firewall
35+
36+
> Use (--ufw) to open port on ufw-based systems automatically
37+
>
38+
> tinc-boot run --ufw ...
39+
>
40+
> Required opened default ports:
41+
>
42+
> * `<port>/udp,<port>/tcp` - port defined as `--tinc-port` or generated in `tinc.conf`
43+
> * `8665/tcp` - port defined as `-p --port` for boot protocol
44+
> * `18655/tcp (tinc interface)` - internal port for communication. Only for interface defined in `tinc.conf`
3545
3646
## Overview
3747

3848
Tinc VPN - is full-mesh, auto-healing, time-proofed VPN system without single point of failure, with high-throughput and
39-
serious cryptography.
40-
All nodes in a Tinc network are fully equal. New nodes discovering full topology through any entry point.
41-
Node may interact with each other even if they don't have direct connections.
49+
serious cryptography. All nodes in a Tinc network are fully equal. New nodes discovering full topology through any entry
50+
point. Node may interact with each other even if they don't have direct connections.
4251

43-
Tinc is a great and have a lot of features. It's ideal for a complicated situations (China, Russia and others).
44-
I really admire the project.
52+
Tinc is a great and have a lot of features. It's ideal for a complicated situations (China, Russia and others). I really
53+
admire the project.
4554

4655
![transit](https://user-images.githubusercontent.com/6597086/65304801-1b4ae480-dbb4-11e9-933f-b890242358ab.png)
4756

4857
**But...** it's pain to configure and maintain.
4958

5059
Pain to create a new node. Pain to add new node to network.
5160

52-
Minimal configuration for a first public node:
61+
Minimal configuration for a first public node:
5362

54-
* 2 files (tinc.conf, hostfile),
55-
* 1 script (tinc-up),
56-
* 2 directories (net, hosts),
63+
* 2 files (tinc.conf, hostfile),
64+
* 1 script (tinc-up),
65+
* 2 directories (net, hosts),
5766
* 1 command execution (key generation).
5867

5968
(let's not count service initialization and other common stuff)
@@ -62,15 +71,16 @@ Second node adds key exchange (+1 operation if we will use `rsync`, or +2 operat
6271

6372
![second_node](https://user-images.githubusercontent.com/6597086/65304124-72e85080-dbb2-11e9-939f-6359095dbe54.png)
6473

65-
Next new public nodes require increasing number of additional operations (+N operations, where N is a number of public nodes).
74+
Next new public nodes require increasing number of additional operations (+N operations, where N is a number of public
75+
nodes).
6676

6777
![third_node](https://user-images.githubusercontent.com/6597086/65304303-df634f80-dbb2-11e9-8b9a-32bd4c6b9c46.png)
6878

6979

70-
> To be honest, to just to connect to the network an only single key exchange operation required: with any public node.
80+
> To be honest, to just to connect to the network an only single key exchange operation required: with any public node.
7181
> Than tincd will discover all other nodes.
7282
>
73-
> **But** after your node disconnect/reboot and in case of death of your entry node you will be no more able to connect
83+
> **But** after your node disconnect/reboot and in case of death of your entry node you will be no more able to connect
7484
> to other alive nodes (because they don't know your key and your node don't know theirs).
7585
7686

@@ -90,18 +100,20 @@ Donating always welcome
90100
* ETH: `0xA4eD4fB5805a023816C9B55C52Ae056898b6BdBC`
91101
* BTC: `bc1qlj4v32rg8w0sgmtk8634uc36evj6jn3d5drnqy`
92102

93-
94103
## Installation
95104

96105
* (recommended) look at [releases](https://github.com/reddec/tinc-boot/releases) page and download
97106
* one line shell command:
107+
98108
```
99109
curl -L https://github.com/reddec/tinc-boot/releases/latest/download/tinc-boot_linux_amd64.tar.gz | sudo tar -xz -C /usr/local/bin/ tinc-boot
100110
```
111+
101112
* build from source `go get -v github.com/reddec/tinc-boot/cmd/...`
102113
* [Ansible galaxy](https://galaxy.ansible.com/reddec/tinc_boot): `ansible-galaxy install reddec.tinc_boot`
103114

104115
* From bintray repository for most **debian**-based distribution (`trusty`, `xenial`, `bionic`, `buster`, `wheezy`):
116+
105117
```bash
106118
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 379CE192D401AB61
107119
echo "deb https://dl.bintray.com/reddec/debian {distribution} main" | sudo tee -a /etc/apt/sources.list
@@ -110,7 +122,8 @@ sudo apt install tinc-boot
110122

111123
### Independent maintainers
112124

113-
* **Arch Linux** in AUR [package `tinc-boot-git`](https://aur.archlinux.org/packages/tinc-boot-git/): `yaourt -S tinc-boot-git`
125+
* **Arch Linux** in
126+
AUR [package `tinc-boot-git`](https://aur.archlinux.org/packages/tinc-boot-git/): `yaourt -S tinc-boot-git`
114127

115128
### Support
116129

@@ -139,8 +152,7 @@ sudo apt install tinc-boot
139152
* Archlinux (Q1 2019) x64
140153
* Manjaro (Q1 2019) x64
141154

142-
Should work on all major linux systems, except generated helpers useful only for systemd-based OS.
143-
155+
Should work on all major linux systems, except generated helpers useful only for systemd-based OS.
144156

145157
# Quick start
146158

@@ -157,7 +169,7 @@ and follow recommendations
157169
### Explanation
158170

159171
* `--standalone` means that it's a first node, no need for keys exchange
160-
* `-a <address>` sets public address of node (if exists); could be used several times
172+
* `-a <address>` sets public address of node (if exists); could be used several times
161173

162174
Will generate all required files under `/etc/tinc/dnet`.
163175

@@ -173,7 +185,7 @@ and follow recommendations
173185

174186
* `--service` generates systemd file to `/etc/systemd/system/tinc-boot-{net}.service`
175187
* `--dir` location of tinc configuration
176-
* `--token` set's authorization token that will be used by clients
188+
* `--token` set's authorization token that will be used by clients
177189

178190
## Create another node and join to net
179191

@@ -204,10 +216,11 @@ Requirements:
204216

205217
1. Tinc for Windows: [download on official site](https://www.tinc-vpn.org/)
206218
2. **Install TAP driver**!:
207-
* Go to `C:\Program Files(x86)\tinc\tap-win64`
208-
* As administrator run `addtap.bat`
209-
3. Rename generated network adapter to the name of the network (`dnet` by-default)
210219

220+
* Go to `C:\Program Files(x86)\tinc\tap-win64`
221+
* As administrator run `addtap.bat`
222+
223+
3. Rename generated network adapter to the name of the network (`dnet` by-default)
211224

212225
Usage:
213226

cmd/tinc-boot/run/main.go

+26
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net"
1010
"net/http"
1111
"os"
12+
"os/exec"
1213
"os/signal"
1314
"path/filepath"
1415
"strconv"
@@ -41,6 +42,7 @@ type Cmd struct {
4142
Join []string `short:"j" long:"join" env:"JOIN" description:"URLs to join to another network"`
4243
JoinRetry time.Duration `long:"join-retry" env:"JOIN_RETRY" description:"Retry interval" default:"15s"`
4344
DiscoveryInterval time.Duration `long:"discovery-interval" env:"DISCOVERY_INTERVAL" description:"Interval between discovery" default:"5s"`
45+
UFW bool `long:"ufw" env:"UFW" description:"Open ports using ufw" `
4446
}
4547

4648
func (cmd Cmd) configDir() string {
@@ -164,6 +166,10 @@ func (cmd *Cmd) Execute([]string) error {
164166
ctx, cancel := signal.NotifyContext(context.Background(), os.Kill, os.Interrupt)
165167
defer cancel()
166168

169+
if cmd.UFW {
170+
cmd.automaticFirewall(ctx, daemonConfig)
171+
}
172+
167173
// configure daemon if needed
168174
if !daemonConfig.Configured() {
169175
log.Println("configuration not exists or invalid - creating a new one")
@@ -337,6 +343,26 @@ func (cmd Cmd) nextTick() (int64, error) {
337343
return tick, ioutil.WriteFile(cmd.clockFile(), []byte(strconv.FormatInt(tick, 10)), 0755)
338344
}
339345

346+
func (cmd Cmd) automaticFirewall(ctx context.Context, dc *daemon.Config) {
347+
dc.Events().Configured.Subscribe(func(configuration daemon.Configuration) {
348+
if err := exec.CommandContext(ctx, "ufw", "allow", fmt.Sprint(configuration.Main.Port)).Run(); err != nil {
349+
log.Println("failed allow incoming requests for traffic:", err)
350+
} else {
351+
log.Println("opened incoming port", fmt.Sprint(configuration.Main.Port))
352+
}
353+
if err := exec.CommandContext(ctx, "ufw", "allow", "from", "any", "to", "any", "port", fmt.Sprint(cmd.Port), "proto", "tcp").Run(); err != nil {
354+
log.Println("failed allow incoming requests on boot port:", err)
355+
} else {
356+
log.Println("opened boot port", fmt.Sprint(cmd.Port))
357+
}
358+
if err := exec.CommandContext(ctx, "ufw", "allow", "in", "on", configuration.Interface, "to", "any", "port", discovery.Port, "proto", "tcp").Run(); err != nil {
359+
log.Println("failed allow internal ports for discovery:", err)
360+
} else {
361+
log.Println("opened discovery port", discovery.Port, "on", configuration.Interface)
362+
}
363+
})
364+
}
365+
340366
func getAllRoutableIPs() ([]string, error) {
341367
addrs, err := net.InterfaceAddrs()
342368
if err != nil {

tincd/daemon/node.go

-26
Original file line numberDiff line numberDiff line change
@@ -436,32 +436,6 @@ func (dm *Daemon) setupNetwork() error {
436436
return nil
437437
}
438438

439-
//
440-
//func (dm *Daemon) reloadRoutes() error {
441-
// hosts, err := dm.config.Hosts()
442-
// if err != nil {
443-
// return fmt.Errorf("read hosts: %w", err)
444-
// }
445-
// if dm.routes == nil {
446-
// dm.routes = make(map[string]bool)
447-
// }
448-
// for hostName, info := range hosts {
449-
// var node config.Node
450-
// if err := config.Unmarshal(info, &node); err != nil {
451-
// return fmt.Errorf("parse node %s config: %w", hostName, err)
452-
// }
453-
// ip := strings.TrimSpace(strings.Split(node.Subnet, "/")[0])
454-
// if dm.routes[ip] {
455-
// continue
456-
// }
457-
// if err := setRouting(dm.deviceName, ip); err != nil {
458-
// return fmt.Errorf("setup routing for host %s: %w", hostName, err)
459-
// }
460-
// dm.routes[ip] = true
461-
// }
462-
// return nil
463-
//}
464-
465439
// event:"Configured"
466440
// event:"Stopped"
467441
type Configuration struct {

tincd/discovery/discovery.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/reddec/tinc-boot/tincd/daemon"
1212
)
1313

14-
const discoveryPort = "18655"
14+
const Port = "18655"
1515

1616
func New(ssd *SSD, config *daemon.Config, interval time.Duration) *Discovery {
1717
return &Discovery{
@@ -31,7 +31,7 @@ type Discovery struct {
3131

3232
func (ds *Discovery) Configured(payload daemon.Configuration) {
3333
ds.httpServer.server = &http.Server{
34-
Addr: fmt.Sprint(payload.IP, ":", discoveryPort),
34+
Addr: fmt.Sprint(payload.IP, ":", Port),
3535
Handler: ds.serverHandler,
3636
}
3737
ds.httpServer.done = make(chan struct{})
@@ -54,14 +54,14 @@ func (ds *Discovery) Stopped(payload daemon.Configuration) {
5454
}
5555

5656
func (ds *Discovery) SubnetAdded(payload daemon.EventSubnetAdded) {
57-
if ds.client.Watch(context.Background(), strings.Split(payload.Peer.Subnet, "/")[0]+":"+discoveryPort) {
57+
if ds.client.Watch(context.Background(), strings.Split(payload.Peer.Subnet, "/")[0]+":"+Port) {
5858
log.Println("watching subnet", payload.Peer.Subnet)
5959
}
6060
}
6161

6262
func (ds *Discovery) SubnetRemoved(payload daemon.EventSubnetRemoved) {
6363
log.Println("forgetting subnet", payload.Peer.Subnet)
64-
ds.client.Forget(strings.Split(payload.Peer.Subnet, "/")[0] + ":" + discoveryPort)
64+
ds.client.Forget(strings.Split(payload.Peer.Subnet, "/")[0] + ":" + Port)
6565
}
6666

6767
func (ds *Discovery) Ready(payload daemon.EventReady) {

0 commit comments

Comments
 (0)