Skip to content

Commit

Permalink
[create] 1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
lazydog28 committed Aug 20, 2024
0 parents commit c7fcee3
Show file tree
Hide file tree
Showing 11 changed files with 798 additions and 0 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go

name: Go

on:
workflow_dispatch:
inputs:
VERSION:
description: '请输入版本号'
required: true
permissions:
contents: write
jobs:
build:
strategy:
matrix:
goos: [ linux, darwin, windows ]
goarch: [ amd64 ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.20'

- name: Build
# 编译文件 文件名称为 dist/${{ matrix.goos }}_${{ matrix.goarch }}_
run: |
if [[ ${{ matrix.goos }} == "windows" ]]; then
go build -v -ldflags "-s -w" -trimpath -a -o dist/natter_${{ matrix.goos }}_${{ matrix.goarch }}.exe
else
go build -v -ldflags "-s -w" -trimpath -a -o dist/natter_${{ matrix.goos }}_${{ matrix.goarch }}
fi
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: 0

- name: Release
uses: softprops/action-gh-release@v2
with:
name: ${{ github.event.inputs.VERSION }}
body: ${{ github.event.inputs.VERSION }}
draft: true
fail_on_unmatched_files: true
files: |
./dist/*
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module natter

go 1.20
49 changes: 49 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package main

import (
"context"
"flag"
"fmt"
"natter/natter"
"net"
"os"
"os/signal"
"syscall"
)

var logger = natter.GetLogger()

func main() {
// 捕获异常
defer func() {
if err := recover(); err != nil {
logger.Error(err.(error).Error())
}
// 任意键退出
fmt.Println("按回车键退出...")
var input string
_, _ = fmt.Scanln(&input)
}()
// 读取 命令行 参数
var addr string
flag.StringVar(&addr, "f", "127.0.0.1:80", "绑定公网地址至指定地址")
flag.Parse()
forwardAddr, err := net.ResolveTCPAddr("tcp4", addr)
if err != nil {
panic(err)
}
ctx, cancel := context.WithCancel(context.Background())
err = natter.Start(ctx, forwardAddr)
if err != nil {
panic(err)
}
// 等待系统中断信号
// 创建一个 channel 用于接收信号
c := make(chan os.Signal, 1)
// 注册信号处理器
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
// 阻塞直到有信号传入
<-c
fmt.Println("程序退出...")
cancel()
}
123 changes: 123 additions & 0 deletions natter/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package natter

import "strings"

var stunList = []string{
"stun.studio-link.de:3478",
"stun.jabber.dk:3478",
"stun.verbo.be:3478",
"stun.technosens.fr:3478",
"stun.sipnet.com:3478",
"stun.alpirsbacher.de:3478",
"stun.healthtap.com:3478",
"stun.ru-brides.com:3478",
"stun.zepter.ru:3478",
"stun.sip.us:3478",
"stun.flashdance.cx:3478",
"stun.ttmath.org:3478",
"stun.schulinformatik.at:3478",
"stun.romaaeterna.nl:3478",
"stun.ukh.de:3478",
"stun.annatel.net:3478",
"stun.poetamatusel.org:3478",
"stun.bridesbay.com:3478",
"stun.sewan.fr:3478",
"stun.myspeciality.com:3478",
"stun.sonetel.com:3478",
"stun.geesthacht.de:3478",
"stunserver2024.stunprotocol.org:3478",
"stun.allflac.com:3478",
"stun.lleida.net:3478",
"stun.zentauron.de:3478",
"stun.3deluxe.de:3478",
"stun.frozenmountain.com:3478",
"stun.peeters.com:3478",
"stun.godatenow.com:3478",
"stun.galeriemagnet.at:3478",
"stun.fmo.de:3478",
"stun.bitburger.de:3478",
"stun.vavadating.com:3478",
"stun.bethesda.net:3478",
"stun.acronis.com:3478",
"stun.sonetel.net:3478",
"stun.peethultra.be:3478",
"stun.nextcloud.com:3478",
"stun.yesdates.com:3478",
"stun.ncic.com:3478",
"stun.antisip.com:3478",
"stun.nextcloud.com:443",
"stun.pure-ip.com:3478",
"stun.siplogin.de:3478",
"stun.baltmannsweiler.de:3478",
"stun.graftlab.com:3478",
"stun.lebendigefluesse.at:3478",
"stun.oncloud7.ch:3478",
"stun.kaseya.com:3478",
"stun.skydrone.aero:3478",
"stun.files.fm:3478",
"stun.telnyx.com:3478",
"stun.moonlight-stream.org:3478",
"stun.symonics.com:3478",
"stun.cibercloud.com.br:3478",
"stun.1cbit.ru:3478",
"stun.tula.nu:3478",
"stun.sipnet.net:3478",
"stun.genymotion.com:3478",
"stun.business-isp.nl:3478",
"stun.jowisoftware.de:3478",
"stun.ringostat.com:3478",
"stun.romancecompass.com:3478",
"stun.synergiejobs.be:3478",
"stun.ipfire.org:3478",
"stun.dcalling.de:3478",
"stun.radiojar.com:3478",
"stun.root-1.de:3478",
"stun.signalwire.com:3478",
"stun.f.haeder.net:3478",
"stun.engineeredarts.co.uk:3478",
"stun.finsterwalder.com:3478",
"stun.voipia.net:3478",
"stun.hot-chilli.net:3478",
"stun.mixvoip.com:3478",
"stun.isp.net.au:3478",
"stun.avigora.fr:3478",
"stun.foad.me.uk:3478",
"stun.meetwife.com:3478",
"stun.linuxtrent.it:3478",
"stun.kanojo.de:3478",
"stun.m-online.net:3478",
"stun.3wayint.com:3478",
"stun.stochastix.de:3478",
"stun.piratenbrandenburg.de:3478",
"stun.thinkrosystem.com:3478",
"stun.fitauto.ru:3478",
"stun.threema.ch:3478",
"stun.vomessen.de:3478",
"stun.heeds.eu:3478",
"stun.uabrides.com:3478",
"stun.imp.ch:3478",
"stun.freeswitch.org:3478",
"stun.voipgate.com:3478",
"stun.voip.blackberry.com:3478",
"stun.sipnet.ru:3478",
"stun.sylaps.com:3478",
"stun.grazertrinkwasseringefahr.at:3478",
"stun.siptrunk.com:3478",
"stun.lovense.com:3478",
"stun.streamnow.ch:3478",
"stun.cellmail.com:3478",
"stun.nanocosmos.de:3478",
"stun.atagverwarming.nl:3478",
"stun.axialys.net:3478",
}

const keepLiveSrv = "www.baidu.com:80"

func init() {
// 遍历 stunList 列表 解析服务器地址和端口,默认端口为3478
for i, v := range stunList {
if !strings.Contains(v, ":") {
stunList[i] = v + ":3478"
}
}
}
138 changes: 138 additions & 0 deletions natter/forwardSocket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package natter

import (
"fmt"
"io"
"net"
"sync"
"time"
)

// ForwardSocket 是一个用于转发 TCP 流量的结构体
type ForwardSocket struct {
active bool `comment:"是否激活"`
buffSize int `comment:"缓冲区大小"`
LAddr *net.TCPAddr `comment:"本地地址"`
}

// NewForwardSocket 创建一个 ForwardSocket 实例
func NewForwardSocket(lAddr *net.TCPAddr) *ForwardSocket {
return &ForwardSocket{
active: false,
buffSize: 8192,
LAddr: lAddr,
}
}

// StartForward 启动一个 ForwardSocket 实例
func (fs *ForwardSocket) StartForward(forwardAddr *net.TCPAddr) error {
if fs.LAddr.String() == forwardAddr.String() {
return fmt.Errorf("转发地址与监听地址不能为同一地址 %s", fs.LAddr.String())
}
conn, err := net.Dial("tcp4", forwardAddr.String())
if err != nil {
return fmt.Errorf("转发地址无法联通: %s", err.Error())
}
c(conn)

logger.Info(fmt.Sprintf("开始端口转发 %s 到 %s", fs.LAddr.String(), forwardAddr.String()))

fs.active = true
go fs.socketTCPListen(fs.LAddr.Port, forwardAddr)
return nil
}

// socketTCPListen 启动一个 TCP 监听
func (fs *ForwardSocket) socketTCPListen(listenPort int, forwardAddr *net.TCPAddr) {
listenerAddr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf(":%d", listenPort))
if err != nil {
logger.Error(fmt.Sprintf("解析监听地址失败: %s", err.Error()))
return
}
listener, err := net.ListenTCP("tcp", listenerAddr)
if err != nil {
logger.Error(fmt.Sprintf("启动监听失败: %s", err.Error()))
return
}
logger.Debug(fmt.Sprintf("开始监听端口: %s", listenerAddr.String()))

defer c(listener)
for fs.active {
conn, err := listener.Accept()
if err != nil {
logger.Error(fmt.Sprintf("监听端口数据读取失败,退出监听: %s", err.Error()))
return
}
logger.Debug(fmt.Sprintf("接收到新连接: %s", conn.RemoteAddr().String()))
go fs.socketTCPForward(conn, forwardAddr)
}
}

// socketTCPForward 转发 TCP 数据
func (fs *ForwardSocket) socketTCPForward(conn net.Conn, forwardAddr *net.TCPAddr) {
defer c(conn)
outboundConn, err := net.Dial("tcp", forwardAddr.String())
if err != nil {
logger.Error(fmt.Sprintf("转发端口连接失败: %s", err.Error()))
return
}
defer c(outboundConn)
var wg sync.WaitGroup
wg.Add(2)
go fs.copyData(conn, outboundConn, &wg)
go fs.copyData(outboundConn, conn, &wg)
wg.Wait()
}

// copyData 复制数据
func (fs *ForwardSocket) copyData(src net.Conn, dst net.Conn, wg *sync.WaitGroup) {
defer wg.Done()
buf := make([]byte, fs.buffSize)
for {
n, err := src.Read(buf)
if err != nil {
return
}
if n > 0 {
_, err = dst.Write(buf[:n])
if err != nil {
return
}
}
}
}

// StopForward 停止转发
func (fs *ForwardSocket) StopForward() {
fs.active = false
}

// KeepAlive 用于保持连接
func (fs *ForwardSocket) KeepAlive() {
dialer := &net.Dialer{
LocalAddr: fs.LAddr,
}
timer := time.NewTimer(5 * time.Second)

for fs.active {
logger.Debug("keepAlive")
<-timer.C
conn, err := dialer.Dial("tcp4", keepLiveSrv)
logger.Debug("keepAlive")
if err != nil {
logger.Error(fmt.Sprintf("保活请求失败: %s\n", err.Error()))
continue
}
// 设置超时时间 3s
_ = conn.SetReadDeadline(time.Now().Add(3 * time.Second))
_, _ = conn.Write([]byte("HEAD /natter-keep-alive HTTP/1.1\r\n" +
"Host: www.baidu.com\r\n" +
"User-Agent: curl/8.0.0 (Natter)\r\n" +
"Accept: */*\r\n" +
"Connection: keep-alive\r\n" +
"\r\n"))
_, _ = io.ReadAll(conn)
_ = conn.Close()
timer.Reset(5 * time.Second)
}
}
Loading

0 comments on commit c7fcee3

Please sign in to comment.