Skip to content

Commit 8e1ece2

Browse files
authored
#36 attempt to fix api login auth issue (#38)
* #36 attempt to fix api login auth issue * update release version number
1 parent dcaef1a commit 8e1ece2

File tree

5 files changed

+76
-10
lines changed

5 files changed

+76
-10
lines changed

.circleci/config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ version: 2
22
jobs:
33
build:
44
docker:
5-
- image: circleci/golang:1.10.4-stretch
5+
- image: circleci/golang:1.12.4-stretch
66
working_directory: /go/src/github.com/nshttpd/mikrotik-exporter
77
branches:
88
only:
@@ -11,5 +11,5 @@ jobs:
1111
steps:
1212
- checkout
1313
- setup_remote_docker:
14-
version: 18.05.0-ce
14+
version: 18.06.0-ce
1515
- run: make dockerhub

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@
2020
debug
2121

2222
mikrotik-exporter
23+
test-config.yml

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.0.7-DEVEL
1+
1.0.7

collector/collector.go

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package collector
22

33
import (
4+
"crypto/md5"
45
"crypto/tls"
6+
"encoding/hex"
7+
"errors"
8+
"fmt"
9+
"io"
10+
"net"
511
"sync"
612
"time"
713

@@ -206,12 +212,71 @@ func (c *collector) connectAndCollect(d *config.Device, ch chan<- prometheus.Met
206212
}
207213

208214
func (c *collector) connect(d *config.Device) (*routeros.Client, error) {
215+
var conn net.Conn
216+
var err error
217+
218+
log.WithField("device", d.Name).Debug("trying to Dial")
209219
if !c.enableTLS {
210-
return routeros.DialTimeout(d.Address+apiPort, d.User, d.Password, c.timeout)
220+
conn, err = net.Dial("tcp", d.Address+apiPort)
221+
if err != nil {
222+
return nil, err
223+
}
224+
// return routeros.DialTimeout(d.Address+apiPort, d.User, d.Password, c.timeout)
225+
} else {
226+
tlsCfg := &tls.Config{
227+
InsecureSkipVerify: c.insecureTLS,
228+
}
229+
conn, err = tls.Dial("tcp", d.Address+apiPortTLS, tlsCfg)
230+
if err != nil {
231+
return nil, err
232+
}
233+
}
234+
log.WithField("device", d.Name).Debug("done dialing")
235+
236+
client, err := routeros.NewClient(conn)
237+
if err != nil {
238+
return nil, err
211239
}
240+
log.WithField("device", d.Name).Debug("got client")
212241

213-
tls := &tls.Config{
214-
InsecureSkipVerify: c.insecureTLS,
242+
log.WithField("device", d.Name).Debug("trying to login")
243+
r, err := client.Run("/login", "=name="+d.User, "=password="+d.Password)
244+
if err != nil {
245+
return nil, err
215246
}
216-
return routeros.DialTLSTimeout(d.Address+apiPortTLS, d.User, d.Password, tls, c.timeout)
247+
ret, ok := r.Done.Map["ret"]
248+
if !ok {
249+
// Login method post-6.43 one stage, cleartext and no challenge
250+
if r.Done != nil {
251+
return client, nil
252+
}
253+
return nil, errors.New("RouterOS: /login: no ret (challenge) received")
254+
}
255+
256+
// Login method pre-6.43 two stages, challenge
257+
b, err := hex.DecodeString(ret)
258+
if err != nil {
259+
return nil, fmt.Errorf("RouterOS: /login: invalid ret (challenge) hex string received: %s", err)
260+
}
261+
262+
r, err = client.Run("/login", "=name="+d.User, "=response="+challengeResponse(b, d.Password))
263+
if err != nil {
264+
return nil, err
265+
}
266+
log.WithField("device", d.Name).Debug("done wth login")
267+
268+
return client, nil
269+
270+
//tlsCfg := &tls.Config{
271+
// InsecureSkipVerify: c.insecureTLS,
272+
//}
273+
// return routeros.DialTLSTimeout(d.Address+apiPortTLS, d.User, d.Password, tlsCfg, c.timeout)
274+
}
275+
276+
func challengeResponse(cha []byte, password string) string {
277+
h := md5.New()
278+
h.Write([]byte{0})
279+
_, _ = io.WriteString(h, password)
280+
h.Write(cha)
281+
return fmt.Sprintf("00%x", h.Sum(nil))
217282
}

main.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var (
3636
withOptics = flag.Bool("with-optics", false, "retrieves optical diagnostic metrics")
3737
withWlanSTA = flag.Bool("with-wlansta", false, "retrieves connected wlan station metrics")
3838
withWlanIF = flag.Bool("with-wlanif", false, "retrieves wlan interface metrics")
39-
timeout = flag.Duration("timeout", collector.DefaultTimeout, "timeout when connecting to routers")
39+
timeout = flag.Duration("timeout", collector.DefaultTimeout, "timeout when connecting to devices")
4040
tls = flag.Bool("tls", false, "use tls to connect to routers")
4141
insecure = flag.Bool("insecure", false, "skips verification of server certificate when using TLS (not recommended)")
4242
cfg *config.Config
@@ -118,11 +118,11 @@ func startServer() {
118118
http.Handle(*metricsPath, h)
119119

120120
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
121-
w.Write([]byte("ok"))
121+
_, _ = w.Write([]byte("ok"))
122122
})
123123

124124
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
125-
w.Write([]byte(`<html>
125+
_, _ = w.Write([]byte(`<html>
126126
<head><title>Mikrotik Exporter</title></head>
127127
<body>
128128
<h1>Mikrotik Exporter</h1>

0 commit comments

Comments
 (0)