mirror of
https://github.com/bettercap/bettercap
synced 2025-07-05 12:36:40 -07:00
misc: small fix or general refactoring i did not bother commenting
This commit is contained in:
parent
91d360327a
commit
51a5b4ad6e
17 changed files with 1375 additions and 239 deletions
125
epson.yml
Normal file
125
epson.yml
Normal 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
3
go.mod
|
@ -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
2
go.sum
|
@ -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=
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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))
|
||||
|
|
|
@ -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()
|
||||
|
|
109
modules/zerogod/zerogod_acceptor.go
Normal file
109
modules/zerogod/zerogod_acceptor.go
Normal 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)
|
||||
}
|
197
modules/zerogod/zerogod_advertise.go
Normal file
197
modules/zerogod/zerogod_advertise.go
Normal 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
|
||||
}
|
|
@ -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()
|
72
modules/zerogod/zerogod_endpoint_update.go
Normal file
72
modules/zerogod/zerogod_endpoint_update.go
Normal 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)
|
||||
}
|
69
modules/zerogod/zerogod_generic_handler.go
Normal file
69
modules/zerogod/zerogod_generic_handler.go
Normal 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]))
|
||||
}
|
||||
}
|
||||
}
|
355
modules/zerogod/zerogod_ipp_handler.go
Normal file
355
modules/zerogod/zerogod_ipp_handler.go
Normal 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)
|
||||
}
|
|
@ -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")
|
||||
}
|
|
@ -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
187
printer3.yml
Normal 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
207
test.yml
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue