├── Dockerfile ├── .gitignore ├── README.md ├── LICENSE └── main.go /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:onbuild 2 | EXPOSE 2203 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | udpproxy 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # udpproxy 2 | 3 | A simple UDP Proxy Server in Golang. 4 | 5 | ## Features 6 | - [x] one source, multi target based on copy. 7 | 8 | ## Build 9 | * docker: `docker build -t udpproxy .` 10 | * `go build main.go -o udpproxy` 11 | 12 | ## Run 13 | * `--source`: data source, default source is `:2203`. 14 | * `--target`: data target, e.g. `ip:port`. 15 | * `--quiet`: whether to print logging info or not. 16 | * `--buffer`: default is 10240. 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Bob Liu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net" 5 | "os" 6 | "strings" 7 | 8 | log "github.com/Sirupsen/logrus" 9 | "github.com/jessevdk/go-flags" 10 | ) 11 | 12 | var opts struct { 13 | Source string `long:"source" default:":2203" description:"Source port to listen on"` 14 | Target []string `long:"target" description:"Target address to forward to"` 15 | Quiet bool `long:"quiet" description:"whether to print logging info or not"` 16 | Buffer int `long:"buffer" default:"10240" description:"max buffer size for the socket io"` 17 | } 18 | 19 | func main() { 20 | _, err := flags.Parse(&opts) 21 | if err != nil { 22 | if !strings.Contains(err.Error(), "Usage") { 23 | log.Printf("error: %v\n", err.Error()) 24 | os.Exit(1) 25 | } else { 26 | // log.Printf("%v\n", err.Error()) 27 | os.Exit(0) 28 | } 29 | } 30 | 31 | if opts.Quiet { 32 | log.SetLevel(log.WarnLevel) 33 | } 34 | 35 | sourceAddr, err := net.ResolveUDPAddr("udp", opts.Source) 36 | if err != nil { 37 | log.WithError(err).Fatal("Could not resolve source address:", opts.Source) 38 | return 39 | } 40 | 41 | var targetAddr []*net.UDPAddr 42 | for _, v := range opts.Target { 43 | addr, err := net.ResolveUDPAddr("udp", v) 44 | if err != nil { 45 | log.WithError(err).Fatal("Could not resolve target address:", v) 46 | return 47 | } 48 | targetAddr = append(targetAddr, addr) 49 | } 50 | 51 | sourceConn, err := net.ListenUDP("udp", sourceAddr) 52 | if err != nil { 53 | log.WithError(err).Fatal("Could not listen on address:", opts.Source) 54 | return 55 | } 56 | 57 | defer sourceConn.Close() 58 | 59 | var targetConn []*net.UDPConn 60 | for _, v := range targetAddr { 61 | conn, err := net.DialUDP("udp", nil, v) 62 | if err != nil { 63 | log.WithError(err).Fatal("Could not connect to target address:", v) 64 | return 65 | } 66 | 67 | defer conn.Close() 68 | targetConn = append(targetConn, conn) 69 | } 70 | 71 | log.Printf(">> Starting udpproxy, Source at %v, Target at %v...", opts.Source, opts.Target) 72 | 73 | for { 74 | b := make([]byte, opts.Buffer) 75 | n, addr, err := sourceConn.ReadFromUDP(b) 76 | 77 | if err != nil { 78 | log.WithError(err).Error("Could not receive a packet") 79 | continue 80 | } 81 | 82 | log.WithField("addr", addr.String()).WithField("bytes", n).WithField("content", string(b)).Info("Packet received") 83 | for _, v := range targetConn { 84 | if _, err := v.Write(b[0:n]); err != nil { 85 | log.WithError(err).Warn("Could not forward packet.") 86 | } 87 | } 88 | } 89 | } 90 | --------------------------------------------------------------------------------