misc: small fix or general refactoring i did not bother commenting

This commit is contained in:
Simone Margaritelli 2024-09-19 21:49:02 +02:00
parent 91d360327a
commit 51a5b4ad6e
17 changed files with 1375 additions and 239 deletions

125
epson.yml Normal file
View file

@ -0,0 +1,125 @@
_http._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-03
service: _http._tcp
domain: local.
port: 8080
_ipp._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-03
service: _ipp._tcp
domain: local.
port: 6631
_ipps._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-03
service: _ipps._tcp
domain: local.
port: 6633
text:
- txtvers=1
- ty=EPSON XP-630 Series
- usb_MFG=EPSON
- usb_MDL=XP-630 Series
- product=(EPSON XP-630 Series)
- pdl=application/octet-stream,image/pwg-raster,image/urf,image/jpeg
- rp=ipp/print
- qtotal=1
- Color=T
- Duplex=T
- Scan=T
- Fax=F
- kind=document,envelope,label,photo
- PaperMax=legal-A4
- URF=CP1,MT1-3-5-8-10-11-12,PQ4-5,OB9,OFU0,RS360,SRGB24,W8,DM3,IS1-7,V1.4
- mopria-certified=1.2
- priority=30
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- note=
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
- TLS=1.2
_pdl-datastream._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-03
service: _pdl-datastream._tcp
domain: local.
port: 9100
_printer._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-03
service: _printer._tcp
domain: local.
port: 515
text:
- txtvers=1
- priority=50
- ty=EPSON XP-630 Series
- usb_MFG=EPSON
- usb_MDL=XP-630 Series
- product=(EPSON XP-630 Series)
- pdl=raw
- rp=auto
- qtotal=1
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- note=
_privet._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-03
service: _privet._tcp
domain: local.
port: 8081
text:
- txtvers=1
- ty=EPSON XP-630 Series (EPSON59F5BA)
- url=https://www.google.com/cloudprint
- type=printer
- id=0936a89f-33d7-80f5-c1bc-7421d40a78b5
- cs=offline
_scanner._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-03
service: _scanner._tcp
domain: local.
port: 1865
text:
- txtvers=1
- ty=EPSON XP-630 Series
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- mfg=EPSON
- mdl=XP-630 Series
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
- scannerAvailable=0
- note=
_smb._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-03
service: _smb._tcp
domain: local.
port: 4445
_uscan._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-03
service: _uscan._tcp
domain: local.
port: 4443
text:
- txtvers=1
- vers=2.5
- representation=/PRESENTATION/AIRPRINT/PRINTER_128.PNG
- rs=eSCL
- ty=EPSON XP-630 Series
- pdl=application/pdf,image/jpeg
- cs=color,grayscale,binary
- is=platen
- duplex=F
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
- note=

3
go.mod
View file

@ -22,6 +22,7 @@ require (
github.com/google/gousb v1.1.3
github.com/gorilla/mux v1.8.1
github.com/gorilla/websocket v1.5.3
github.com/grandcat/zeroconf v1.0.0
github.com/hashicorp/go-bexpr v0.1.14
github.com/inconshreveable/go-vhost v1.0.0
github.com/jpillora/go-tld v1.2.1
@ -29,6 +30,7 @@ require (
github.com/mdlayher/dhcp6 v0.0.0-20190311162359-2a67805d7d0b
github.com/miekg/dns v1.1.61
github.com/mitchellh/go-homedir v1.1.0
github.com/phin1x/go-ipp v1.6.1
github.com/robertkrimen/otto v0.4.0
github.com/stratoberry/go-gpsd v1.3.0
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07
@ -47,7 +49,6 @@ require (
github.com/golang/mock v1.6.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/grandcat/zeroconf v1.0.0 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/kr/binarydist v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect

2
go.sum
View file

@ -101,6 +101,8 @@ github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxd
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw=
github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/phin1x/go-ipp v1.6.1 h1:oxJXi92BO2FZhNcG3twjnxKFH1liTQ46vbbZx+IN/80=
github.com/phin1x/go-ipp v1.6.1/go.mod h1:GZwyNds6grdLi2xRBX22Cvt7Dh7ITWsML0bjrqBF5uo=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

View file

@ -4,13 +4,13 @@ import (
"fmt"
"io"
"github.com/bettercap/bettercap/v2/modules/mdns"
"github.com/bettercap/bettercap/v2/modules/zerogod"
"github.com/bettercap/bettercap/v2/session"
"github.com/evilsocket/islazy/tui"
)
func (mod *EventsStream) viewMDNSEvent(output io.Writer, e session.Event) {
event := e.Data.(mdns.ServiceDiscoveryEvent)
event := e.Data.(zerogod.ServiceDiscoveryEvent)
fmt.Fprintf(output, "[%s] [%s] service %s detected for %s (%s):%d with %d records\n",
e.Time.Format(mod.timeFormat),
tui.Green(e.Tag),

View file

@ -1,139 +0,0 @@
package mdns
import (
"errors"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/evilsocket/islazy/tui"
"github.com/grandcat/zeroconf"
yaml "gopkg.in/yaml.v3"
)
/*
type multiService struct {
mod *MDNSModule
services []*MDNSService
}
func (m multiService) Records(q dns.Question) []dns.RR {
records := make([]dns.RR, 0)
m.mod.Debug("QUESTION: %+v", q)
if strings.HasPrefix(q.Name, "_services._dns-sd._udp.") {
for _, svc := range m.services {
records = append(records, svc.Records(q)...)
}
} else {
for _, svc := range m.services {
if svcRecords := svc.Records(q); len(svcRecords) > 0 {
records = svcRecords
break
}
}
}
if num := len(records); num == 0 {
m.mod.Debug("unhandled service %+v", q)
} else {
m.mod.Info("responding to query %s with %d records", tui.Green(q.Name), num)
if q.Name == "_services._dns-sd._udp.local." {
for _, r := range records {
m.mod.Info(" %+v", r)
}
}
}
return records
}
*/
type Advertiser struct {
Filename string
Mapping map[string]zeroconf.ServiceEntry
Servers map[string]*zeroconf.Server
}
func (mod *MDNSModule) startAdvertiser(fileName string) error {
if mod.advertiser != nil {
return fmt.Errorf("advertiser already started for %s", mod.advertiser.Filename)
}
data, err := ioutil.ReadFile(fileName)
if err != nil {
return fmt.Errorf("could not read %s: %v", fileName, err)
}
mapping := make(map[string]zeroconf.ServiceEntry)
if err = yaml.Unmarshal(data, &mapping); err != nil {
return fmt.Errorf("could not deserialize %s: %v", fileName, err)
}
hostName, err := os.Hostname()
if err != nil {
return fmt.Errorf("could not get hostname: %v", err)
}
if !strings.HasSuffix(hostName, ".") {
hostName += "."
}
ifName := mod.Session.Interface.Name()
/*
iface, err := net.InterfaceByName(ifName)
if err != nil {
return fmt.Errorf("error getting interface %s: %v", ifName, err)
}
*/
mod.Info("loaded %d services from %s, advertising with host=%s iface=%s ipv4=%s ipv6=%s",
len(mapping),
fileName,
hostName,
ifName,
mod.Session.Interface.IpAddress,
mod.Session.Interface.Ip6Address)
advertiser := &Advertiser{
Filename: fileName,
Mapping: mapping,
Servers: make(map[string]*zeroconf.Server),
}
for key, svc := range mapping {
server, err := zeroconf.Register(svc.Instance, svc.Service, svc.Domain, svc.Port, svc.Text, nil)
if err != nil {
return fmt.Errorf("could not create service %s: %v", svc.Instance, err)
}
mod.Info("advertising service %s", tui.Yellow(svc.Service))
advertiser.Servers[key] = server
}
mod.advertiser = advertiser
mod.Debug("%+v", *mod.advertiser)
return nil
}
func (mod *MDNSModule) stopAdvertiser() error {
if mod.advertiser == nil {
return errors.New("advertiser not started")
}
mod.Info("stopping %d services ...", len(mod.advertiser.Mapping))
for key, server := range mod.advertiser.Servers {
mod.Info("stopping %s ...", key)
server.Shutdown()
}
mod.Info("all services stopped")
mod.advertiser = nil
return nil
}

View file

@ -19,7 +19,6 @@ import (
"github.com/bettercap/bettercap/v2/modules/https_proxy"
"github.com/bettercap/bettercap/v2/modules/https_server"
"github.com/bettercap/bettercap/v2/modules/mac_changer"
"github.com/bettercap/bettercap/v2/modules/mdns"
"github.com/bettercap/bettercap/v2/modules/mysql_server"
"github.com/bettercap/bettercap/v2/modules/ndp_spoof"
"github.com/bettercap/bettercap/v2/modules/net_probe"
@ -33,6 +32,7 @@ import (
"github.com/bettercap/bettercap/v2/modules/update"
"github.com/bettercap/bettercap/v2/modules/wifi"
"github.com/bettercap/bettercap/v2/modules/wol"
"github.com/bettercap/bettercap/v2/modules/zerogod"
"github.com/bettercap/bettercap/v2/session"
)
@ -55,7 +55,7 @@ func LoadModules(sess *session.Session) {
sess.Register(https_server.NewHttpsServer(sess))
sess.Register(mac_changer.NewMacChanger(sess))
sess.Register(mysql_server.NewMySQLServer(sess))
sess.Register(mdns.NewMDNSModule(sess))
sess.Register(zerogod.NewZeroGod(sess))
sess.Register(net_sniff.NewSniffer(sess))
sess.Register(packet_proxy.NewPacketProxy(sess))
sess.Register(net_probe.NewProber(sess))

View file

@ -118,7 +118,7 @@ func (mod *Prober) Start() error {
}
if mod.probes.MDNS {
mod.Session.Run("mdns.discovery on")
mod.Session.Run("zerogod.discovery on")
}
fromIP := mod.Session.Interface.IP
@ -158,7 +158,7 @@ func (mod *Prober) Start() error {
func (mod *Prober) Stop() error {
return mod.SetRunning(false, func() {
if mod.probes.MDNS {
mod.Session.Run("mdns.discovery off")
mod.Session.Run("zerogod.discovery off")
}
mod.waitGroup.Wait()

View file

@ -0,0 +1,109 @@
package zerogod
import (
"context"
"crypto/tls"
"fmt"
"net"
"strings"
"github.com/evilsocket/islazy/tui"
)
type Handler struct {
TLS bool
Handle func(mod *ZeroGod, client net.Conn, srvHost string, srvPort int, srvTLS bool)
}
// TODO: add more and possibly autodetect from peeking at the first bytes sent by the client
var TCP_HANDLERS = map[string]Handler{
"_ipp": {
Handle: ippClientHandler,
},
"_ipps": {
TLS: true,
Handle: ippClientHandler,
},
// TODO: _http at least
}
type Acceptor struct {
mod *ZeroGod
srvHost string
port uint16
service string
tlsConfig *tls.Config
listener net.Listener
running bool
context context.Context
ctxCancel context.CancelFunc
handler Handler
}
func NewAcceptor(mod *ZeroGod, service string, srvHost string, port uint16, tlsConfig *tls.Config) *Acceptor {
context, ctcCancel := context.WithCancel(context.Background())
acceptor := Acceptor{
mod: mod,
port: port,
service: service,
context: context,
ctxCancel: ctcCancel,
srvHost: srvHost,
}
for svcName, svcHandler := range TCP_HANDLERS {
if strings.Contains(service, svcName) {
acceptor.tlsConfig = tlsConfig
acceptor.handler = svcHandler
break
}
}
if acceptor.handler.Handle == nil {
mod.Warning("no protocol handler found for service %s, using generic dump handler", tui.Yellow(service))
acceptor.handler.Handle = handleGenericTCP
} else {
mod.Info("found %s protocol handler", tui.Green(service))
}
return &acceptor
}
func (a *Acceptor) Start() (err error) {
var lc net.ListenConfig
if a.listener, err = lc.Listen(a.context, "tcp", fmt.Sprintf("0.0.0.0:%d", a.port)); err != nil {
return err
}
if a.tlsConfig != nil {
a.listener = tls.NewListener(a.listener, a.tlsConfig)
}
a.running = true
go func() {
a.mod.Debug("tcp listener for port %d (%s) started", a.port, tui.Green(a.service))
for a.running {
if conn, err := a.listener.Accept(); err != nil {
if a.running {
a.mod.Error("%v", err)
}
} else {
a.mod.Info("accepted connection for service %s (port %d): %v", tui.Green(a.service), a.port, conn.RemoteAddr())
go a.handler.Handle(a.mod, conn, a.srvHost, int(a.port), a.tlsConfig != nil)
}
}
a.mod.Debug("tcp listener for port %d (%s) stopped", a.port, tui.Green(a.service))
}()
return nil
}
func (a *Acceptor) Stop() {
a.mod.Debug("stopping tcp listener for port %d", a.port)
a.running = false
a.ctxCancel()
<-a.context.Done()
a.listener.Close()
a.mod.Debug("tcp listener for port %d stopped", a.port)
}

View file

@ -0,0 +1,197 @@
package zerogod
import (
"crypto/tls"
"errors"
"fmt"
"io/ioutil"
"os"
"strings"
"time"
tls_utils "github.com/bettercap/bettercap/v2/tls"
"github.com/evilsocket/islazy/fs"
"github.com/evilsocket/islazy/tui"
"github.com/grandcat/zeroconf"
yaml "gopkg.in/yaml.v3"
)
type Advertiser struct {
Filename string
Mapping map[string]zeroconf.ServiceEntry
Servers map[string]*zeroconf.Server
Acceptors map[string]*Acceptor
}
type setupResult struct {
err error
key string
server *zeroconf.Server
}
func (mod *ZeroGod) startAdvertiser(fileName string) error {
if mod.advertiser != nil {
return fmt.Errorf("advertiser already started for %s", mod.advertiser.Filename)
}
var certFile string
var keyFile string
var err error
// read tls configuration
if err, certFile = mod.StringParam("zerogod.advertise.certificate"); err != nil {
return err
} else if certFile, err = fs.Expand(certFile); err != nil {
return err
}
if err, keyFile = mod.StringParam("zerogod.advertise.key"); err != nil {
return err
} else if keyFile, err = fs.Expand(keyFile); err != nil {
return err
}
if !fs.Exists(certFile) || !fs.Exists(keyFile) {
cfg, err := tls_utils.CertConfigFromModule("zerogod.advertise", mod.SessionModule)
if err != nil {
return err
}
mod.Debug("%+v", cfg)
mod.Info("generating server TLS key to %s", keyFile)
mod.Info("generating server TLS certificate to %s", certFile)
if err := tls_utils.Generate(cfg, certFile, keyFile, false); err != nil {
return err
}
} else {
mod.Info("loading server TLS key from %s", keyFile)
mod.Info("loading server TLS certificate from %s", certFile)
}
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return err
}
tlsConfig := tls.Config{
Certificates: []tls.Certificate{cert},
InsecureSkipVerify: true,
}
data, err := ioutil.ReadFile(fileName)
if err != nil {
return fmt.Errorf("could not read %s: %v", fileName, err)
}
mapping := make(map[string]zeroconf.ServiceEntry)
if err = yaml.Unmarshal(data, &mapping); err != nil {
return fmt.Errorf("could not deserialize %s: %v", fileName, err)
}
hostName, err := os.Hostname()
if err != nil {
return fmt.Errorf("could not get hostname: %v", err)
}
if !strings.HasSuffix(hostName, ".") {
hostName += "."
}
mod.Info("loaded %d services from %s, advertising with host=%s iface=%s ipv4=%s ipv6=%s",
len(mapping),
fileName,
hostName,
mod.Session.Interface.Name(),
mod.Session.Interface.IpAddress,
mod.Session.Interface.Ip6Address)
advertiser := &Advertiser{
Filename: fileName,
Mapping: mapping,
Servers: make(map[string]*zeroconf.Server),
Acceptors: make(map[string]*Acceptor),
}
svcChan := make(chan setupResult)
// paralleize initialization
for key, svc := range mapping {
go func(key string, svc zeroconf.ServiceEntry) {
mod.Info("unregistering instance %s ...", tui.Yellow(fmt.Sprintf("%s.%s.%s", svc.Instance, svc.Service, svc.Domain)))
// create a first instance just to deregister it from the network
server, err := zeroconf.Register(svc.Instance, svc.Service, svc.Domain, svc.Port, svc.Text, nil)
if err != nil {
svcChan <- setupResult{err: fmt.Errorf("could not create service %s: %v", svc.Instance, err)}
return
}
server.Shutdown()
// give some time to the network to adjust
time.Sleep(time.Duration(1) * time.Second)
// now create it again to actually advertise
if server, err = zeroconf.Register(svc.Instance, svc.Service, svc.Domain, svc.Port, svc.Text, nil); err != nil {
svcChan <- setupResult{err: fmt.Errorf("could not create service %s: %v", svc.Instance, err)}
return
}
mod.Info("advertising service %s", tui.Yellow(svc.Service))
svcChan <- setupResult{
key: key,
server: server,
}
}(key, svc)
}
for res := range svcChan {
if res.err != nil {
return res.err
}
advertiser.Servers[res.key] = res.server
if len(advertiser.Servers) == len(mapping) {
break
}
}
// now create the tcp acceptors
for key, svc := range mapping {
acceptor := NewAcceptor(mod, key, hostName, uint16(svc.Port), &tlsConfig)
if err := acceptor.Start(); err != nil {
return err
}
advertiser.Acceptors[key] = acceptor
}
mod.advertiser = advertiser
mod.Debug("%+v", *mod.advertiser)
return nil
}
func (mod *ZeroGod) stopAdvertiser() error {
if mod.advertiser == nil {
return errors.New("advertiser not started")
}
mod.Info("stopping %d services ...", len(mod.advertiser.Mapping))
for key, server := range mod.advertiser.Servers {
mod.Info("stopping %s ...", key)
server.Shutdown()
}
mod.Info("all services stopped")
mod.Info("stopping %d acceptors ...", len(mod.advertiser.Acceptors))
for _, acceptor := range mod.advertiser.Acceptors {
acceptor.Stop()
}
mod.Info("all acceptors stopped")
mod.advertiser = nil
return nil
}

View file

@ -1,20 +1,18 @@
package mdns
package zerogod
import (
"context"
"fmt"
"strings"
"github.com/bettercap/bettercap/v2/modules/syn_scan"
"github.com/bettercap/bettercap/v2/network"
"github.com/bettercap/bettercap/v2/session"
"github.com/evilsocket/islazy/str"
"github.com/bettercap/bettercap/v2/tls"
"github.com/evilsocket/islazy/tui"
"github.com/grandcat/zeroconf"
)
type MDNSModule struct {
type ZeroGod struct {
session.SessionModule
advertiser *Advertiser
@ -24,59 +22,59 @@ type MDNSModule struct {
mapping map[string]map[string]*zeroconf.ServiceEntry
}
func NewMDNSModule(s *session.Session) *MDNSModule {
mod := &MDNSModule{
SessionModule: session.NewSessionModule("mdns", s),
func NewZeroGod(s *session.Session) *ZeroGod {
mod := &ZeroGod{
SessionModule: session.NewSessionModule("zerogod", s),
mapping: make(map[string]map[string]*zeroconf.ServiceEntry),
resolvers: make(map[string]*zeroconf.Resolver),
}
mod.SessionModule.Requires("net.recon")
mod.AddHandler(session.NewModuleHandler("mdns.discovery on", "",
mod.AddHandler(session.NewModuleHandler("zerogod.discovery on", "",
"Start DNS-SD / mDNS discovery.",
func(args []string) error {
return mod.Start()
}))
mod.AddHandler(session.NewModuleHandler("mdns.discovery off", "",
mod.AddHandler(session.NewModuleHandler("zerogod.discovery off", "",
"Stop DNS-SD / mDNS discovery.",
func(args []string) error {
return mod.Stop()
}))
// TODO: add autocomplete
mod.AddHandler(session.NewModuleHandler("mdns.show", "",
mod.AddHandler(session.NewModuleHandler("zerogod.show", "",
"Show discovered services.",
func(args []string) error {
return mod.show("", false)
}))
mod.AddHandler(session.NewModuleHandler("mdns.show-full", "",
mod.AddHandler(session.NewModuleHandler("zerogod.show-full", "",
"Show discovered services and their DNS records.",
func(args []string) error {
return mod.show("", true)
}))
mod.AddHandler(session.NewModuleHandler("mdns.show ADDRESS", "mdns.show (.+)",
mod.AddHandler(session.NewModuleHandler("zerogod.show ADDRESS", "zerogod.show (.+)",
"Show discovered services given an ip address.",
func(args []string) error {
return mod.show(args[0], false)
}))
mod.AddHandler(session.NewModuleHandler("mdns.show-full ADDRESS", "mdns.show-full (.+)",
mod.AddHandler(session.NewModuleHandler("zerogod.show-full ADDRESS", "zerogod.show-full (.+)",
"Show discovered services and DNS records given an ip address.",
func(args []string) error {
return mod.show(args[0], true)
}))
mod.AddHandler(session.NewModuleHandler("mdns.save ADDRESS FILENAME", "mdns.save (.+) (.+)",
mod.AddHandler(session.NewModuleHandler("zerogod.save ADDRESS FILENAME", "zerogod.save (.+) (.+)",
"Save the mDNS information of a given ADDRESS in the FILENAME yaml file.",
func(args []string) error {
return mod.save(args[0], args[1])
}))
mod.AddHandler(session.NewModuleHandler("mdns.advertise FILENAME", "mdns.advertise (.+)",
mod.AddHandler(session.NewModuleHandler("zerogod.advertise FILENAME", "zerogod.advertise (.+)",
"Start advertising the mDNS services from the FILENAME yaml file.",
func(args []string) error {
if args[0] == "off" {
@ -85,28 +83,40 @@ func NewMDNSModule(s *session.Session) *MDNSModule {
return mod.startAdvertiser(args[0])
}))
mod.AddHandler(session.NewModuleHandler("mdns.advertise off", "",
mod.AddHandler(session.NewModuleHandler("zerogod.advertise off", "",
"Start a previously started advertiser.",
func(args []string) error {
return mod.stopAdvertiser()
}))
mod.AddParam(session.NewStringParameter("zerogod.advertise.certificate",
"~/.bettercap-zerogod.cert.pem",
"",
"TLS certificate file (will be auto generated if filled but not existing) to use for advertised TCP services."))
mod.AddParam(session.NewStringParameter("zerogod.advertise.key",
"~/.bettercap-zerogod.key.pem",
"",
"TLS key file (will be auto generated if filled but not existing) to use for advertised TCP services."))
tls.CertConfigToModule("zerogod.advertise", &mod.SessionModule, tls.DefaultLegitConfig)
return mod
}
func (mod *MDNSModule) Name() string {
return "mdns"
func (mod *ZeroGod) Name() string {
return "zerogod"
}
func (mod *MDNSModule) Description() string {
return "A DNS-SD / mDNS module for discovery and spoofing."
func (mod *ZeroGod) Description() string {
return "A DNS-SD / mDNS / Bonjour / Zeroconf module for discovery and spoofing."
}
func (mod *MDNSModule) Author() string {
func (mod *ZeroGod) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>"
}
func (mod *MDNSModule) Configure() (err error) {
func (mod *ZeroGod) Configure() (err error) {
if mod.Running() {
return session.ErrAlreadyStarted(mod.Name())
}
@ -127,68 +137,7 @@ type ServiceDiscoveryEvent struct {
Endpoint *network.Endpoint `json:"endpoint"`
}
func (mod *MDNSModule) updateEndpointMeta(address string, endpoint *network.Endpoint, svc *zeroconf.ServiceEntry) {
mod.Debug("found endpoint %s for address %s", endpoint.HwAddress, address)
// TODO: this is shit and needs to be refactored
// update mdns metadata
meta := make(map[string]string)
svcType := svc.Service
meta[fmt.Sprintf("mdns:%s:name", svcType)] = svc.ServiceName()
meta[fmt.Sprintf("mdns:%s:hostname", svcType)] = svc.HostName
// TODO: include all
if len(svc.AddrIPv4) > 0 {
meta[fmt.Sprintf("mdns:%s:ipv4", svcType)] = svc.AddrIPv4[0].String()
}
if len(svc.AddrIPv6) > 0 {
meta[fmt.Sprintf("mdns:%s:ipv6", svcType)] = svc.AddrIPv6[0].String()
}
meta[fmt.Sprintf("mdns:%s:port", svcType)] = fmt.Sprintf("%d", svc.Port)
for _, field := range svc.Text {
field = str.Trim(field)
if len(field) == 0 {
continue
}
key := ""
value := ""
if strings.Contains(field, "=") {
parts := strings.SplitN(field, "=", 2)
key = parts[0]
value = parts[1]
} else {
key = field
}
meta[fmt.Sprintf("mdns:%s:info:%s", svcType, key)] = value
}
mod.Debug("meta for %s: %v", address, meta)
endpoint.OnMeta(meta)
// update ports
ports := endpoint.Meta.GetOr("ports", map[int]*syn_scan.OpenPort{}).(map[int]*syn_scan.OpenPort)
if _, found := ports[svc.Port]; !found {
ports[svc.Port] = &syn_scan.OpenPort{
Proto: "tcp",
Port: svc.Port,
Service: network.GetServiceByPort(svc.Port, "tcp"),
}
}
endpoint.Meta.Set("ports", ports)
}
func (mod *MDNSModule) onServiceDiscovered(svc *zeroconf.ServiceEntry) {
func (mod *ZeroGod) onServiceDiscovered(svc *zeroconf.ServiceEntry) {
mod.Debug("%++v", *svc)
if svc.Service == "_services._dns-sd._udp" && len(svc.AddrIPv4) == 0 && len(svc.AddrIPv6) == 0 {
@ -243,7 +192,7 @@ func (mod *MDNSModule) onServiceDiscovered(svc *zeroconf.ServiceEntry) {
session.I.Refresh()
}
func (mod *MDNSModule) startResolver(service string) error {
func (mod *ZeroGod) startResolver(service string) error {
mod.Debug("starting resolver for service %s", tui.Yellow(service))
resolver, err := zeroconf.NewResolver(nil)
@ -273,7 +222,7 @@ func (mod *MDNSModule) startResolver(service string) error {
return nil
}
func (mod *MDNSModule) Start() (err error) {
func (mod *ZeroGod) Start() (err error) {
if err = mod.Configure(); err != nil {
return err
}
@ -292,10 +241,12 @@ func (mod *MDNSModule) Start() (err error) {
})
}
func (mod *MDNSModule) Stop() error {
func (mod *ZeroGod) Stop() error {
return mod.SetRunning(false, func() {
mod.stopAdvertiser()
if mod.rootCancel != nil {
mod.Debug("stopping mDNS discovery")
mod.Debug("stopping discovery")
mod.rootCancel()
<-mod.rootContext.Done()

View file

@ -0,0 +1,72 @@
package zerogod
import (
"fmt"
"strings"
"github.com/bettercap/bettercap/v2/modules/syn_scan"
"github.com/bettercap/bettercap/v2/network"
"github.com/evilsocket/islazy/str"
"github.com/grandcat/zeroconf"
)
func (mod *ZeroGod) updateEndpointMeta(address string, endpoint *network.Endpoint, svc *zeroconf.ServiceEntry) {
mod.Debug("found endpoint %s for address %s", endpoint.HwAddress, address)
// TODO: this is shit and needs to be refactored
// update mdns metadata
meta := make(map[string]string)
svcType := svc.Service
meta[fmt.Sprintf("mdns:%s:name", svcType)] = svc.ServiceName()
meta[fmt.Sprintf("mdns:%s:hostname", svcType)] = svc.HostName
// TODO: include all
if len(svc.AddrIPv4) > 0 {
meta[fmt.Sprintf("mdns:%s:ipv4", svcType)] = svc.AddrIPv4[0].String()
}
if len(svc.AddrIPv6) > 0 {
meta[fmt.Sprintf("mdns:%s:ipv6", svcType)] = svc.AddrIPv6[0].String()
}
meta[fmt.Sprintf("mdns:%s:port", svcType)] = fmt.Sprintf("%d", svc.Port)
for _, field := range svc.Text {
field = str.Trim(field)
if len(field) == 0 {
continue
}
key := ""
value := ""
if strings.Contains(field, "=") {
parts := strings.SplitN(field, "=", 2)
key = parts[0]
value = parts[1]
} else {
key = field
}
meta[fmt.Sprintf("mdns:%s:info:%s", svcType, key)] = value
}
mod.Debug("meta for %s: %v", address, meta)
endpoint.OnMeta(meta)
// update ports
ports := endpoint.Meta.GetOr("ports", map[int]*syn_scan.OpenPort{}).(map[int]*syn_scan.OpenPort)
if _, found := ports[svc.Port]; !found {
ports[svc.Port] = &syn_scan.OpenPort{
Proto: "tcp",
Port: svc.Port,
Service: network.GetServiceByPort(svc.Port, "tcp"),
}
}
endpoint.Meta.Set("ports", ports)
}

View file

@ -0,0 +1,69 @@
package zerogod
import (
"fmt"
"net"
)
func Dump(by []byte) string {
s := ""
n := len(by)
rowcount := 0
width := 16
stop := (n / width) * width
k := 0
for i := 0; i <= stop; i += width {
k++
if i+width < n {
rowcount = width
} else {
rowcount = min(k*width, n) % width
}
s += fmt.Sprintf("%02d ", i)
for j := 0; j < rowcount; j++ {
s += fmt.Sprintf("%02x ", by[i+j])
}
for j := rowcount; j < width; j++ {
s += " "
}
s += fmt.Sprintf(" '%s'\n", viewString(by[i:(i+rowcount)]))
}
return s
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func viewString(b []byte) string {
r := []rune(string(b))
for i := range r {
if r[i] < 32 || r[i] > 126 {
r[i] = '.'
}
}
return string(r)
}
func handleGenericTCP(mod *ZeroGod, client net.Conn, srvHost string, srvPort int, srvTLS bool) {
defer client.Close()
buf := make([]byte, 1024)
for {
if read, err := client.Read(buf); err != nil {
mod.Error("error while reading from %v: %v", client.RemoteAddr(), err)
break
} else if read == 0 {
mod.Error("error while reading from %v: no data", client.RemoteAddr())
break
} else {
mod.Info("read %d bytes from %v:\n%s\n", read, client.RemoteAddr(), Dump(buf[0:read]))
}
}
}

View file

@ -0,0 +1,355 @@
package zerogod
import (
"bufio"
"bytes"
"fmt"
"io"
"net"
"net/http"
"time"
"github.com/evilsocket/islazy/ops"
"github.com/evilsocket/islazy/tui"
"github.com/phin1x/go-ipp"
)
var IPP_REQUEST_NAMES = map[int16]string{
// https://tools.ietf.org/html/rfc2911#section-4.4.15
0x0002: "Print-Job",
0x0003: "Print-URI",
0x0004: "Validate-Job",
0x0005: "Create-Job",
0x0006: "Send-Document",
0x0007: "Send-URI",
0x0008: "Cancel-Job",
0x0009: "Get-Job-Attributes",
0x000A: "Get-Jobs",
0x000B: "Get-Printer-Attributes",
0x000C: "Hold-Job",
0x000D: "Release-Job",
0x000E: "Restart-Job",
0x0010: "Pause-Printer",
0x0011: "Resume-Printer",
0x0012: "Purge-Jobs",
// https://web.archive.org/web/20061024184939/http://uw714doc.sco.com/en/cups/ipp.html
0x4001: "CUPS-Get-Default",
0x4002: "CUPS-Get-Printers",
0x4003: "CUPS-Add-Modify-Printer",
0x4004: "CUPS-Delete-Printer",
0x4005: "CUPS-Get-Classes",
0x4006: "CUPS-Add-Modify-Class",
0x4007: "CUPS-Delete-Class",
0x4008: "CUPS-Accept-Jobs",
0x4009: "CUPS-Reject-Jobs",
0x400A: "CUPS-Set-Default",
0x400B: "CUPS-Get-Devices",
0x400C: "CUPS-Get-PPDs",
0x400D: "CUPS-Move-Job",
}
func ippClientHandler(mod *ZeroGod, client net.Conn, srvHost string, srvPort int, srvTLS bool) {
defer client.Close()
buf := make([]byte, 4096)
// read raw request
read, err := client.Read(buf)
if err != nil {
if err == io.EOF {
return
}
mod.Error("error while reading from %v: %v", client.RemoteAddr(), err)
return
} else if read == 0 {
mod.Error("error while reading from %v: no data", client.RemoteAddr())
return
}
raw_req := buf[0:read]
mod.Debug("read %d bytes from %v:\n%s\n", read, client.RemoteAddr(), Dump(raw_req))
// parse as http
reader := bufio.NewReader(bytes.NewReader(raw_req))
http_req, err := http.ReadRequest(reader)
if err != nil {
mod.Error("error while parsing http request from %v: %v", client.RemoteAddr(), err)
return
}
mod.Info("%v -> %s", client.RemoteAddr(), tui.Green(http_req.UserAgent()))
ipp_body := http_req.Body
// check for an Expect 100-continue
if http_req.Header.Get("Expect") == "100-continue" {
// inform the client we're ready to read the request body
client.Write([]byte("HTTP/1.1 100 Continue\r\n\r\n"))
// read the body
read, err := client.Read(buf)
if err != nil {
if err == io.EOF {
return
}
mod.Error("error while reading ipp body from %v: %v", client.RemoteAddr(), err)
return
} else if read == 0 {
mod.Error("error while reading ipp body from %v: no data", client.RemoteAddr())
return
}
ipp_body = io.NopCloser(bytes.NewReader(buf[0:read]))
}
// parse as IPP
ipp_req, err := ipp.NewRequestDecoder(ipp_body).Decode(nil)
if err != nil {
mod.Error("error while parsing ip request from %v: %v", client.RemoteAddr(), err)
return
}
ipp_op_name := fmt.Sprintf("<unknown 0x%x>", ipp_req.Operation)
if name, found := IPP_REQUEST_NAMES[ipp_req.Operation]; found {
ipp_op_name = name
}
mod.Info("%v op=%s attributes=%v", client.RemoteAddr(), tui.Bold(ipp_op_name), ipp_req.OperationAttributes)
switch ipp_req.Operation {
// Get-Printer-Attributes
case 0x000B:
ippOnGetPrinterAttributes(mod, client, ipp_req, srvHost, srvPort, srvTLS)
default:
ippOnUnhandledRequest(mod, client, ipp_req, ipp_op_name)
}
}
func ippSendResponse(mod *ZeroGod, client net.Conn, response *ipp.Response) {
mod.Debug("SENDING %++v", *response)
resp_data, err := response.Encode()
if err != nil {
mod.Error("error while encoding ipp response: %v", err)
return
}
headers := [][]byte{
[]byte("HTTP/1.1 200 OK\r\n"),
[]byte("Content-Type: application/ipp\r\n"),
[]byte(fmt.Sprintf("Content-Length: %d\r\n", len(resp_data))),
[]byte("Connection: close\r\n"),
[]byte("\r\n"),
}
for _, header := range headers {
if _, err := client.Write(header); err != nil {
mod.Error("error while writing header: %v", err)
return
}
}
if _, err = client.Write(resp_data); err != nil {
mod.Error("error while writing ipp response data: %v", err)
return
}
mod.Debug("sent %d of ipp response to %v", len(resp_data), client.RemoteAddr())
}
func ippOnUnhandledRequest(mod *ZeroGod, client net.Conn, ipp_req *ipp.Request, ipp_op_name string) {
ipp_resp := ipp.NewResponse(ipp.StatusErrorOperationNotSupported, ipp_req.RequestId)
ippSendResponse(mod, client, ipp_resp)
mod.Warning("unhandled request from %v: operation=%s", client.RemoteAddr(), ipp_op_name)
}
func ippOnGetPrinterAttributes(mod *ZeroGod, client net.Conn, ipp_req *ipp.Request, srvHost string, srvPort int, srvTLS bool) {
ipp_resp := ipp.NewResponse(ipp.StatusOk, ipp_req.RequestId)
// https://tools.ietf.org/html/rfc2911 section 3.1.4.2 Response Operation Attributes
ipp_resp.OperationAttributes["attributes-charset"] = []ipp.Attribute{
{
Value: "utf-8",
Tag: ipp.TagCharset,
},
}
ipp_resp.OperationAttributes["attributes-natural-language"] = []ipp.Attribute{
{
Value: "en",
Tag: ipp.TagLanguage,
},
}
// rfc2911 section 4.4
ipp.AttributeTagMapping["printer-uri-supported"] = ipp.TagUri
ipp.AttributeTagMapping["uri-authentication-supported"] = ipp.TagKeyword
ipp.AttributeTagMapping["uri-security-supported"] = ipp.TagKeyword
ipp.AttributeTagMapping["printer-name"] = ipp.TagName
ipp.AttributeTagMapping["printer-info"] = ipp.TagText
ipp.AttributeTagMapping["printer-make-and-model"] = ipp.TagText
ipp.AttributeTagMapping["printer-state"] = ipp.TagEnum
ipp.AttributeTagMapping["printer-state-reasons"] = ipp.TagKeyword
ipp.AttributeTagMapping["ipp-versions-supported"] = ipp.TagKeyword
ipp.AttributeTagMapping["operations-supported"] = ipp.TagEnum
ipp.AttributeTagMapping["multiple-document-jobs-supported"] = ipp.TagBoolean
ipp.AttributeTagMapping["charset-configured"] = ipp.TagCharset
ipp.AttributeTagMapping["charset-supported"] = ipp.TagCharset
ipp.AttributeTagMapping["natural-language-configured"] = ipp.TagLanguage
ipp.AttributeTagMapping["generated-natural-language-supported"] = ipp.TagLanguage
ipp.AttributeTagMapping["document-format-default"] = ipp.TagMimeType
ipp.AttributeTagMapping["document-format-supported"] = ipp.TagMimeType
ipp.AttributeTagMapping["printer-is-accepting-jobs"] = ipp.TagBoolean
ipp.AttributeTagMapping["queued-job-count"] = ipp.TagInteger
ipp.AttributeTagMapping["pdl-override-supported"] = ipp.TagKeyword
ipp.AttributeTagMapping["printer-up-time"] = ipp.TagInteger
ipp.AttributeTagMapping["compression-supported"] = ipp.TagKeyword
ipp_resp.PrinterAttributes = []ipp.Attributes{
{
"printer-uri-supported": []ipp.Attribute{
{
Value: fmt.Sprintf("%s://%s:%d/printer", ops.Ternary(srvTLS, "ipps", "ipp"), srvHost, srvPort),
Tag: ipp.TagUri,
},
},
"uri-authentication-supported": []ipp.Attribute{
{
Value: "none",
Tag: ipp.TagKeyword,
},
},
"uri-security-supported": []ipp.Attribute{
{
Value: ops.Ternary(srvTLS, "tls", "none"),
Tag: ipp.TagKeyword,
},
},
"printer-name": []ipp.Attribute{
{
Value: "PRINTER_NAME",
Tag: ipp.TagName,
},
},
"printer-info": []ipp.Attribute{
{
Value: "PRINTER_INFO",
Tag: ipp.TagText,
},
},
"printer-make-and-model": []ipp.Attribute{
{
Value: "PRINTER_MAKE PRINTER_MODEL",
Tag: ipp.TagText,
},
},
"printer-state": []ipp.Attribute{
{
Value: 3, // idle
Tag: ipp.TagEnum,
},
},
"printer-state-reasons": []ipp.Attribute{
{
Value: "none",
Tag: ipp.TagKeyword,
},
},
"ipp-versions-supported": []ipp.Attribute{
{
Value: "1.1",
Tag: ipp.TagKeyword,
},
},
"operations-supported": []ipp.Attribute{
{
Value: []int{
0x0002, // print job (required by cups)
0x0004, // validate job (required by cups)
0x0008, // cancel job (required by cups)
0x0009, // get job attributes (required by cups)
0x000b, // get printer attributes
},
Tag: ipp.TagEnum,
},
},
"multiple-document-jobs-supported": []ipp.Attribute{
{
Value: false,
Tag: ipp.TagBoolean,
},
},
"charset-configured": []ipp.Attribute{
{
Value: "utf-8",
Tag: ipp.TagCharset,
},
},
"charset-supported": []ipp.Attribute{
{
Value: "utf-8",
Tag: ipp.TagCharset,
},
},
"natural-language-configured": []ipp.Attribute{
{
Value: "en",
Tag: ipp.TagLanguage,
},
},
"generated-natural-language-supported": []ipp.Attribute{
{
Value: "en",
Tag: ipp.TagLanguage,
},
},
"document-format-default": []ipp.Attribute{
{
Value: "application/pdf",
Tag: ipp.TagMimeType,
},
},
"document-format-supported": []ipp.Attribute{
{
Value: "application/pdf",
Tag: ipp.TagMimeType,
},
},
"printer-is-accepting-jobs": []ipp.Attribute{
{
Value: true,
Tag: ipp.TagBoolean,
},
},
"queued-job-count": []ipp.Attribute{
{
Value: 0,
Tag: ipp.TagInteger,
},
},
"pdl-override-supported": []ipp.Attribute{
{
Value: "not-attempted",
Tag: ipp.TagKeyword,
},
},
"printer-up-time": []ipp.Attribute{
{
Value: time.Now().Unix(),
Tag: ipp.TagInteger,
},
},
"compression-supported": []ipp.Attribute{
{
Value: "none",
Tag: ipp.TagKeyword,
},
},
},
}
ippSendResponse(mod, client, ipp_resp)
}

View file

@ -1,4 +1,4 @@
package mdns
package zerogod
import (
"fmt"
@ -7,7 +7,7 @@ import (
yaml "gopkg.in/yaml.v3"
)
func (mod *MDNSModule) save(address, filename string) error {
func (mod *ZeroGod) save(address, filename string) error {
if address == "" {
return fmt.Errorf("address cannot be empty")
}

View file

@ -1,4 +1,4 @@
package mdns
package zerogod
import (
"fmt"
@ -14,7 +14,7 @@ type entry struct {
services map[string]*zeroconf.ServiceEntry
}
func (mod *MDNSModule) show(filter string, withData bool) error {
func (mod *ZeroGod) show(filter string, withData bool) error {
fmt.Fprintf(mod.Session.Events.Stdout, "\n")
// convert to list for sorting

187
printer3.yml Normal file
View file

@ -0,0 +1,187 @@
EPSON\ XP-630\ Series-59F5BA-02._http._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-02
service: _http._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 80
text:
- ""
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-02._ipp._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-02
service: _ipp._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 631
text: []
ttl: 120
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-02._ipps._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-02
service: _ipps._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 631
text:
- txtvers=1
- ty=EPSON XP-630 Series
- usb_MFG=EPSON
- usb_MDL=XP-630 Series
- product=(EPSON XP-630 Series)
- pdl=application/octet-stream,image/pwg-raster,image/urf,image/jpeg
- rp=ipp/print
- qtotal=1
- Color=T
- Duplex=T
- Scan=T
- Fax=F
- kind=document,envelope,label,photo
- PaperMax=legal-A4
- URF=CP1,MT1-3-5-8-10-11-12,PQ4-5,OB9,OFU0,RS360,SRGB24,W8,DM3,IS1-7,V1.4
- mopria-certified=1.2
- priority=30
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- note=
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
- TLS=1.2
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-02._pdl-datastream._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-02
service: _pdl-datastream._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 9100
text:
- txtvers=1
- priority=40
- ty=EPSON XP-630 Series
- usb_MFG=EPSON
- usb_MDL=XP-630 Series
- product=(EPSON XP-630 Series)
- pdl=raw
- qtotal=1
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- note=
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-02._printer._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-02
service: _printer._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 515
text:
- txtvers=1
- priority=50
- ty=EPSON XP-630 Series
- usb_MFG=EPSON
- usb_MDL=XP-630 Series
- product=(EPSON XP-630 Series)
- pdl=raw
- rp=auto
- qtotal=1
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- note=
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-02._privet._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-02
service: _privet._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 80
text:
- txtvers=1
- ty=EPSON XP-630 Series (EPSON59F5BA)
- url=https://www.google.com/cloudprint
- type=printer
- id=0936a89f-33d7-80f5-c1bc-7421d40a78b5
- cs=offline
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-02._scanner._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-02
service: _scanner._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 1865
text:
- txtvers=1
- ty=EPSON XP-630 Series
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- mfg=EPSON
- mdl=XP-630 Series
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
- scannerAvailable=0
- note=
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-02._smb._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-02
service: _smb._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 445
text:
- ""
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-02._uscan._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-02
service: _uscan._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 443
text:
- txtvers=1
- vers=2.5
- representation=/PRESENTATION/AIRPRINT/PRINTER_128.PNG
- rs=eSCL
- ty=EPSON XP-630 Series
- pdl=application/pdf,image/jpeg
- cs=color,grayscale,binary
- is=platen
- duplex=F
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
- note=
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba

207
test.yml Normal file
View file

@ -0,0 +1,207 @@
EPSON\ XP-630\ Series-59F5BA-04._http._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-04
service: _http._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 80
text:
- ""
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-04._ipp._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-04
service: _ipp._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 6633
text:
- txtvers=1
- ty=EPSON XP-630 Series
- usb_MFG=EPSON
- usb_MDL=XP-630 Series
- product=(EPSON XP-630 Series)
- pdl=application/octet-stream,image/pwg-raster,image/urf,image/jpeg
- rp=ipp/print
- qtotal=1
- Color=T
- Duplex=T
- Scan=T
- Fax=F
- kind=document,envelope,label,photo
- PaperMax=legal-A4
- URF=CP1,MT1-3-5-8-10-11-12,PQ4-5,OB9,OFU0,RS360,SRGB24,W8,DM3,IS1-7,V1.4
- mopria-certified=1.2
- priority=30
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- note=
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
- TLS=1.2
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-04._ipps._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-04
service: _ipps._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 6631
text:
- txtvers=1
- ty=EPSON XP-630 Series
- usb_MFG=EPSON
- usb_MDL=XP-630 Series
- product=(EPSON XP-630 Series)
- pdl=application/octet-stream,image/pwg-raster,image/urf,image/jpeg
- rp=ipp/print
- qtotal=1
- Color=T
- Duplex=T
- Scan=T
- Fax=F
- kind=document,envelope,label,photo
- PaperMax=legal-A4
- URF=CP1,MT1-3-5-8-10-11-12,PQ4-5,OB9,OFU0,RS360,SRGB24,W8,DM3,IS1-7,V1.4
- mopria-certified=1.2
- priority=30
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- note=
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
- TLS=1.2
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-04._pdl-datastream._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-04
service: _pdl-datastream._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 9100
text:
- txtvers=1
- priority=40
- ty=EPSON XP-630 Series
- usb_MFG=EPSON
- usb_MDL=XP-630 Series
- product=(EPSON XP-630 Series)
- pdl=raw
- qtotal=1
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- note=
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-04._printer._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-04
service: _printer._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 1515
text:
- txtvers=1
- priority=50
- ty=EPSON XP-630 Series
- usb_MFG=EPSON
- usb_MDL=XP-630 Series
- product=(EPSON XP-630 Series)
- pdl=raw
- rp=auto
- qtotal=1
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- note=
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-04._privet._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-04
service: _privet._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 8081
text:
- txtvers=1
- ty=EPSON XP-630 Series (EPSON59F5BA)
- url=https://www.google.com/cloudprint
- type=printer
- id=0936a89f-33d7-80f5-c1bc-7421d40a78b5
- cs=offline
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-04._scanner._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-04
service: _scanner._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 1865
text:
- txtvers=1
- ty=EPSON XP-630 Series
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- mfg=EPSON
- mdl=XP-630 Series
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
- scannerAvailable=0
- note=
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-04._smb._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-04
service: _smb._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 1445
text: []
ttl: 120
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba
EPSON\ XP-630\ Series-59F5BA-04._uscan._tcp.local.:
servicerecord:
instance: EPSON\ XP-630\ Series-59F5BA-04
service: _uscan._tcp
domain: local.
hostname: EPSON59F5BA.local.
port: 8443
text:
- txtvers=1
- vers=2.5
- representation=/PRESENTATION/AIRPRINT/PRINTER_128.PNG
- rs=eSCL
- ty=EPSON XP-630 Series
- pdl=application/pdf,image/jpeg
- cs=color,grayscale,binary
- is=platen
- duplex=F
- adminurl=http://EPSON59F5BA.local.:80/PRESENTATION/BONJOUR
- UUID=cfe92100-67c4-11d4-a45f-44d24459f5ba
- note=
ttl: 4500
addripv4:
- 192.168.50.21
addripv6:
- fe80::46d2:44ff:fe59:f5ba