Understanding the Scapy "Mac address to reach destination not found. Using broadcast." warning - scapy

If I generate an Ethernet frame without any upper layers payload and send it at layer two with sendp(), then I receive the "Mac address to reach destination not found. Using broadcast." warning and frame put to wire indeed uses ff:ff:ff:ff:ff:ff as a destination MAC address. Why is this so? Shouldn't the Scapy send exactly the frame I constructed?
My crafted package can be seen below:
>>> ls(x)
dst : DestMACField = '01:00:0c:cc:cc:cc' (None)
src : SourceMACField = '00:11:22:33:44:55' (None)
type : XShortEnumField = 0 (0)
>>> sendp(x, iface="eth0")
WARNING: Mac address to reach destination not found. Using broadcast.
.
Sent 1 packets.
>>>

Most people encountering this issue are incorrectly using send() (or sr(), sr1(), srloop()) instead of sendp() (or srp(), srp1(), srploop()). For the record, the "without-p" functions like send() are for sending layer 3 packets (send(IP())) while the "with-p" variants are for sending layer 2 packets (sendp(Ether() / IP())).
If you define x like I do below and use sendp() (and not send()) and you still have this issue, you should probably try with the latest version from the project's git repository (see https://github.com/secdev/scapy).
I've tried:
>>> x = Ether(src='01:00:0c:cc:cc:cc', dst='00:11:22:33:44:55')
>>> ls(x)
dst : DestMACField = '00:11:22:33:44:55' (None)
src : SourceMACField = '01:00:0c:cc:cc:cc' (None)
type : XShortEnumField = 0 (0)
>>> sendp(x, iface='eth0')
.
Sent 1 packets.
At the same time I was running tcpdump:
# tcpdump -eni eth0 ether host 00:11:22:33:44:55
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
12:33:47.774570 01:00:0c:cc:cc:cc > 00:11:22:33:44:55, 802.3, length 14: [|llc]

Related

IP addressing of the equipment behind the router for SNMP

I am trying to develop a Traps receiver for SNMPv1 and SNMPv2c with OpenVPN. I have used the PURESNMP and PYSNMP libraries with Python. PYSNMP can receive SNMPv1 and SNMPv2c Traps, while PURESNMP only works with SNMPv2c. My project works as follows: the OpenVPN file is loaded into a Router so that it can connect, and several devices are connected behind the Router to be monitored by SNMP.
OpenVPN Router IP: 10.8.0.18,
LAN Router IP: 192.168.2.1
Team A IP: 192.168.2.3
OpenVPN Server IP: 10.8.0.1
Client2 IP: 10.8.0.10
I manage to receive the Traps, but I cannot distinguish where the information comes from, if in the LAN behind the Router how is it possible to identify from which the alarm came. This is the Team's SNMPv1 Trap response:
Agent is listening SNMP Trap on 10.8.0.10 , Port : 162
-------------------------------------------------- ------------------------
SourceIP: ('10.8.0.18', 49181)
----------------------Received new Trap message------------------------ ---
1.3.6.1.2.1.1.3.0 = 910296
1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.4.1.1918.2.13.0.700
1.3.6.1.6.3.18.1.3.0 = 10.168.2.3
1.3.6.1.6.3.18.1.4.0 = public
1.3.6.1.6.3.1.1.4.3.0 = 1.3.6.1.4.1.1918.2.13
1.3.6.1.4.1.1918.2.13.10.111.12.0 = 1
1.3.6.1.4.1.1918.2.13.10.111.10.0 = 3
1.3.6.1.4.1.1918.2.13.10.111.11.0 = Digital Input 1
1.3.6.1.4.1.1918.2.13.10.111.14.0 = 4
1.3.6.1.4.1.1918.2.13.10.10.40.0 = System Location
1.3.6.1.4.1.1918.2.13.10.10.50.0 = SiteName
1.3.6.1.4.1.1918.2.13.10.10.60.0 = SiteAddress
1.3.6.1.4.1.1918.2.13.10.111.13.0 = Input D01 Disconnected.
In “IP Source”, a function is used to obtain the source IP, but it shows me the IP of the Router and not of the device that is alarmed. If you look at the third line of the traps, it indicates a source IP that the SNMPV1 protocol itself has incorporated:
1.3.6.1.6.3.18.1.3.0 = 10.168.2.3
But it is not from the device or from the Router, it is as if the Router's network segment had been mixed with the device's hots segment. This is the response when receiving SNMPv2c Traps:
Agent is listening SNMP Trap on 10.8.0.10 , Port : 162
-------------------------------------------------- --------------------------
SourceIP: ('10.8.0.18', 49180)
----------------------Received new Trap message------------------------ -----
1.3.6.1.2.1.1.3.0 = 896022
1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.4.1.1918.2.13.20.700
1.3.6.1.4.1.1918.2.13.10.111.12.0 = 1
1.3.6.1.4.1.1918.2.13.10.111.10.0 = 3
1.3.6.1.4.1.1918.2.13.10.111.11.0 = Digital Input 1
1.3.6.1.4.1.1918.2.13.10.111.14.0 = 5
1.3.6.1.4.1.1918.2.13.10.10.40.0 = System Location
1.3.6.1.4.1.1918.2.13.10.10.50.0 = SiteName
1.3.6.1.4.1.1918.2.13.10.10.60.0 = SiteAddress
1.3.6.1.4.1.1918.2.13.10.111.13.0 = Input D01 Disconnected.
In Trap SNMPv2c, you can only get the source IP but it shows the IP of the Router, but it does not work for me since there are several devices behind the Router, and there is no way to identify which one the alarm came from. I am doing the tests from an OpenVPN client, and not yet from the server, it will be uploaded to the server once it works well.
Could you help me because that can happen. Since I thought it was a problem with the libraries and I used another trap receiving software and the answer was the same.
This is the Server configuration:
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh none
server 10.8.0.0 255.255.0.0
ifconfig-pool-persist /var/log/openvpn/ipp.txt
client-config-dir ccd
route 192.168.0.0 255.255.0.0
keepalive 10 120
tls-crypt ta.key
cipher AES-256-GCM
auth SHA256
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
verb 3
explicit-exit-notify 1
This is the client configuration:
client
dev tun
proto udp
remote x.x.x.x 1194
resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-GCM
auth SHA256
key-direction 1
verb 3
<ca>
</ca>
<cert>
</cert>
<key>
</key>
<tls-crypt>
#
#
</tls-crypt>
Firewall configuration on the server:
# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
# Allow traffic from OpenVPN client to eth0 (change to the interface you discovered!)
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
COMMIT
# END OPENVPN RULES
This is the code to Receive SNMPv1 and SNMPv2c Traps:
from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcher
#python snmp trap receiver
from pysnmp.entity import engine, config
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.entity.rfc3413 import ntfrcv
from pysnmp.proto import api
datosnmp = []
snmpEngine = engine.SnmpEngine()
TrapAgentAddress='10.8.0.10' #Trap listerner address
Port=162 #trap listerner port
print("Agent is listening SNMP Trap on "+TrapAgentAddress+" , Port : " +str(Port))
print('--------------------------------------------------------------------------')
config.addTransport(snmpEngine, udp.domainName + (1,), udp.UdpTransport().openServerMode((TrapAgentAddress, Port)))
#Configure community here
config.addV1System(snmpEngine, 'my-area', 'public')
def cbFun(snmpEngine, stateReference, contextEngineId, contextName,varBinds, cbCtx):
global datosnmp
#while wholeMsg:
execContext = snmpEngine.observer.getExecutionContext('rfc3412.receiveMessage:request')
print("IP Source: ", execContext['transportAddress']) #IP Origen del Trap
#print('snmpEngine : {0}'.format(snmpEngine))
#print('stateReference : {0}'.format(stateReference))
#print('contextEngineId : {0}'.format(contextEngineId))
#print('contextName : {0}'.format(contextName))
#print('cbCtx : {0}'.format(cbCtx))
print('{0}Received new Trap message{0}\n'.format('-' * 40))
for oid, val in varBinds:
datosnmp.append(val.prettyPrint())
print('%s = %s' % (oid.prettyPrint(), val.prettyPrint())) #name = OID, val = contenido de la OID
#print(datosnmp)
ntfrcv.NotificationReceiver(snmpEngine, cbFun)
snmpEngine.transportDispatcher.jobStarted(1)
try:
snmpEngine.transportDispatcher.runDispatcher()
except:
snmpEngine.transportDispatcher.closeDispatcher()
raise
Could you please help me if it could be a configuration error of the OpenVPN server, or maybe something else needs to be added. Have you seen a similar lake?
Any comment is appreciated.

ACK packets forged issues: "This frame is a (suspected) retransmission"

I'm playing with scapy. I'm trying to forge JUST PSH/ACK and ACK packets in sequence
I coded two tools: A which sends PSH/ACK packets and then sniffs the resulting ACK, writing the sequence in a file to use it later
.....
bitack = random.randrange(1,656787969)
bitseq = random.randrange(1,4294967295)
if os.path.exists('test.txt'):
with open('test.txt','r') as f:
bitseq = int(f.read())
else:
with open('test.txt','w') as f:
f.write(str(bitseq))
.....
text = "Ok"
TSval = int(time.time())
TSecr = TSval
acker = IP(src="127.0.0.1",dst=destinazione"127.0.0.1")/TCP(sport=88,dport=8888,
flags="PA", seq=bitseq, ack=bitack, options=[('Timestamp', (TSval, TSecr))])/text
send(acker)
.....
rx = sniff(filter="host 127.0.0.1 and src port 8888", iface="lo", count=1)
seqcc = rx[0].getlayer(TCP).seq
ackcc = rx[0].getlayer(TCP).ack
with open('test.txt','w') as f:
f.write(str(ackcc))
print("SEQFINALE=", ackcc)
B: which sends ACK packets AFTER it sniffs a PSH/ACK packet from A. I know the ack packets contain text ( in this example the same of A), but this is what I want
....
rx = sniff(filter="host 127.0.0.1 and dst port 8888", iface="lo", count=1)
seqcc = rx[0].getlayer(TCP).seq
print("seq:", seqcc)
ackcc = rx[0].getlayer(TCP).ack
print("ack:", ackcc)
var = rx[0][Raw].load.decode(encoding='utf-8', errors='ignore')
acker = IP(src="127.0.0.1",dst="127.0.0.1")/TCP(sport=8888,dport=88, flags="A",
seq=ackcc, ack=seqcc + int(len(var)), options=[('Timestamp', (TSval, TSecr))])/var
send(acker)
.....
Everything works fine expect that wireshark gives some warning and I don't understand why:
"Expert Info (Note/Sequence): This frame is a (suspected) retransmission"
The first two packets are perfect:
Is there any issue in how I handle the sequence number/ ack number?
This makes me crazy
It is a retransmission. Your capture shows a frame from 8888 to 88 at seq=1 with 52 bytes of data (len=52). If you ever send another frame from 8888 to 88 at seq=1, it's a retransmission. TCP streams are in a single direction: A sends to B, B ACK's what A sent. (in this case, there should be an ACK=53 in a frame from 88 to 8888, either alone or piggybacking data.)

Cannot read tls section even after calling load_layer('tls') in scapy

This question explains how to read the TLS section of a packet using scapy.
However, my program is not able to read it. All it returns is a bunch of hexadecimal characters
>>> from scapy.all import *
>>> load_layer('tls')
>>> cap = rdpcap('tls.pcap')
>>> p1=cap[0]
>>> p1
<Ether dst=14:cc:20:51:33:ea src=f4:f2:6d:93:51:f1 type=0x800 |<IP version=4 ihl=5 tos=0x0 len=146 id=62970 flags=DF frag=0 ttl=64 proto=tcp chksum=0x50a0 src=192.168.1.143 dst=54.254.250.149 |<TCP sport=49335 dport=50443 seq=549695462 ack=200962336 dataofs=5 reserved=0 flags=PA window=4380 chksum=0xb0ac urgptr=0 |<Raw load="\x17\x03\x01\x00 \xf2\x10\xfd\x95N'\xf2\xaf\x99tp\x93\xbc\xe9\x81w\x91\x1b\xe0\xc9M:\x9a!]\xb0!\xae\xd2\x86\xb0>\x17\x03\x01\x00#d>\x0b\xee\xf0\xab\xded\x02E)\x0e0\xbb\xe6\x82uU\xb22\x87\xd6\xe4n[\x1d\x18\xe8\xd6\x1c\x00N_C\xe6\xdd\xbe\x89#6p\xd9\xaf\x19\xb3s\x07H\xdeF\x88\xdar\x0f\x8a\n!4\xeb\xd3F\xefgH" |>>>>
I want to get the tls record version, tls record length and the tls record content type.
This is screenshot of the packet opened in wireshark.
Can somepne please show me what I am doing wrong and how to read the tls content properly?
I am using Python3.6, and thus am not able to use stable scapy-ssl_tls, which is currently limited to Python 2.
You are so close. You just need to use TLS(pkt.load).
Download a TLS Capture
For this example, use this tls capture from Wireshark's Bugzilla.
We can see that packet 4 is the TLS Client Hello:
tshark -r DNS-over-TLS.pcapng -Y "frame.number==4"
4 0.122267 133.93.28.45 → li280-151.members.linode.com TLSv1 384 Client
Hello 00:00:5e:00:01:18 ← 48:d7:05:df:86:0b
Load with Scapy
Make sure that you have the cryptography library installed, as it's required for loading TLS captures.
>>> import cryptography
>>> # No errors
Reproducing what you have so far with this capture:
>>> from scapy.all import *
>>> load_layer('tls')
>>> cap = rdpcap('DNS-over-TLS.pcapng')
>>> tls_client_hello=cap[3] # Wireshark numbers packets starting at 1, scapy at 0
>>> tls_client_hello
<Ether dst=14:cc:20:51:33:ea src=f4:f2:6d:93:51:f1 type=0x800 |<IP version=4
ihl=5 tos=0x0 len=146 id=62970 flags=DF frag=0 ttl=64 proto=tcp chksum=0x50a0
src=192.168.1.143 dst=54.254.250.149 |<TCP sport=49335 dport=50443 seq=549695462
ack=200962336 dataofs=5 reserved=0 flags=PA window=4380 chksum=0xb0ac urgptr=0 |
<Raw load="\x17\x03\x01\x00
\xf2\x10\xfd\x95N'\xf2\xaf\x99tp\x93\xbc\xe9\x81w\x91\x1b\xe0\xc9M:\x9a!]\xb0!\xa
e\xd2\x86\xb0>\x17\x03\x01\x00#d>\x0b\xee\xf0\xab\xded\x02E)\x0e0\xbb\xe6\x82uU\x
b22\x87\xd6\xe4n[\x1d\x18\xe8\xd6\x1c\x00N_C\xe6\xdd\xbe\x89#6p\xd9\xaf\x19\xb3s\
x07H\xdeF\x88\xdar\x0f\x8a\n!4\xeb\xd3F\xefgH" |>>>>
Note that the part that we want to view is called Raw load. To access this part of the packet, you use tls_client_hello.load. Keep in mind that TLS will take a bytes object that contains the data, but not an entire packet.
>>> TLS(tls_client_hello.load)
<TLS type=handshake version=TLS 1.0 len=313 iv=b'' msg=[<TLSClientHello
msgtype=client_hello msglen=309 version=TLS 1.2 gmt_unix_time=Tue, 18 May 2077
23:20:52 +0000 (3388605652)
random_bytes=d6d533aca04dca42db8b123b0a143dcd580079147122e4de095c15cf sidlen=0
sid='' cipherslen=182 ciphers=[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
< TLS output truncated ... >
Further Reading
I highly recommend looking at Scapy TLS Notebooks that do a good job of documenting scapy+TLS usage.

icmp response for ip options

How should I do it?
I have written a new IP Option field in the scapy 2.4 source code (scapy.layers.inet).
class IPOption_Ex(IPOption):
name = "IP Option Ex"
copy_flag = 1
option = 26
fields_desc = [_IPOption_HDR,
ByteField("op1", 16),
ShortField("op2", 0),
ShortField("op3", 0),
IPField("originator_ip", "0.0.0.0"),
LongField("op4", 0)]
It is just L3 level option so it does not involve TCP or UDP. Whenever the destination receives the new IP Option (say 26) I want a response ICMP packet (type 45). Say the response ICMP packet has four fields: 1.Type 2.Code 3.Checksum 4.source IP address. (scapy.layers.inet)
class ICMP(Packet):
name = "ICMP"
fields_desc = [ ByteEnumField("type",8, icmptypes),
MultiEnumField("code",0, icmpcodes, depends_on=lambda pkt:pkt.type,fmt="B"),
XShortField("chksum", None),
ConditionalField(IPField("originator_ip","0.0.0.0"), lambda pkt:pkt.type==45)]
Now what I don't understand how to write code in python/scapy to generate ICMP type-45 response packet from the destination and where to write in scapy source code?
You just need
IPOption_Ex.register_variant()
You'll then have
IP(options=[IPOption(option=26)])
working

snmp cisco switch oid for multiVlans

I'm using snmp to go through a switch and get some info.
i use:
for searching Names :
Oid: iso.3.6.1.2.1.2.2.1.2
for searching a Single Vlan:
Oid: iso.3.6.1.4.1.9.9.68.1.2.2.1.2
What i want is for multiple Vlans what is the oid.
Does anyone knows?
The Cisco OID referred to in your post will give you the VLAN-id associated on each interface on the device. For example snmpwalk yields following (so you can get all VLANs associated with the interfaces on the device)
# snmpwalk -v2c -c public 172.23.219.36 1.3.6.1.4.1.9.9.68.1.2.2.1.2
..
SNMPv2-SMI::enterprises.9.9.68.1.2.2.1.2.436217344 = INTEGER: 101
Taking ifIndex from VLAN 101 one can find the associated interface
# snmpwalk -v2c -c public 172.23.219.36 1.3.6.1.2.1.2.2.1.2.436217344
..
IF-MIB::ifDescr.436217344 = STRING: Ethernet1/20
However if you are only interested in getting VLANs on the system you may want to consider looking at Q-BRIDGE-MIB (https://www.rfc-editor.org/rfc/rfc4363). Any of these OIDs will get all the VLANs on the system whether associated with an interface or not via Q-BRIDGE MIB (dot1qFdbTable)
snmpwalk -v2c -c public 172.23.219.36 1.3.6.1.2.1.17.7.1.2
SNMPv2-SMI::mib-2.17.7.1.2.1.1.2.1 = Counter32: 0
SNMPv2-SMI::mib-2.17.7.1.2.1.1.2.101 = Counter32: 0
SNMPv2-SMI::mib-2.17.7.1.2.1.1.2.201 = Counter32: 0
SNMPv2-SMI::mib-2.17.7.1.2.1.1.2.301 = Counter32: 0

Resources