I need to send a FIN packet to close a connection having IP and ports information (plus other informations from previus packets).
I've seen that is possbile to craft a new connection through a 3-way-handshake (see 3 way handshake in Scapy), but nothing on connection closure.
As stated by the RFC you need to send a FIN segment then wait for the endpoint's acknowledgment (ACK) + FIN segment and then send a last ACK segment for it.
Here is a simple example using Scapy:
from scapy.all import *
conf.L3socket=L3RawSocket
sport=10000
dport=45000
pkt=IP(src="1.2.3.4", dst="4.5.6.7")
SYN=pkt/TCP(sport=sport, dport=dport, flags="S")
SYNACK=sr1(SYN)
ACK=pkt/TCP(sport=sport, dport=dport, flags="A", seq=SYNACK.ack, ack=SYNACK.seq + 1)
send(ACK)
# ...
FIN=pkt/TCP(sport=sport, dport=dport, flags="FA", seq=SYNACK.ack, ack=SYNACK.seq + 1)
FINACK=sr1(FIN)
LASTACK=pkt/TCP(sport=sport, dport=dport, flags="A", seq=FINACK.ack, ack=FINACK.seq + 1)
send(LASTACK)
Related
I'm trying to do a pretty weird thing with Python/Scapy/Socket (Linux env). I'd like to manage the 3-way handshake and then go back to the usual "socket" management.
Here is what I did:
import socket
from scapy.all import *
pkt = IP(src='192.168.1.2',dst='192.168.1.1')/TCP(sport=12345,dport=44144,flags='S',seq=1000)
SYN = bytes(pkt)
outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
outs.connect(('192.168.1.1',44144))
outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
outs.sendto(SYN, ('192.168.1.1', 0))
raw_buffer = outs.recv(4096)
buffer = IP(raw_buffer)
my_ack = buffer.seq + 1
pkt=IP(src='192.168.1.2',dst='192.168.1.1')/TCP(sport=12345, dport=44144, flags='A', seq=1001, ack=my_ack)
ACK=bytes(pkt)
outs.sendto(ACK, ('192.168.1.1', 0))
So far so good, the connection is established. Then I try to use the socket and the created connection with the usual "send" method:
outs.send(bytes('AAA','utf8'))
At this point I get an error:
*** OSError: [Errno 22] Invalid argument
So, what I'm trying to do is to switch back from a RAW_SOCKET to a system handled one. Is that possible in some ways?
Thanks,
Here is my code:
ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, 3)
ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
ins.bind((interface_name, 3))
while True:
fmt = "B"*7+"I"*21
pkt, sa_ll = self.ins.recvfrom(65535)
x = struct.unpack(fmt, ins.getsockopt(socket.IPPROTO_TCP, socket.TCP_INFO, 92))
print "===>",x
print "HEX Packet",hexlify(pkt)
process_ipframe(sa_ll[2],hexlify(pkt))
Getting socket.error: [Errno 92] Protocol not available error. Or is there any better way to get the TCP(Need only ESTAB connctions) states for the connections.
Ok, my requirement is to get the established connections. But I was sniffing traffic on the interface for other purpose. So, I though I could get TCP states from raw sockets. But I found /proc/net/tcp: there is st field, from that I can get ESTABLISHED connections. So, I should read /proc/net/tcp continuously to get ESTAB for a specific time in different thread.
So, the answer is /proc/net/tcp. Check this question. or may I should use netfilter
#!/usr/bin/python
from scapy.all import *
def findWeb():
a = sr1(IP(dst="8.8.8.8")/UDP()/DNS(qd=DNSQR(qname="www.google.com")),verbose=0)
return a[DNSRR].rdata
def sendPacket(dst,src):
ip = IP(dst = dst)
SYN = TCP(sport=1500, dport=80, flags='S')
SYNACK = sr1(ip/SYN)
my_ack = SYNACK.seq + 1
ACK = TCP(sport=1050, dport=80, flags='A', ack=my_ack)
send(ip/ACK)
payload = "stuff"
PUSH = TCP(sport=1050, dport=80, flags='PA', seq=11, ack=my_ack)
send(ip/PUSH/payload)
http = sr1(ip/TCP()/'GET /index.html HTTP/1.0 \n\n',verbose=0)
print http.show()
src = '10.0.0.24'
dst = findWeb()
sendPacket(dst,src)
I'm trying to do HTTP packets with SCAPY
I am using UBUNTU on VMwaer
The problem is that every time I send messages I have RESET
How do we fix it?
Thanks
sniff package image
Few things I notice wrong.
1. You have your sequence number set statically (seq=11) which is wrong. Sequence numbers are always randomly generated and they must be used as per RFC793. So the sequence should be = SYNACK[TCP].ack
You set your source port as 1500 during SYN packet, but then you use it as 1050 (typo?)
You don't need extra payload/PUSH.
Also, have a look at these threads:
How to create HTTP GET request Scapy?
Python-Scapy or the like-How can I create an HTTP GET request at the packet level
I need to create HTTP GET request and save the data response.
I tried to use this:
syn = IP(dst=URL) / TCP(dport=80, flags='S')
syn_ack = sr1(syn)
getStr = 'GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n'
request = IP(dst='www.google.com') / TCP(dport=80, sport=syn_ack[TCP].dport,
seq=syn_ack[TCP].ack, ack=syn_ack[TCP].seq + 1, flags='A') / getStr
reply = sr1(request)
print reply.show()
But when I print reply I don't see any data response.
In addition, when I checked in 'Wireshark' I got SYN, SYN/ACK but I didn't get an ACK.
Image:
Edit:
I try to do that now:
# Import scapy
from scapy.all import *
# Print info header
print "[*] ACK-GET example -- Thijs 'Thice' Bosschert, 06-06-2011"
# Prepare GET statement
get='GET / HTTP/1.0\n\n'
# Set up target IP
ip=IP(dst="www.google.com")
# Generate random source port number
port=RandNum(1024,65535)
# Create SYN packet
SYN=ip/TCP(sport=port, dport=80, flags="S", seq=42)
# Send SYN and receive SYN,ACK
print "\n[*] Sending SYN packet"
SYNACK=sr1(SYN)
# Create ACK with GET request
ACK=ip/TCP(sport=SYNACK.dport, dport=80, flags="A", seq=SYNACK.ack, ack=SYNACK.seq + 1) / get
# SEND our ACK-GET request
print "\n[*] Sending ACK-GET packet"
reply,error=sr(ACK)
# print reply from server
print "\n[*] Reply from server:"
print reply.show()
print '\n[*] Done!'
but its print me in reply from server;
0000 IP / TCP 192.168.44.130:23181 > 216.58.208.164:http A / Raw ==>
IP / TCP 216.58.208.164:http > 192.168.44.130:23181 A / Padding None
And I need Line-based text data: text/html.
You are sending a RST segment in response to the SYN-ACK because your kernel has no knowledge of the SYN you sent via Scapy (see here). This could be solved with an iptable rule:
iptables -A OUTPUT -p tcp --tcp-flags RST RST -s <your ip> -j DROP
Because you are ending the connection with that RST segment, when you send your HTTP request, the endpoint answers with a RST too because connection is not established and so you are using show() on a RST segment with no data, that is why you do not see anything.
You are sending a SYN and correctly receiving a SYN_ACK. At this point, you should generate and send an ACK based on the SYN_ACK that you've received, and THEN finally transmit the HTTP GET request. It seems that you are somewhat confused about the TCP 3-way handshake mechanism. In short, you are not supposed to 'get' an ACK, you are supposed to generate and send this yourself.
After setting the rule in your iptables as has been suggested above, you could do the following :
from scapy.all import *
seq = 12345
sport = 1040
dport = 80
ip_packet = IP(dst='192.168.56.107')
syn_packet = TCP(sport=sport, dport=dport, flags='S', seq=seq)
packet = ip_packet/syn_packet
synack_response = sr1(packet)
next_seq = seq + 1
my_ack = synack_response.seq + 1
ack_packet = TCP(sport=sport, dport=dport, flags='A', seq=next_seq, ack=my_ack)
send(ip_packet/ack_packet)
payload_packet = TCP(sport=sport, dport=dport, flags='A', seq=next_seq, ack=my_ack)
payload = "GET / HTTP/1.0\r\nHOST: 192.168.56.107\r\n\r\n"
reply, error = sr(ip_packet/payload_packet/payload, multi=1, timeout=1)
for r in reply:
r[0].show2()
r[1].show2()
Hope this helps. Basically, the first response you get back does not really hold the HTTP response data. I tested the script against an INETSIM simulated HTTP server and in that case (at least) the first packet (after the 3-way TCP handshake) that the server responded with was a series of NULL (0x00) bytes. Hence using multi somehow did the stuff in my case.
I am trying to make an IRC bot, but it keeps timing out after 240 seconds. How can I fix this?
import socket
host = 'test'
port = 6667
channel = '#test'
nick = "test"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send('NICK ' + str(nick) + ' \n\r')
s.send('USER v v v :v Script' + '\r\n')
s.send('JOIN '+channel+' \n\r')
while True:
command = s.recv(4096)
print command
You aren't replying to ping requests from the server.
When you're idle for a long time, the server thinks the connection is dead, and sends a ping request, you need to reply with pong (and whatever the server sent to you after the ping). So if the server sent you this, that should be your reply:
PING :HELLO_WORLD
PONG :HELLO_WORLD
Without that, the server will confirm the link is dead and terminate the connection.
You could try using irclib- however hat is happening,most likely, is that you are not replying to the server's PING message.
Whenever a received message starts with "PING", you have to reply it with a "PONG" message containg the word PONG and your program name (and optionally host) - leaving an space after "PONG".
Check the full IRC specifcations for PING and PONG messages, and take a look onother things ou might be missing along your experiments: http://www.irchelp.org/irchelp/rfc/rfc.html
My problem was that I wasn't even reliably receiving PING packets from the IRC server. I fixed it by adding keepalives at the socket level:
# enable keepalives at the socket (SOL_SOCKET) level
self.client.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
# after 1 second of TCP inactivity, trigger keepalive pings
self.client.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 1)
# send a keepalive ping every 60 seconds
self.client.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 60)
# quit after 5 consecutive failures
self.client.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)
That, combined with sending back a PONG for each PING, is keeping my connection open longer.