traffic forwarding with scapy between two interfaces - scapy

Hello I want to forward traffic between two interfaces to manipulate the packages between them (mitm). Here is my code:
from scapy.all import *
interfaces = {
"plc": "ens19",
"io": "ens20"
}
def pkt_PLC(pkt):
return True
def pkt_IO(pkt):
return True
def bridge():
bridge_and_sniff(interfaces["plc"], interfaces["io"],
xfrm12=pkt_PLC, xfrm21=pkt_io,
count=0, store=0)
if __name__ == "__main__":
conf.sniff_promisc=True
bridge()
The script is working and forwarding the traffic. My Problem is know that through the two interfaces is running are large amount of packages and the connection is not allowed to stop. My Problem is know that when i am looking at wireshark i can see that the connection is at points cut because not all the traffic is forwarded ,and so the application from which i am getting the traffic is stopped, after the short stop the traffic is again re transmitted. The process with stoping and res transmitting is repeated all the time. Ifthink
The setup is an industrial control station which is communicating with provinet. The component which i am siting between is the plc and and the rest of the system. When the system is starting it builds a connection with the rest of its components over profinet and continuously sends after that packages with profinet. Now if the communication is cut one needs to reset the error messages that the system can run again. Per second are about 3000 packages transmited.

Related

Designing a DSR load balancer

I want to build a DSR load balancer for an application I am writing. I wont go into the application because it is irrelevant for this discussion. My goal is to create a simple load balancer that does direct server response for TCP packets. The idea is to receive all packets at the load balancer, then using something like round robin, select a server from a list of available servers which are defined in some config file. The next step would be to alter the packer received and change the destination ip to be equal to the chosen backend server. Finally, the packet will be sent over to the backend server using normal system calls for sending packets. Theoretically the backend server should receive the packet, and send one back to the original requester, and then the requester can communicate directly with the backend server rather than going through the load balancer.
I am concerned that this design will not work as I expect it to. The main question is, what happens when computer A send a packet to IP Y, but receives a packet back in the same TCP stream from a computer at IP X? Will it continue to send packets to IP Y? Or will it switch over to IP X?
So it turns out this is possible, but only halfway so, and I will explain what I mean by this. I have three processes, one which is netcat, used to initiate an tcp request, a second process, the dsr-lb, which receives packets on a certain port, changes the destination ip to a backend server(passed in via command line arg), and forwards it off using raw sockets, and a third process which is a basic echo server. I got this working on a local setup. The local setup consists of netcat running on my desktop, and dsr-lb and echo servers running on two different linux VMs on the desktop as well. The path of the packets was like this:
nc -> dsr-lb -> echo -> nc
When I said it only half works, what I meant was that outgoing traffic has to always go through the dsr-lb, but returning traffic can go directly to the client. The client does not send further traffic directly to the backend server, but still goes through the dsr-lb. This makes sense since the client opened a socket to the dsr-lb ip, and internally still remembers this ip, regardless of where the packet came from.
The comment saying "if its from a different IP, it's not the same stream. tcp is connection-based" is incorrect. I read through the linux source code, specifically the receive tcp packet portion, and it turns out that linux uses source ip, source port, destination ip, and destination port to calculate a hash which is uses to find the socket that should receive the traffic. However, if no such socket matches the hash, it tries again using only the destination ip and destination port and that is how this "magic" works. I have no idea if this would work on a windows machine though.
One caveat to this answer is that I also spun up two remote VMs and tried the same experiment, and it did not work. I am guessing it worked while all the machines were on the same switch, but there might be a little more work to do to get it to work if it goes through different routers. I am still trying to figure this out, but from using tcpdump to analyze the traffic, for some reason the dsr-lb is forwarding to the wrong port on the echo server. I am not sure if something is corrupted, or if the checksum is wrong after changing the destination ip and some router along the way is dropping it or changing it somehow(I suspect this might be the case) but hopefully I can get it working over an actual network.
The theory should still hold though. The IP layer is basically a packet forwarding layer and routers should not care about the contents of the packets, they should just forward packets based on their routing tables, so changing the destination of the packet while leaving the source the same should result in the source receiving any answer. The fact that the linux kernel ultimately resolves packets to sockets just using destination ip and port means the only real roadblock to this working does not really exist.
Also, if anyone is wondering why bother doing this, it may be useful for a loadbalancer in front of websocket servers. Its not as great as a direct connection from client to websocket server, but it is better than a loadbalancer that handles both requests and responses, which makes it more scalable, and more able to run on less resources.

Send data over network to multiple recipient parallely

Hellow, i'm working with network programing and it's been so hard to create a logic that allows to stream a video from a single server to multiple clients with no delay.
which means that i have to implement a parallel execution during the stream to all connected clients in order to display the images at the same time.
and why is that important for my project it's because i'm intending to have large number of clients (from 200 to approximately 700), now with 10 clients that delay is nothing but with 700 clients could significantly increase the delay to several minutes (not sure but possible).
for those who don't know what's the cause of the dely, it's from the for loop that i'm using which contain the send function for each frame, and that is a serial execution.
i tried threading and multiprocessing and even function schedule but every thing got messy, previously i was using socket & opencv, but for some reason it caused issues during the streaming, now i switched to Netgear & Vidgear but i'm still struggling.
Hope someone can help.
PS: multicast is just not right for the job, after i tried it i was receiving errors because of the length of the transmitted images, UDP protocol will NOT accept more then 65535 byte.
Per your comment, everything is in the same network, and we have multicast for exactly your problem. Rather than sending the same data over and over to multiple hosts, you can send a single stream of traffic to many receivers.
You set up the clients to subscribe to a multicast group, normally a group in the 239.0.0.0/8 Organization-Local scope. Your server then sends its traffic to the same multicast group to which the clients have subscribed. The single traffic stream will be received and processed by every client subscribed to the multicast group.
Because multicast sends to multiple clients, you must use a connectionless transport protocol, e.g. UDP. Connection-oriented transport protocols, e.g. TCP, create connections between two hosts, so they cannot be used with multicast, which is one-to-many.
By default, multicast only works in the same network. We do have multicast routing to send traffic to other networks, but it is very different than the usual unicast routing. Also, you cannot multicast on the public Internet because the ISPs do not have multicast routing. You can multicast to a different site across the Internet by using a tunnel that supports multicast, e.g. GRE. Both the source and destination routers need to be configured for multicast routing, as well as any routers in the path of the multicast packets (the Internet routers on see the unicast tunnel packets, not the multicast packets, so you can send the multicast across the Internet).
Hellow, i'm working with network programing and it's been so hard to create a logic that allows to stream a video from a single server to multiple clients with no delay.
Hey #zaki-lazhari I'm the creator of VidGear Video Processing Python Project. Actually, NetGear is not right API choice for multi-casting task, instead you should be using WebGear API. WebGear can acts as powerful Video Streaming Server that transfers live video-frames to any web browser on a network. So you can easily setup WebGear Server in few lines of code as follows:
# import required libraries
import uvicorn
from vidgear.gears.asyncio import WebGear
#various performance tweaks
options={"frame_size_reduction": 40, "frame_jpeg_quality": 80, "frame_jpeg_optimize": True, "frame_jpeg_progressive": False}
#initialize WebGear app
web=WebGear(source="foo.mp4", logging=True, **options)
#run this app on Uvicorn server at address http://0.0.0.0:8000/
uvicorn.run(web(), host='0.0.0.0', port=8000)
#close app safely
web.shutdown()
So every device (even a smartphone with any browser installed) on the same network can access real-time frames on there browser without any extra dependencies. More code samples can be found here: https://abhitronix.github.io/vidgear/gears/webgear/advanced/
Hope it helps. Good luck!

Whitelist a script for Internet Access

We've a windows server and a linux server. There is no internet on both servers. Now, we need to deploy a python script on these servers which will make an http get request to an outside network url. So, I would need internet for that. But we can't enable internet for all applications. Is there a way we can enable internet only for this particular script?
I don't know well Linux platform, but you could allow the program to make outgoing requests with the command line, from python like so:
import sys
import os
def allow_outbound_connections(program_path):
"""
Allow program outbound connections.
"""
if "win" in sys.platform:
command = f'netsh advfirewall firewall add rule name="{program_path}" '\
'dir=out action=block program= "{os.path.basename(program_path}"'\
' enable=yes profile=any'
if "linux" in sys.platform:
# *Add a similar command in Linux*
with os.popen(command) as stream:
return stream.read()
def main():
# First allow this program to make outbound connections.
output = allow_outbound_connections(__file__)
# (Eventually you could handle the output)
# Now make request to an outside network url.

How to redirect commands to a raspberry from an android App?

I have a trial version of a VPS, I want to use this as a server to send commands from a smartphone to the raspberry.
I am using http to send requests to the VPS but how can I redirect the commands received from the smartphone to the raspberry?
You can code a client-side script in Python which reads the response from the VPS each 2 seconds (or other time) and execute the command you want. E.g.
client-side script (read.py)
#client example
import socket, time
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('theVPSip', 80)) # port 80 by default
TIME = 2 # amount of time to wait. Do not saturate VPS server
while 1:
time.sleep(TIME)
data = client_socket.recv(512)
print "RECIEVED:" , data
import subprocess
process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
output = process.communicate()[0]
server-side script
Depending on what language you code, you will use a different syntax (of course). But I'll tell you what you have to do:
Register the Raspberry IP into a variable (only first time, experimenting, then let it fixed)
Register to-be-sent commands in a database
Check if the request comes from the RPi or from the phone.
RPi-> send command to execute as a return in plain text
Phone-> register data (taken from POST/GET request) into database
I suppose you could communicate with the raspberry using other model, but you would need to have a bigger control to the server and be able to run scripts of the kind of a socket connection (e.g. using Python/Java)

Networking with Python: No response from IP Phone

I'm an Automation Developer and lately I've taken it upon myself to control an IP Phone on my desk (Cisco 7940).
I have a third party application that can control the IP phone with SCCP (Skinny) packets. Through Wireshark, I see that the application will send 4 unique SCCP packets and then receives a TCP ACK message.
SCCP is not very well known, but it looks like this:
Ethernet( IP( TCP( SCCP( ))))
Using a Python packet builder: Scapy, I've been able to send the same 4 packets to the IP Phone, however I never get the ACK. In my packets, I have correctly set the sequence, port and acknowledge values in the TCP header. The ID field in the IP header is also correct.
The only thing I can imagine wrong is that it takes Python a little more than a full second to send the four packets. Whereas the application takes significantly less time. I've tried raising the priority for the Python shell with no luck.
Does anyone have an idea why I may not be receiving the ACK back?
This website may be helpful in debugging why on your machine you aren't seeing the traffic you expect, and taking steps to modify your environment to produce the desired output.
Normally, the Linux kernel takes care of setting up and sending and
receiving network traffic. It automatically sets appropriate header
values and even knows how to complete a TCP 3 way handshake. Uising
the kernel services in this way is using a "cooked" socket.
Scapy does not use these kernel services. It creates a "raw" socket. The
entire TCP/IP stack of the OS is circumvented. Because of this, Scapy
give us compete control over the traffic. Traffic to and from Scapy
will not be filtered by iptables. Also, we will have to take care of
the TCP 3 way handshake ourselves.
http://www.packetlevel.ch/html/scapy/scapy3way.html

Resources