mirror of
https://github.com/net-byte/vtun
synced 2024-03-14 10:50:03 +08:00
force aes-256-gcm encryption for http/https/tcp protocols.
This commit is contained in:
parent
47bd7b930d
commit
0e83cdbc27
@ -20,8 +20,9 @@ A simple VPN written in Go.
|
||||
* VPN over utls
|
||||
* VPN over dtls
|
||||
* VPN over h2
|
||||
* VPN over http
|
||||
* VPN over tcp
|
||||
* VPN over http (Use aes-256-gcm encryption by default)
|
||||
* VPN over tcp (Use aes-256-gcm encryption by default)
|
||||
* VPN over https (Use aes-256-gcm encryption by default)
|
||||
# Usage
|
||||
|
||||
```
|
||||
@ -49,7 +50,7 @@ Usage of vtun:
|
||||
-obfs
|
||||
enable data obfuscation
|
||||
-p string
|
||||
protocol udp/tls/grpc/quic/utls/dtls/h2/http/tcp/ws/wss (default "udp")
|
||||
protocol udp/tls/grpc/quic/utls/dtls/h2/http/tcp/https/ws/wss (default "udp")
|
||||
-path string
|
||||
websocket path (default "/freedom")
|
||||
-privatekey string
|
||||
|
@ -22,6 +22,7 @@
|
||||
* 支持h2
|
||||
* 支持http
|
||||
* 支持tcp
|
||||
* 支持https
|
||||
|
||||
# 用法
|
||||
|
||||
@ -50,7 +51,7 @@ Usage of vtun:
|
||||
-obfs
|
||||
enable data obfuscation
|
||||
-p string
|
||||
protocol udp/tls/grpc/quic/utls/dtls/h2/http/tcp/ws/wss (default "udp")
|
||||
protocol udp/tls/grpc/quic/utls/dtls/h2/http/tcp/https/ws/wss (default "udp")
|
||||
-path string
|
||||
websocket path (default "/freedom")
|
||||
-privatekey string
|
||||
|
63
common/xcrypto/xcrypto.go
Normal file
63
common/xcrypto/xcrypto.go
Normal file
@ -0,0 +1,63 @@
|
||||
package xcrypto
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
)
|
||||
|
||||
type XCrypto struct {
|
||||
Key []byte
|
||||
Nonce []byte
|
||||
aesGcm cipher.AEAD
|
||||
}
|
||||
|
||||
func (x *XCrypto) Load(key string) {
|
||||
x.LoadKey(key)
|
||||
x.LoadNonce(key)
|
||||
}
|
||||
|
||||
func (x *XCrypto) LoadKey(key string) {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(key))
|
||||
x.Key = h.Sum(nil)
|
||||
}
|
||||
|
||||
func (x *XCrypto) LoadNonce(key string) {
|
||||
h := sha1.New()
|
||||
h.Write([]byte(key))
|
||||
b := h.Sum(nil)
|
||||
x.Nonce = b[:12]
|
||||
}
|
||||
|
||||
func (x *XCrypto) Init(key string) error {
|
||||
x.Load(key)
|
||||
return x.init()
|
||||
}
|
||||
|
||||
func (x *XCrypto) init() error {
|
||||
block, err := aes.NewCipher(x.Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
aesGcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
x.aesGcm = aesGcm
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *XCrypto) Encode(pl []byte) ([]byte, error) {
|
||||
ci := x.aesGcm.Seal(nil, x.Nonce, pl, nil)
|
||||
return ci, nil
|
||||
}
|
||||
|
||||
func (x *XCrypto) Decode(ci []byte) ([]byte, error) {
|
||||
pl, err := x.aesGcm.Open(nil, x.Nonce, ci, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pl, nil
|
||||
}
|
@ -3,11 +3,10 @@ package h1
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/net-byte/vtun/common/xcrypto"
|
||||
"github.com/net-byte/vtun/common/xproto"
|
||||
"log"
|
||||
"net"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
@ -41,7 +40,6 @@ func StartClient(iFace *water.Interface, config config.Config) {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
continue
|
||||
}
|
||||
//go checkH1SessionAlive(conn, config)
|
||||
cache.GetCache().Set("conn", conn, 24*time.Hour)
|
||||
h1ToTun(config, conn, iFace)
|
||||
cache.GetCache().Delete("conn")
|
||||
@ -71,10 +69,16 @@ func handshake(config config.Config, conn net.Conn) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// tunToH1 sends packets from tun to tls
|
||||
// tunToH1 sends packets from tun to h1
|
||||
func tunToH1(config config.Config, iFace *water.Interface) {
|
||||
authKey := xproto.ParseAuthKeyFromString(config.Key)
|
||||
buffer := make([]byte, config.BufferSize)
|
||||
xp := &xcrypto.XCrypto{}
|
||||
err := xp.Init(config.Key)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
return
|
||||
}
|
||||
for {
|
||||
n, err := iFace.Read(buffer)
|
||||
if err != nil {
|
||||
@ -86,6 +90,11 @@ func tunToH1(config config.Config, iFace *water.Interface) {
|
||||
if config.Obfs {
|
||||
b = cipher.XOR(b)
|
||||
}
|
||||
b, err = xp.Encode(b)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
break
|
||||
}
|
||||
if config.Compress {
|
||||
b = snappy.Encode(nil, b)
|
||||
}
|
||||
@ -112,11 +121,17 @@ func tunToH1(config config.Config, iFace *water.Interface) {
|
||||
}
|
||||
}
|
||||
|
||||
// h1ToTun sends packets from tls to tun
|
||||
// h1ToTun sends packets from h1 to tun
|
||||
func h1ToTun(config config.Config, conn net.Conn, iFace *water.Interface) {
|
||||
defer conn.Close()
|
||||
header := make([]byte, xproto.ServerSendPacketHeaderLength)
|
||||
packet := make([]byte, config.BufferSize)
|
||||
xp := &xcrypto.XCrypto{}
|
||||
err := xp.Init(config.Key)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
return
|
||||
}
|
||||
for {
|
||||
n, err := conn.Read(header)
|
||||
if err != nil {
|
||||
@ -149,6 +164,11 @@ func h1ToTun(config config.Config, conn net.Conn, iFace *water.Interface) {
|
||||
break
|
||||
}
|
||||
}
|
||||
b, err = xp.Decode(b)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
break
|
||||
}
|
||||
if config.Obfs {
|
||||
b = cipher.XOR(b)
|
||||
}
|
||||
@ -160,26 +180,3 @@ func h1ToTun(config config.Config, conn net.Conn, iFace *water.Interface) {
|
||||
counter.IncrReadBytes(n)
|
||||
}
|
||||
}
|
||||
|
||||
func checkH1SessionAlive(conn net.Conn, config config.Config) {
|
||||
os := runtime.GOOS
|
||||
defer conn.Close()
|
||||
for {
|
||||
if os == "windows" {
|
||||
result := netutil.ExecCmd("ping", "-n", "2", "-l", "21", "-w", "1200", config.ServerIP)
|
||||
if strings.Contains(result, `100%`) {
|
||||
netutil.PrintErr(errors.New("ping server failed, reconnecting"), config.Verbose)
|
||||
break
|
||||
}
|
||||
continue
|
||||
} else if os == "linux" || os == "darwin" {
|
||||
result := netutil.ExecCmd("ping", "-c", "2", "-s", "21", "-w", "1200", config.ServerIP)
|
||||
// macos return "100.0% packet loss", linux return "100% packet loss"
|
||||
if strings.Contains(result, `100.0%`) || strings.Contains(result, `100%`) {
|
||||
netutil.PrintErr(errors.New("ping server failed, reconnecting"), config.Verbose)
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/net-byte/vtun/common/config"
|
||||
"github.com/net-byte/vtun/common/counter"
|
||||
"github.com/net-byte/vtun/common/netutil"
|
||||
"github.com/net-byte/vtun/common/xcrypto"
|
||||
"github.com/net-byte/vtun/common/xproto"
|
||||
"github.com/net-byte/water"
|
||||
"log"
|
||||
@ -60,9 +61,15 @@ func StartServer(iFace *water.Interface, config config.Config) {
|
||||
}
|
||||
}
|
||||
|
||||
// toClient sends packets from iFace to conn
|
||||
// toClient sends packets from tun to h1
|
||||
func toClient(config config.Config, iFace *water.Interface) {
|
||||
buffer := make([]byte, config.BufferSize)
|
||||
xp := &xcrypto.XCrypto{}
|
||||
err := xp.Init(config.Key)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
return
|
||||
}
|
||||
for {
|
||||
n, err := iFace.Read(buffer)
|
||||
if err != nil {
|
||||
@ -75,6 +82,11 @@ func toClient(config config.Config, iFace *water.Interface) {
|
||||
if config.Obfs {
|
||||
b = cipher.XOR(b)
|
||||
}
|
||||
b, err = xp.Encode(b)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
break
|
||||
}
|
||||
if config.Compress {
|
||||
b = snappy.Encode(nil, b)
|
||||
}
|
||||
@ -103,13 +115,19 @@ func toClient(config config.Config, iFace *water.Interface) {
|
||||
}
|
||||
}
|
||||
|
||||
// toServer sends packets from conn to iFace
|
||||
// toServer sends packets from h1 to tun
|
||||
func toServer(config config.Config, conn net.Conn, iFace *water.Interface) {
|
||||
defer conn.Close()
|
||||
handshake := make([]byte, xproto.ClientHandshakePacketLength)
|
||||
header := make([]byte, xproto.ClientSendPacketHeaderLength)
|
||||
packet := make([]byte, config.BufferSize)
|
||||
authKey := xproto.ParseAuthKeyFromString(config.Key)
|
||||
xp := &xcrypto.XCrypto{}
|
||||
err := xp.Init(config.Key)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
return
|
||||
}
|
||||
n, err := conn.Read(handshake)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
@ -166,6 +184,11 @@ func toServer(config config.Config, conn net.Conn, iFace *water.Interface) {
|
||||
break
|
||||
}
|
||||
}
|
||||
b, err = xp.Decode(b)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
break
|
||||
}
|
||||
if config.Obfs {
|
||||
b = cipher.XOR(b)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package tcp
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/net-byte/vtun/common/xcrypto"
|
||||
"github.com/net-byte/vtun/common/xproto"
|
||||
"log"
|
||||
"net"
|
||||
@ -66,6 +67,12 @@ func handshake(config config.Config, conn net.Conn) error {
|
||||
func tunToTcp(config config.Config, iFace *water.Interface) {
|
||||
authKey := xproto.ParseAuthKeyFromString(config.Key)
|
||||
buffer := make([]byte, config.BufferSize)
|
||||
xp := &xcrypto.XCrypto{}
|
||||
err := xp.Init(config.Key)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
return
|
||||
}
|
||||
for {
|
||||
n, err := iFace.Read(buffer)
|
||||
if err != nil {
|
||||
@ -77,6 +84,11 @@ func tunToTcp(config config.Config, iFace *water.Interface) {
|
||||
if config.Obfs {
|
||||
b = cipher.XOR(b)
|
||||
}
|
||||
b, err = xp.Encode(b)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
break
|
||||
}
|
||||
if config.Compress {
|
||||
b = snappy.Encode(nil, b)
|
||||
}
|
||||
@ -108,6 +120,12 @@ func tcpToTun(config config.Config, conn net.Conn, iFace *water.Interface) {
|
||||
defer conn.Close()
|
||||
header := make([]byte, xproto.ServerSendPacketHeaderLength)
|
||||
packet := make([]byte, config.BufferSize)
|
||||
xp := &xcrypto.XCrypto{}
|
||||
err := xp.Init(config.Key)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
return
|
||||
}
|
||||
for {
|
||||
n, err := conn.Read(header)
|
||||
if err != nil {
|
||||
@ -140,6 +158,11 @@ func tcpToTun(config config.Config, conn net.Conn, iFace *water.Interface) {
|
||||
break
|
||||
}
|
||||
}
|
||||
b, err = xp.Decode(b)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
break
|
||||
}
|
||||
if config.Obfs {
|
||||
b = cipher.XOR(b)
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/net-byte/vtun/common/config"
|
||||
"github.com/net-byte/vtun/common/counter"
|
||||
"github.com/net-byte/vtun/common/netutil"
|
||||
"github.com/net-byte/vtun/common/xcrypto"
|
||||
"github.com/net-byte/vtun/common/xproto"
|
||||
"github.com/net-byte/water"
|
||||
"log"
|
||||
@ -40,6 +41,12 @@ func StartServer(iFace *water.Interface, config config.Config) {
|
||||
// toClient sends packets from iFace to conn
|
||||
func toClient(config config.Config, iFace *water.Interface) {
|
||||
buffer := make([]byte, config.BufferSize)
|
||||
xp := &xcrypto.XCrypto{}
|
||||
err := xp.Init(config.Key)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
return
|
||||
}
|
||||
for {
|
||||
n, err := iFace.Read(buffer)
|
||||
if err != nil {
|
||||
@ -55,6 +62,11 @@ func toClient(config config.Config, iFace *water.Interface) {
|
||||
if config.Obfs {
|
||||
b = cipher.XOR(b)
|
||||
}
|
||||
b, err = xp.Encode(b)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
break
|
||||
}
|
||||
if config.Compress {
|
||||
b = snappy.Encode(nil, b)
|
||||
}
|
||||
@ -67,7 +79,6 @@ func toClient(config config.Config, iFace *water.Interface) {
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
cache.GetCache().Delete(key)
|
||||
//fmt.Printf("del %s %v\r\n", key, conn)
|
||||
conn.Close()
|
||||
continue
|
||||
}
|
||||
@ -78,7 +89,6 @@ func toClient(config config.Config, iFace *water.Interface) {
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
cache.GetCache().Delete(key)
|
||||
//fmt.Printf("del %s %v\r\n", key, conn)
|
||||
conn.Close()
|
||||
continue
|
||||
}
|
||||
@ -86,8 +96,6 @@ func toClient(config config.Config, iFace *water.Interface) {
|
||||
fmt.Printf("conn-p write: %v\n", b)
|
||||
}
|
||||
counter.IncrWrittenBytes(n)
|
||||
//} else {
|
||||
// fmt.Printf("%s not ok!!!\n", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,6 +108,12 @@ func toServer(config config.Config, conn net.Conn, iFace *water.Interface) {
|
||||
header := make([]byte, xproto.ClientSendPacketHeaderLength)
|
||||
packet := make([]byte, config.BufferSize)
|
||||
authKey := xproto.ParseAuthKeyFromString(config.Key)
|
||||
xp := &xcrypto.XCrypto{}
|
||||
err := xp.Init(config.Key)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
return
|
||||
}
|
||||
n, err := conn.Read(handshake)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
@ -165,6 +179,11 @@ func toServer(config config.Config, conn net.Conn, iFace *water.Interface) {
|
||||
break
|
||||
}
|
||||
}
|
||||
b, err = xp.Decode(b)
|
||||
if err != nil {
|
||||
netutil.PrintErr(err, config.Verbose)
|
||||
break
|
||||
}
|
||||
if config.Obfs {
|
||||
b = cipher.XOR(b)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user