Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance Windows TUN mode #63

Closed
wants to merge 3 commits into from
Closed
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
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ language: go
go:
- "1.12.1"
- "1.10.8"
go_import_path: github.com/songgao/water
go_import_path: github.com/chengxuncc/water
install: go get -u golang.org/x/lint/golint
script: make ci

Expand Down
169 changes: 159 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

~~`water/waterutil` has some useful functions to interpret MAC frame headers and IP packet headers. It also contains some constants such as protocol numbers and ethernet frame types.~~

See https://github.com/songgao/packets for functions for parsing various packets.
See https://github.com/chengxuncc/packets for functions for parsing various packets.

## Supported Platforms

Expand All @@ -20,12 +20,12 @@ See https://github.com/songgao/packets for functions for parsing various packets

## Installation
```
go get -u github.com/songgao/water
go get -u github.com/songgao/water/waterutil
go get -u github.com/chengxuncc/water
go get -u github.com/chengxuncc/water/waterutil
```

## Documentation
[http://godoc.org/github.com/songgao/water](http://godoc.org/github.com/songgao/water)
[http://godoc.org/github.com/chengxuncc/water](http://godoc.org/github.com/chengxuncc/water)

## Example

Expand All @@ -37,8 +37,8 @@ package main
import (
"log"

"github.com/songgao/packets/ethernet"
"github.com/songgao/water"
"github.com/chengxuncc/packets/ethernet"
"github.com/chengxuncc/water"
)

func main() {
Expand Down Expand Up @@ -102,7 +102,7 @@ package main
import (
"log"

"github.com/songgao/water"
"github.com/chengxuncc/water"
)

func main() {
Expand Down Expand Up @@ -168,8 +168,8 @@ package main
import (
"log"

"github.com/songgao/packets/ethernet"
"github.com/songgao/water"
"github.com/chengxuncc/packets/ethernet"
"github.com/chengxuncc/water"
)

func main() {
Expand Down Expand Up @@ -230,11 +230,160 @@ If you are going to use multiple TAP devices on the Windows, there is a way to s
PlatformSpecificParams: water.PlatformSpecificParams{
ComponentID: "tap0901",
InterfaceName: "Ethernet 3",
Network: "192.168.1.10/24",
},
})
```

### TUN on Windows:

To use it with windows, you will need to install a [tap driver](https://github.com/OpenVPN/tap-windows6), or [OpenVPN client](https://github.com/OpenVPN/openvpn) for windows.

#### Static mode
```go
package main

import (
"github.com/chengxuncc/water"
"fmt"
"log"
"net"
)

func main() {
config:=water.Config{
DeviceType: water.TUN,
PlatformSpecificParams: water.PlatformSpecificParams{
ComponentID: "tap0901",
Network: "10.1.0.10/24",
}}
ifce, err := water.New(config)
if err != nil {
log.Fatal(err)
}
recvBuf:=make([]byte,1500)

for {
n, err := ifce.Read(recvBuf)
if err != nil {
log.Fatal(err)
}
switch recvBuf[0] >> 4 {
case 4:
fmt.Printf("IPv4 %s -> %s packet %x\n",
net.IPv4(recvBuf[12],recvBuf[13],recvBuf[14],recvBuf[15]),
net.IPv4(recvBuf[16],recvBuf[17],recvBuf[18],recvBuf[19]),
recvBuf[:n])
case 6:
//break to ignore ipv6 packet
ipv6IPsrc:=make(net.IP,16)
ipv6IPdst:=make(net.IP,16)
copy(ipv6IPsrc,recvBuf[8:24])
copy(ipv6IPdst,recvBuf[24:40])
fmt.Printf("IPv6 %s -> %s packet %x\n",
ipv6IPsrc,
ipv6IPdst,
recvBuf[:n],
)
}
}
}
```

Run as Administrator:
```dos
go run main.go
```

Start a new Administrator cmd to assign static IP for device:

```dos
# Replace with your device name, it can be achieved by ifce.Name().
netsh interface ip set address name="Ehternet 2" source=static addr=10.1.0.10 mask=255.255.255.0 gateway=none
```

In oreder to see IPv4 packets, you should ping a IP in network, e.g. 10.1.0.2:
```dos
ping 10.1.0.2
```

You'll see output containing the IPv4 ICMP packets.

#### DHCP mode
```go
package main

import (
"fmt"
"github.com/chengxuncc/water"
"log"
"net"
)

func main() {
// DHCPServer, Dns1 and Dn2 can be empty.
config := water.Config{
DeviceType: water.TUN,
PlatformSpecificParams: water.PlatformSpecificParams{
ComponentID: "tap0901",
Network: "10.1.0.10/24",
IsDHCP: true,
DHCPServer: "10.1.0.1",
DNS1: "8.8.8.8",
DNS2: "1.1.1.1",
}}
ifce, err := water.New(config)
if err != nil {
log.Fatal(err)
}
recvBuf := make([]byte, 1500)

for {
n, err := ifce.Read(recvBuf)
if err != nil {
log.Fatal(err)
}
switch recvBuf[0] >> 4 {
case 4:
fmt.Printf("IPv4 [%s] -> [%s] packet [%x]\n",
net.IPv4(recvBuf[12], recvBuf[13], recvBuf[14], recvBuf[15]),
net.IPv4(recvBuf[16], recvBuf[17], recvBuf[18], recvBuf[19]),
recvBuf[:n])
case 6:
//break to ignore ipv6 packet
ipv6IPsrc := make(net.IP, 16)
ipv6IPdst := make(net.IP, 16)
copy(ipv6IPsrc, recvBuf[8:24])
copy(ipv6IPdst, recvBuf[24:40])
fmt.Printf("IPv6 [%s] -> [%s] packet [%x]\n",
ipv6IPsrc,
ipv6IPdst,
recvBuf[:n],
)
}
}
}
```

Run as Administrator:
```dos
go run main.go
```

Start a new Administrator cmd to configure device work on DHCP mode:

```dos
# Replace with your device name, it can be achieved by ifce.Name().
netsh interface ip set address "Ehternet 2" dhcp
netsh interface ip set dns "Ehteret 2" dhcp
```

In oreder to see IPv4 packets, you should ping a IP in network, e.g. 10.1.0.2:
```dos
ping 10.1.0.2
```

You'll see output containing the IPv4 ICMP packets.

## TODO
* tuntaposx for TAP on Darwin

Expand Down
2 changes: 1 addition & 1 deletion ipv4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"testing"
"time"

"github.com/songgao/water/waterutil"
"github.com/chengxuncc/water/waterutil"
)

const BUFFERSIZE = 1522
Expand Down
25 changes: 23 additions & 2 deletions ipv4_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os/exec"
"strings"
"testing"
"time"
)

func startPing(t *testing.T, dst net.IP, _ bool) {
Expand All @@ -21,8 +22,8 @@ func setupIfce(t *testing.T, ipNet net.IPNet, dev string) {
args[6] = fmt.Sprintf("addr=%s", ipNet.IP)
args[7] = fmt.Sprintf("mask=%d.%d.%d.%d", ipNet.Mask[0], ipNet.Mask[1], ipNet.Mask[2], ipNet.Mask[3])
cmd := exec.Command("netsh", args...)
if err := cmd.Run(); err != nil {
t.Fatal(err)
if output, err := cmd.Output(); err != nil {
t.Fatal(string(output), err.Error())
}
}

Expand Down Expand Up @@ -52,3 +53,23 @@ func TestBroadcastTAP(t *testing.T) {

waitForPingOrBust(t, true, true, self, brd, dataCh, errCh)
}

func TestDHCP(t *testing.T) {
config := Config{
DeviceType: TUN,
PlatformSpecificParams: PlatformSpecificParams{
ComponentID: "tap0901",
Network: "10.1.0.10/24",
IsDHCP: true,
DHCPServer: "10.1.0.1",
DNS1: "1.1.1.1",
DNS2: "8.8.8.8",
}}
ifce, err := New(config)
if err != nil {
t.Fatal(err)
}
fmt.Println("name:",ifce.Name())
time.Sleep(time.Second*60)

}
15 changes: 8 additions & 7 deletions params_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,19 @@ type PlatformSpecificParams struct {
// net.ParseCIDR() to parse this string into LocalIP, RemoteNetaddr,
// RemoteNetmask. The underlying driver will need those to generate ARP
// response to Windows kernel, to emulate an TUN interface.
// Please note that it cannot perceive the IP changes caused by DHCP, user
// configuration to the adapter and etc,. If IP changed, please reconfigure
// the adapter using syscall, just like openDev().
// For detail, please refer
// https://github.com/OpenVPN/tap-windows6/blob/master/src/device.c#L431
// and https://github.com/songgao/water/pull/13#issuecomment-270341777
// Please note that Network must be same with IP and Mask that configured manually.
Network string

DHCPServer string
DNS1 string
DNS2 string
// Configure IP and DNS by device DHCP
IsDHCP bool
}

func defaultPlatformSpecificParams() PlatformSpecificParams {
return PlatformSpecificParams{
ComponentID: "tap0901",
Network: "192.168.1.10/24",
Network: "10.1.0.10/24",
}
}
Loading