URI: 
       ttlstun.go - tlstun - simple go program to add tls support to other listeners
  HTML git clone https://git.parazyd.org/tlstun
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       ttlstun.go (3666B)
       ---
            1 // Copyright (c) 2019-2021 Ivan J. <parazyd@dyne.org>
            2 //
            3 // This file is part of tlstun
            4 //
            5 // This program is free software: you can redistribute it and/or modify
            6 // it under the terms of the GNU Affero General Public License as published by
            7 // the Free Software Foundation, either version 3 of the License, or
            8 // (at your option) any later version.
            9 //
           10 // This program is distributed in the hope that it will be useful,
           11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
           12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
           13 // GNU Affero General Public License for more details.
           14 //
           15 // You should have received a copy of the GNU Affero General Public License
           16 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
           17 package main
           18 
           19 import (
           20         "crypto/tls"
           21         "crypto/x509"
           22         "flag"
           23         "fmt"
           24         "io"
           25         "io/ioutil"
           26         "log"
           27         "net"
           28 )
           29 
           30 var (
           31         cacert  = flag.String("cacert", "ca.pem", "Path for CA certificate file")
           32         cert    = flag.String("cert", "server.pem", "Path for Certificate file")
           33         key     = flag.String("key", "server-key.pem", "Path for Key file")
           34         listen  = flag.String("listen", "127.0.0.1:7443", "Listen address")
           35         forward = flag.String("forward", "127.0.0.1:72", "Forward address")
           36         fwtls   = flag.Bool("forwardtls", false, "Forward using TLS")
           37         client  = flag.Bool("verifyclient", false, "Do client verification")
           38         verbose = flag.Bool("verbose", false, "Verbose mode")
           39         notls   = flag.Bool("notls", false, "Disable TLS and tunnel plain TCP")
           40         tlsver  = flag.Int("tlsver", 13, "TLS version to use (11, 12, 13)")
           41 )
           42 
           43 func tlsConfig(cert, key string) (*tls.Config, error) {
           44         creds, err := tls.LoadX509KeyPair(cert, key)
           45         if err != nil {
           46                 return nil, err
           47         }
           48 
           49         tlscfg := &tls.Config{Certificates: []tls.Certificate{creds}}
           50 
           51         if *client {
           52                 certpool, _ := x509.SystemCertPool()
           53                 if certpool == nil {
           54                         certpool = x509.NewCertPool()
           55                 }
           56                 pem, err := ioutil.ReadFile(*cacert)
           57                 if err != nil {
           58                         return nil, err
           59                 }
           60                 if !certpool.AppendCertsFromPEM(pem) {
           61                         return nil, fmt.Errorf("can't parse client certificate authority")
           62                 }
           63                 tlscfg.ClientCAs = certpool
           64                 tlscfg.ClientAuth = tls.RequireAndVerifyClientCert
           65         }
           66 
           67         switch *tlsver {
           68         case 11:
           69                 tlscfg.MinVersion = tls.VersionTLS11
           70         case 12:
           71                 tlscfg.MinVersion = tls.VersionTLS12
           72         case 13:
           73                 tlscfg.MinVersion = tls.VersionTLS13
           74         default:
           75                 log.Fatal("Unsupported TLS version:", *tlsver)
           76         }
           77 
           78         return tlscfg, nil
           79 }
           80 
           81 func tunnel(conn net.Conn, tlsCfg *tls.Config) {
           82         var client net.Conn
           83         var err error
           84 
           85         if *fwtls {
           86                 client, err = tls.Dial("tcp", *forward, tlsCfg)
           87         } else {
           88                 client, err = net.Dial("tcp", *forward)
           89         }
           90 
           91         if err != nil {
           92                 log.Fatal(err)
           93         }
           94 
           95         if *verbose {
           96                 log.Printf("Connected to localhost for %s\n", conn.RemoteAddr())
           97         }
           98 
           99         go func() {
          100                 defer client.Close()
          101                 defer conn.Close()
          102                 io.Copy(client, conn)
          103         }()
          104         go func() {
          105                 if *verbose {
          106                         defer log.Printf("Closed connection from %s\n", conn.RemoteAddr())
          107                 }
          108                 defer client.Close()
          109                 defer conn.Close()
          110                 io.Copy(conn, client)
          111         }()
          112 }
          113 
          114 func server(tlsCfg *tls.Config) (net.Listener, error) {
          115         t, err := net.Listen("tcp", *listen)
          116         if err != nil {
          117                 return nil, err
          118         }
          119 
          120         if *notls {
          121                 return t, nil
          122         }
          123 
          124         return tls.NewListener(t, tlsCfg), nil
          125 }
          126 
          127 func main() {
          128         flag.Parse()
          129 
          130         var tlsCfg *tls.Config
          131         var err error
          132 
          133         if *notls {
          134                 tlsCfg = nil
          135         } else {
          136                 tlsCfg, err = tlsConfig(*cert, *key)
          137                 if err != nil {
          138                         log.Fatal(err)
          139                 }
          140         }
          141 
          142         tcpsock, err := server(tlsCfg)
          143         if err != nil {
          144                 log.Fatal(err)
          145         }
          146 
          147         for {
          148                 conn, err := tcpsock.Accept()
          149                 if err != nil {
          150                         log.Fatal(err)
          151                 }
          152                 if *verbose {
          153                         log.Printf("Accepted connection from %s\n", conn.RemoteAddr())
          154                 }
          155                 go tunnel(conn, tlsCfg)
          156         }
          157 }