pebbe / zmq4

A Go interface to ZeroMQ version 4
BSD 2-Clause "Simplified" License
1.18k stars 163 forks source link

zmq.PlainAuthRemove not working as intended ? #98

Closed agnivade closed 7 years ago

agnivade commented 7 years ago

Hi there,

I have been trying to setup a secure zmq communication using plain auth. I want to be able to dynamically add and remove users without restarting my service. However, when I do zmq.AuthPlainRemove, the service keeps on running as if nothing has changed.

Here is my server.go -

//  The Woodhouse Pattern
//
//  It may keep some malicious people out but all it takes is a bit
//  of network sniffing, and they'll be able to fake their way in.

package main

import (
    "fmt"
    "log"
    "os"

    zmq "github.com/pebbe/zmq4"
)

func main() {
    logger := log.New(os.Stdout, "[INFO] ", log.Lshortfile)
    //  Start authentication engine
    zmq.AuthSetVerbose(true)
    zmq.AuthStart()
    zmq.AuthAllow("*", "127.0.0.1")

    //  Tell the authenticator how to handle PLAIN requests
    zmq.AuthPlainAdd("*", "admin", "secret")

    //  Create and bind server socket
    server, err := zmq.NewSocket(zmq.PULL)
    if err != nil {
        logger.Println(err)
        return
    }
    err = server.ServerAuthPlain("*")
    if err != nil {
        logger.Println(err)
        return
    }
    err = server.Bind("tcp://*:9000")
    if err != nil {
        logger.Println(err)
        return
    }
    defer server.Close()

    //  Send a single message from server to client
    cnt := 0
    for {
        message, err := server.Recv(0)
        if err != nil {
            logger.Println(err)
            return
        }
        log.Println("Received ", message)
        cnt++
        if cnt == 5 {
            log.Println("Removing auth")
            zmq.AuthPlainRemove("*", "admin")
        }

        if message == "END" {
            break
        }

    }

    zmq.AuthStop()

    fmt.Println("Woodhouse test OK")

}

And client.go -

//  The Woodhouse Pattern
//
//  It may keep some malicious people out but all it takes is a bit
//  of network sniffing, and they'll be able to fake their way in.

package main

import (
    "fmt"
    "log"
    "os"
    "time"

    zmq "github.com/pebbe/zmq4"
)

func main() {
    logger := log.New(os.Stdout, "[INFO] ", log.Lshortfile)
    //  Create and connect client socket
    client, err := zmq.NewSocket(zmq.PUSH)
    if err != nil {
        logger.Println(err)
        return
    }
    err = client.SetPlainUsername("admin")
    if err != nil {
        logger.Println(err)
        return
    }
    err = client.SetPlainPassword("secret")
    if err != nil {
        logger.Println(err)
        return
    }
    err = client.Connect("tcp://127.0.0.1:9000")
    if err != nil {
        logger.Println(err)
        return
    }
    defer client.Close()

    //  Send a single message from server to client

    for i := 0; i < 10; i++ {
        str := fmt.Sprintf("Hello %d", i)
        _, err = client.Send(str, 0)
        if err != nil {
            logger.Println(err)
            return
        }
        log.Println("Sent " + str)
        time.Sleep(1 * time.Second)
    }
    _, err = client.Send("END", 0)
    if err != nil {
        logger.Println(err)
        return
    }

    fmt.Println("Woodhouse test OK")

}

This is the output that I see on the server side -

go run zmq_server.go 
2017/03/22 11:57:38 AUTH: Starting
2017/03/22 11:57:39 AUTH: PASSED (whitelist) domain="*" address="127.0.0.1"
2017/03/22 11:57:39 AUTH: ALLOWED (PLAIN) domain="*" username="admin" password="secret"
2017/03/22 11:57:39 Received  Hello 0
2017/03/22 11:57:40 Received  Hello 1
2017/03/22 11:57:41 Received  Hello 2
2017/03/22 11:57:42 Received  Hello 3
2017/03/22 11:57:43 Received  Hello 4
2017/03/22 11:57:43 Removing auth
2017/03/22 11:57:44 Received  Hello 5
2017/03/22 11:57:45 Received  Hello 6
2017/03/22 11:57:46 Received  Hello 7
2017/03/22 11:57:47 Received  Hello 8
2017/03/22 11:57:48 Received  Hello 9
2017/03/22 11:57:49 Received  END
2017/03/22 11:57:49 AUTH: Stopping
2017/03/22 11:57:49 AUTH: Quitting: received QUIT message
2017/03/22 11:57:49 AUTH: Quit
2017/03/22 11:57:49 AUTH: Stopped
Woodhouse test OK

I expect the server to stop allowing messages after zmq.AuthPlainRemove is executed. But that does not seem to happen. Am I missing something ?

pebbe commented 7 years ago

In client.go, you should close the socket before ending the program, or the server may not receive the END message.

But then: remove sending the END message, so the server keeps running. Start the client, and after it finished, start it again, and notice the access is denied.

AuthPlainRemove only effects new connections, not connections that have already been given access. I think this is how it is supposed to work.

agnivade commented 7 years ago

AuthPlainRemove only effects new connections, not connections that have already been given access.

Ah, so that is a problem. So what is the cleanest way to close and re-create a connection ? Or how do I tell the client that it is no longer authenticated ?

pebbe commented 7 years ago

I don't know. Depends on the situation. Perhaps you best ask the mailing list. http://zeromq.org/docs:mailing-lists

agnivade commented 7 years ago

Thanks. Will do !