force aes-256-gcm encryption for http/https/tcp protocols.

This commit is contained in:
NNdroid 2023-07-14 11:12:59 +08:00
parent 47bd7b930d
commit 0e83cdbc27
7 changed files with 165 additions and 38 deletions

View File

@ -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

View File

@ -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
View 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
}

View File

@ -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
}
}
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}