Полагаю, так должно работать.
package main
import (
"github.com/armon/go-socks5"
)
func main() {
conf := &socks5.Config{
AuthMethods: []socks5.Authenticator{
&socks5.UserPassAuthenticator{
socks5.StaticCredentials{
"username1": "password1",
"username2": "password2",
"username3": "password3",
},
},
},
}
server, err := socks5.New(conf)
if err != nil {
panic(err)
}
// Create SOCKS5 proxy on localhost port 8000
if err := server.ListenAndServe("tcp", "127.0.0.1:8000"); err != nil {
panic(err)
}
}
Поясню, почему автор библиотеки сделал именно так.
AuthMethods является массивом, чтобы можно было задать одновременно несколько методов аутентификации, если один не прошел, пробуется следующий из массива.
Authenticator — это интерфейс, позволяющий подставлять на свое место все объекты, у которых есть методы:
Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error)
и
GetCode() uint8
UserPassAuthenticator как раз реализует эти методы для случая аутентификации по имени/паролю.
Внутри него есть поле Credentials, в которое можно подставить любой объект, удовлетворяющий интерфейсу CredentialStore, т.е., имеющий метод Valid(user, password string) bool. Соответственно, вы можете сюда подставить свой объект, которому аутентификатор будет кидать пару имя/пароль, а объект в ответ будет выдавать, валидная это пара или нет.
Простейшая реализация такого объекта есть в модуле в виде объекта StaticCredentials, который по сути является map[string]string и имеет метод, который проверяет, есть ли в этом map переданная пара юзер/пароль.
Т.е., модуль предоставляет вам выбор, использовать штатные реализации аутентификации или писать свои.