fix crash when prometheus is disable

This commit is contained in:
Shizun Ge 2021-10-27 00:34:18 -07:00
parent de031db282
commit 31cf50b63f
3 changed files with 64 additions and 36 deletions

View file

@ -14,17 +14,23 @@ Clone the repo then build from source:
``` ```
go build . go build .
./endlessh-go ./endlessh-go &
``` ```
Alternatively, you can use the [docker image](https://hub.docker.com/r/shizunge/endlessh-go): Alternatively, you can use the [docker image](https://hub.docker.com/r/shizunge/endlessh-go):
``` ```
sudo docker run -d shizunge/endlessh-go sudo docker run -d -p 2222:2222 shizunge/endlessh-go
``` ```
It listens to port `2222` by default. It listens to port `2222` by default.
Then you can try to connect to the endlessh server. Your SSH client should hang there.
```
ssh -p 2222 localhost
```
If you want log like the [C implementation](https://github.com/skeeto/endlessh), you need to set both CLI arguments `-logtostderr` and `-v=1`, then the log will go to the stderr. You can set different log destinations via CLI arguments. If you want log like the [C implementation](https://github.com/skeeto/endlessh), you need to set both CLI arguments `-logtostderr` and `-v=1`, then the log will go to the stderr. You can set different log destinations via CLI arguments.
## Usage ## Usage

View file

@ -38,19 +38,20 @@ func randStringBytes(n int64) []byte {
} }
type client struct { type client struct {
conn net.Conn conn net.Conn
last time.Time last time.Time
next time.Time next time.Time
start time.Time start time.Time
interval time.Duration interval time.Duration
geoipSupplier string geoipSupplier string
geohash string geohash string
country string country string
location string location string
bytes_sent int bytesSent int
prometheusEnabled bool
} }
func NewClient(conn net.Conn, interval time.Duration, maxClient int64, geoipSupplier string) *client { func NewClient(conn net.Conn, interval time.Duration, maxClient int64, geoipSupplier string, prometheusEnabled bool) *client {
addr := conn.RemoteAddr().(*net.TCPAddr) addr := conn.RemoteAddr().(*net.TCPAddr)
atomic.AddInt64(&numCurrentClients, 1) atomic.AddInt64(&numCurrentClients, 1)
atomic.AddInt64(&numTotalClients, 1) atomic.AddInt64(&numTotalClients, 1)
@ -58,22 +59,25 @@ func NewClient(conn net.Conn, interval time.Duration, maxClient int64, geoipSupp
if err != nil { if err != nil {
glog.Warningf("Failed to obatin the geohash of %v: %v.", addr.IP, err) glog.Warningf("Failed to obatin the geohash of %v: %v.", addr.IP, err)
} }
clientIP.With(prometheus.Labels{ if prometheusEnabled {
"ip": addr.IP.String(), clientIP.With(prometheus.Labels{
"geohash": geohash, "ip": addr.IP.String(),
"country": country, "geohash": geohash,
"location": location}).Inc() "country": country,
"location": location}).Inc()
}
glog.V(1).Infof("ACCEPT host=%v port=%v n=%v/%v\n", addr.IP, addr.Port, numCurrentClients, maxClient) glog.V(1).Infof("ACCEPT host=%v port=%v n=%v/%v\n", addr.IP, addr.Port, numCurrentClients, maxClient)
return &client{ return &client{
conn: conn, conn: conn,
last: time.Now(), last: time.Now(),
next: time.Now().Add(interval), next: time.Now().Add(interval),
start: time.Now(), start: time.Now(),
interval: interval, interval: interval,
geohash: geohash, geohash: geohash,
country: country, country: country,
location: location, location: location,
bytes_sent: 0, bytesSent: 0,
prometheusEnabled: prometheusEnabled,
} }
} }
@ -84,15 +88,17 @@ func (c *client) Send(bannerMaxLength int64) error {
c.last = time.Now() c.last = time.Now()
c.next = time.Now().Add(c.interval) c.next = time.Now().Add(c.interval)
atomic.AddInt64(&numTotalMilliseconds, millisecondsSpent) atomic.AddInt64(&numTotalMilliseconds, millisecondsSpent)
clientSeconds.With(prometheus.Labels{"ip": addr.IP.String()}).Add(float64(millisecondsSpent) / 1000) if c.prometheusEnabled {
clientSeconds.With(prometheus.Labels{"ip": addr.IP.String()}).Add(float64(millisecondsSpent) / 1000)
}
}(c) }(c)
length := rand.Int63n(bannerMaxLength) length := rand.Int63n(bannerMaxLength)
bytes_sent, err := c.conn.Write(randStringBytes(length)) bytesSent, err := c.conn.Write(randStringBytes(length))
if err != nil { if err != nil {
return err return err
} }
c.bytes_sent += bytes_sent c.bytesSent += bytesSent
atomic.AddInt64(&numTotalBytes, int64(bytes_sent)) atomic.AddInt64(&numTotalBytes, int64(bytesSent))
return nil return nil
} }
@ -100,6 +106,6 @@ func (c *client) Close() {
addr := c.conn.RemoteAddr().(*net.TCPAddr) addr := c.conn.RemoteAddr().(*net.TCPAddr)
atomic.AddInt64(&numCurrentClients, -1) atomic.AddInt64(&numCurrentClients, -1)
atomic.AddInt64(&numTotalClientsClosed, 1) atomic.AddInt64(&numTotalClientsClosed, 1)
glog.V(1).Infof("CLOSE host=%v port=%v time=%v bytes=%v\n", addr.IP, addr.Port, time.Now().Sub(c.start).Seconds(), c.bytes_sent) glog.V(1).Infof("CLOSE host=%v port=%v time=%v bytes=%v\n", addr.IP, addr.Port, time.Now().Sub(c.start).Seconds(), c.bytesSent)
c.conn.Close() c.conn.Close()
} }

24
main.go
View file

@ -1,3 +1,19 @@
// Copyright (C) 2021 Shizun Ge
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
package main package main
import ( import (
@ -95,10 +111,10 @@ func main() {
connType := flag.String("conn_type", "tcp", "Connection type. Possible values are tcp, tcp4, tcp6") connType := flag.String("conn_type", "tcp", "Connection type. Possible values are tcp, tcp4, tcp6")
connHost := flag.String("host", "0.0.0.0", "Listening address") connHost := flag.String("host", "0.0.0.0", "Listening address")
connPort := flag.String("port", "2222", "Listening port") connPort := flag.String("port", "2222", "Listening port")
enablePrometheus := flag.Bool("enable_prometheus", false, "Enable prometheus") prometheusEnabled := flag.Bool("enable_prometheus", false, "Enable prometheus")
prometheusPort := flag.String("prometheus_port", "2112", "The port for prometheus") prometheusPort := flag.String("prometheus_port", "2112", "The port for prometheus")
prometheusEntry := flag.String("prometheus_entry", "metrics", "Entry point for prometheus") prometheusEntry := flag.String("prometheus_entry", "metrics", "Entry point for prometheus")
geoipSupplier := flag.String("geoip_supplier", "ip-api", "Supplier to obtain Geohash of IPs. Possible values are \"ip-api\", \"freegeoip\"") geoipSupplier := flag.String("geoip_supplier", "off", "Supplier to obtain Geohash of IPs. Possible values are \"off\", \"ip-api\", \"freegeoip\"")
flag.Usage = func() { flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %v \n", os.Args[0]) fmt.Fprintf(flag.CommandLine.Output(), "Usage of %v \n", os.Args[0])
@ -106,7 +122,7 @@ func main() {
} }
flag.Parse() flag.Parse()
if *enablePrometheus { if *prometheusEnabled {
initPrometheus(*connHost, *prometheusPort, *prometheusEntry) initPrometheus(*connHost, *prometheusPort, *prometheusEntry)
} }
@ -155,7 +171,7 @@ func main() {
for numCurrentClients >= *maxClients { for numCurrentClients >= *maxClients {
time.Sleep(interval) time.Sleep(interval)
} }
clients <- NewClient(conn, interval, *maxClients, *geoipSupplier) clients <- NewClient(conn, interval, *maxClients, *geoipSupplier, *prometheusEnabled)
} }
} }
listener() listener()