Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

config: various fixes for ports #308

Merged
merged 4 commits into from
May 2, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
124 changes: 81 additions & 43 deletions server/honeytrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ type Honeytrap struct {

dataDir string

ports map[int][]string // Maps a port to an array of service names

services map[string]*ServiceMap // Maps a service name to a service implementation
// Maps a port and a protocol to an array of pointers to services
tcpPorts map[int][]*ServiceMap
udpPorts map[int][]*ServiceMap
}

// New returns a new instance of a Honeytrap struct.
Expand Down Expand Up @@ -180,23 +180,27 @@ type ServiceMap struct {
func (hc *Honeytrap) findService(conn net.Conn) (*ServiceMap, net.Conn, error) {
localAddr := conn.LocalAddr()
var port int
var serviceCandidates []*ServiceMap
// Todo(capacitorset): implement port "any"?
switch a := localAddr.(type) {
case *net.TCPAddr:
port = a.Port
tmp, ok := hc.tcpPorts[port]
if !ok {
return nil, nil, fmt.Errorf("no services for the given port")
}
serviceCandidates = tmp // prevent variable shadowing and "unused variable" error
case *net.UDPAddr:
port = a.Port
tmp, ok := hc.udpPorts[port]
if !ok {
return nil, nil, fmt.Errorf("no services for the given port")
}
serviceCandidates = tmp
default:
return nil, nil, fmt.Errorf("unknown address type %T", a)
}
serviceNames, ok := hc.ports[port]
if !ok {
// Todo(capacitorset): implement port "any"?
return nil, nil, fmt.Errorf("no services for the given port")
}
var serviceCandidates []*ServiceMap
for _, serviceName := range serviceNames {
serviceCandidates = append(serviceCandidates, hc.services[serviceName])
}

if len(serviceCandidates) == 1 {
return serviceCandidates[0], conn, nil
}
Expand Down Expand Up @@ -439,7 +443,8 @@ func (hc *Honeytrap) Run(ctx context.Context) {
enabledDirectorNames = append(enabledDirectorNames, key)
}

hc.services = make(map[string]*ServiceMap)
serviceList := make(map[string]*ServiceMap)
isServiceUsed := make(map[string]bool) // Used to check that every service is used by a port
// same for proxies
for key, s := range hc.config.Services {
x := struct {
Expand Down Expand Up @@ -479,11 +484,12 @@ func (hc *Honeytrap) Run(ctx context.Context) {
}

service := fn(options...)
hc.services[key] = &ServiceMap{
serviceList[key] = &ServiceMap{
Service: service,
Name: key,
Type: x.Type,
}
isServiceUsed[key] = false
log.Infof("Configured service %s (%s)", x.Type, key)
}

Expand All @@ -501,10 +507,12 @@ func (hc *Honeytrap) Run(ctx context.Context) {
log.Fatalf("Error initializing listener %s: %s", x.Type, err)
}

hc.ports = make(map[int][]string)
hc.tcpPorts = make(map[int][]*ServiceMap)
hc.udpPorts = make(map[int][]*ServiceMap)
for _, s := range hc.config.Ports {
x := struct {
Port string `toml:"port"`
Ports []string `toml:"ports"`
Services []string `toml:"services"`
}{}

Expand All @@ -513,48 +521,78 @@ func (hc *Honeytrap) Run(ctx context.Context) {
continue
}

addr, _, port, err := ToAddr(x.Port)
if err != nil {
log.Error("Error parsing port string: %s", err.Error())
continue
var ports []string
if x.Ports != nil {
ports = x.Ports
}
if addr == nil {
log.Error("Failed to bind: addr is nil")
continue
if x.Port != "" {
ports = append(ports, x.Port)
}

if _, ok := hc.ports[port]; ok {
log.Error("Port %d was already defined, ignoring the newer definition", port)
if x.Port != "" && x.Ports != nil {
log.Warning("Both \"port\" and \"ports\" were defined, this can be confusing")
} else if x.Port == "" && x.Ports == nil {
log.Error("Neither \"port\" nor \"ports\" were defined")
continue
}

if len(x.Services) == 0 {
log.Warningf("Port %d has no services defined", port)
log.Warning("No services defined for port(s) " + strings.Join(ports, ", "))
}

// check for the existence of the named services
for _, service := range x.Services {
found := false
for name := range hc.services {
if service == name {
found = true
break
for _, portStr := range ports {
addr, proto, port, err := ToAddr(portStr)
if err != nil {
log.Error("Error parsing port string: %s", err.Error())
continue
}
if addr == nil {
log.Error("Failed to bind: addr is nil")
continue
}

// Get the services from their names
var servicePtrs []*ServiceMap
for _, serviceName := range x.Services {
ptr, ok := serviceList[serviceName]
if !ok {
log.Error("Unknown service '%s' in ports", serviceName)
}
servicePtrs = append(servicePtrs, ptr)
isServiceUsed[serviceName] = true
}
if !found {
log.Error("Unknown service '%s' in ports", service)
switch proto {
case "tcp":
if _, ok := hc.tcpPorts[port]; ok {
log.Error("Port tcp/%d was already defined, ignoring the newer definition", port)
continue
}
hc.tcpPorts[port] = servicePtrs
case "udp":
if _, ok := hc.udpPorts[port]; ok {
log.Error("Port udp/%d was already defined, ignoring the newer definition", port)
continue
}
hc.udpPorts[port] = servicePtrs
default:
log.Errorf("Unknown protocol %s", proto)
continue
}
}
hc.ports[port] = x.Services

a, ok := l.(listener.AddAddresser)
if !ok {
log.Error("Listener error")
continue
a, ok := l.(listener.AddAddresser)
if !ok {
log.Error("Listener error")
continue
}
a.AddAddress(addr)

log.Infof("Configured port %s/%s", addr.Network(), addr.String())
}
a.AddAddress(addr)
}

log.Infof("Configured port %s/%s", addr.Network(), addr.String())
for name, isUsed := range isServiceUsed {
if !isUsed {
log.Warningf("Service %s is defined but not used", name)
}
}

if err := l.Start(ctx); err != nil {
Expand Down