POX - Modifying a packet's destination in POX Controller - networking

I am trying to create a honeypot using Mininet and POX Controller. Here, what I want to achieve is that whenever a particular host pings a specific network, instead of redirecting it to the actual host, the switch should modify its destination as the ip address of our host behaving as honeypot.
I'm quite confused about the implementation of this using ofp_flow_mod() method and which switch should actually implement it. Any code examples to give me a direction would be really helpful.
I've included the topology diagram below to illustrate a clear understanding:
Mininet Topology
I've created a Mininet Topology using the following code:
from mininet.net import Mininet
from mininet.node import RemoteController
from mininet.cli import CLI
from mininet.log import setLogLevel, info
setLogLevel( 'info' )
info('\n*** Initialize Mininet\n')
net = Mininet()
info( '*** Adding controller\n' )
net.addController(name='c0', controller=RemoteController, ip='192.168.56.101', port=6633 )
info( '*** Adding hosts\n' )
h1 = net.addHost( 'h1', ip='10.0.1.1', )
h2 = net.addHost( 'h2', ip='10.0.1.2', )
h3 = net.addHost( 'h3', ip='10.0.2.1', )
h4 = net.addHost( 'h4', ip='10.0.2.2', )
h5 = net.addHost( 'h5', ip='10.0.2.3', )
h6 = net.addHost( 'h6', ip='10.0.2.4', )
h7 = net.addHost( 'h7', ip='10.0.3.1', )
h8 = net.addHost( 'h8', ip='10.0.3.2', )
info( '*** Adding switches\n' )
s1 = net.addSwitch( 's1' )
s2 = net.addSwitch( 's2' )
s3 = net.addSwitch( 's3' )
info( '*** Creating links\n' )
net.addLink(s1, s2)
net.addLink(s2, s3)
net.addLink( s1, h1 )
net.addLink( s1, h2 )
net.addLink( s2, h3 )
net.addLink( s2, h4 )
net.addLink( s2, h5 )
net.addLink( s2, h6 )
net.addLink( s3, h7 )
net.addLink( s3, h8 )
info( '*** Starting network\n')
net.start()
info( '*** Running CLI\n' )
CLI( net )
info( '*** Stopping network' )
net.stop()
This topology is successfully connected with POX.
The goal here is that whenever h1 (10.0.1.1) or h2 (10.0.1.2) pings any hosts connected to switch2, the packets should be redirected from switch 2 directly to switch 3 with a modified IP address and vice-versa.
I've tried to implement the following code in POX but it doesn't seem to give me a direction at all.
from pox.core import core
from pox.lib.addresses import IPAddr
import pox.openflow.libopenflow_01 as of
from pox.lib.revent import *
from pox.lib.util import dpid_to_str
from pox.lib.packet.ethernet import ethernet
from pox.lib.packet.ipv4 import ipv4
from pox.lib.addresses import IPAddr, EthAddr
log = core.getLogger()
# creating an event which triggers when a request from switch 1 device sent to switch 2 device
class SDNHoneyPot(EventMixin):
def __init__ (self):
self.listenTo(core.openflow)
def _handle_PacketIn (self, event):
"""
Handles packet in messages from the switch.
"""
packet = event.parsed # This is the parsed packet data.
if not packet.parsed:
log.warning("Ignoring incomplete packet")
return
packet_in = event.ofp # The actual ofp_packet_in message.
msg = of.ofp_flow_mod()
if (event.dpid == 2 and
(isinstance(packet.next, ipv4) and
(packet.next.srcip == "10.0.1.1" and packet.next.dstip == "10.0.2.1") or ((packet.next.srcip == "10.0.2.1" and packet.next.dstip == "10.0.1.1"))))
msg.priority = 10
msg.match.dl_type = 0x0800
msg.match.nw_proto = 1 # ICMP
msg.match.nw_src = "10.0.1.1" # from untrusted host
msg.match.nw_dst = "10.0.2.1" # to our datacenter
event.connection.send(msg)
msg = of.ofp_flow_mod()
msg.priority = 10
msg.match.dl_type = 0x0800
msg.match.nw_proto = 1 # ICMP
msg.match.nw_src = "10.0.2.1" # from untrusted host
msg.match.nw_dst = "10.0.1.1" # to our datacenter
event.connection.send(msg)
else:
msg.data = packet_in
msg.actions.append(of.ofp_action_output(port = of.OFPP_FLOOD))
event.connection.send(msg)
def _handle_ConnectionUp (self, event):
# Log whenever a switch is registered in Mininet Topology.
log.debug("Switch %s has come up.", dpid_to_str(event.dpid))
# registering the event to the core component
def launch ():
core.registerNew(SDNHoneyPot)
Since I have no idea about how to redirect these packets, I'm currently trying to block these packets from forwarding by providing no actions, but that does not seem to work as well.

Related

Modified Google pushtotalk.py crashes on missing attribute 'DeviceRequestHandler'

I am running on a Raspberry Pi 3b+ with latest Raspbian. I have created a Python 2.7 virtual environment to test a few things. I installed the Google Assistant Api using the following instructions:
https://developers.google.com/assistant/sdk/guides/library/python/embed/install-sample
-except the audio, I am using the Respeaker 4-mic hat as I already had that working fine.
When I run the sample code for pushtotalk.py it works fine except CTRL-C no longer functions (have to close the terminal window to kill it).
I made a few minor (or I thought minor) changes and when I run the code I get a strange error.
My version of the code:
# Original pushtotalk.py file Copyright (C) 2017 Google Inc.
# modified by #captstephan for T3 project
#
# my imports for the mechanical functions, motor drivers, etc.
from Raspi_PWM_Servo_Driver import PWM
from voice_engine.source import Source
from voice_engine.channel_picker import ChannelPicker
from voice_engine.kws import KWS
from voice_engine.doa_respeaker_4mic_array import DOA
from pixels import pixels
# imports from the original Google pushtotalk.py file
import concurrent.futures
import json
import logging
import os
import os.path
import pathlib2 as pathlib
import sys
import time
import uuid
import click
import grpc
import google.auth.transport.grpc
import google.auth.transport.requests
import google.oauth2.credentials
from google.assistant.embedded.v1alpha2 import (
embedded_assistant_pb2,
embedded_assistant_pb2_grpc
)
from tenacity import retry, stop_after_attempt, retry_if_exception
import assistant_helpers
import audio_helpers
import browser_helpers
import device_helpers
# set up Google Assistant variables (from pushtotalk.py)
ASSISTANT_API_ENDPOINT = 'embeddedassistant.googleapis.com'
END_OF_UTTERANCE = embedded_assistant_pb2.AssistResponse.END_OF_UTTERANCE
DIALOG_FOLLOW_ON = embedded_assistant_pb2.DialogStateOut.DIALOG_FOLLOW_ON
CLOSE_MICROPHONE = embedded_assistant_pb2.DialogStateOut.CLOSE_MICROPHONE
PLAYING = embedded_assistant_pb2.ScreenOutConfig.PLAYING
DEFAULT_GRPC_DEADLINE = 60 * 3 + 5
# set up items for motor hats
# Initialise the PWM device using the default address
pwm = PWM(0x6F)
# set max and min, servo0=Horiz, servo1=vert
servoMin0 = 155 # Min pulse length out of 4096
servoMid0 = 370
servoMax0 = 585 # Max pulse length out of 4096
servoMin1 = 410 # Min pulse length out of 4096
servoMid1 = 530
servoMax1 = 650 # Max pulse length out of 4096
pwm.setPWMFreq(60) # Set frequency to 60 Hz
# class assignment from pushtotalk.py file:
class SampleAssistant(object):
"""Sample Assistant that supports conversations and device actions.
Args:
device_model_id: identifier of the device model.
device_id: identifier of the registered device instance.
conversation_stream(ConversationStream): audio stream
for recording query and playing back assistant answer.
channel: authorized gRPC channel for connection to the
Google Assistant API.
deadline_sec: gRPC deadline in seconds for Google Assistant API call.
device_handler: callback for device actions.
"""
def __init__(self, language_code, device_model_id, device_id,
conversation_stream, display,
channel, deadline_sec, device_handler):
self.language_code = language_code
self.device_model_id = device_model_id
self.device_id = device_id
self.conversation_stream = conversation_stream
self.display = display
# Opaque blob provided in AssistResponse that,
# when provided in a follow-up AssistRequest,
# gives the Assistant a context marker within the current state
# of the multi-Assist()-RPC "conversation".
# This value, along with MicrophoneMode, supports a more natural
# "conversation" with the Assistant.
self.conversation_state = None
# Force reset of first conversation.
self.is_new_conversation = True
# Create Google Assistant API gRPC client.
self.assistant = embedded_assistant_pb2_grpc.EmbeddedAssistantStub(
channel
)
self.deadline = deadline_sec
self.device_handler = device_handler
def __enter__(self):
return self
def __exit__(self, etype, e, traceback):
if e:
return False
self.conversation_stream.close()
def is_grpc_error_unavailable(e):
is_grpc_error = isinstance(e, grpc.RpcError)
if is_grpc_error and (e.code() == grpc.StatusCode.UNAVAILABLE):
logging.error('grpc unavailable error: %s', e)
return True
return False
#retry(reraise=True, stop=stop_after_attempt(3),
retry=retry_if_exception(is_grpc_error_unavailable))
def assist(self):
"""Send a voice request to the Assistant and playback the response.
Returns: True if conversation should continue.
"""
continue_conversation = False
device_actions_futures = []
self.conversation_stream.start_recording()
logging.info('Recording audio request.')
def iter_log_assist_requests():
for c in self.gen_assist_requests():
assistant_helpers.log_assist_request_without_audio(c)
yield c
logging.debug('Reached end of AssistRequest iteration.')
# This generator yields AssistResponse proto messages
# received from the gRPC Google Assistant API.
for resp in self.assistant.Assist(iter_log_assist_requests(),
self.deadline):
assistant_helpers.log_assist_response_without_audio(resp)
if resp.event_type == END_OF_UTTERANCE:
logging.info('End of audio request detected.')
logging.info('Stopping recording.')
self.conversation_stream.stop_recording()
if resp.speech_results:
logging.info('Transcript of user request: "%s".',
' '.join(r.transcript
for r in resp.speech_results))
if len(resp.audio_out.audio_data) > 0:
if not self.conversation_stream.playing:
self.conversation_stream.stop_recording()
self.conversation_stream.start_playback()
logging.info('Playing assistant response.')
self.conversation_stream.write(resp.audio_out.audio_data)
if resp.dialog_state_out.conversation_state:
conversation_state = resp.dialog_state_out.conversation_state
logging.debug('Updating conversation state.')
self.conversation_state = conversation_state
if resp.dialog_state_out.volume_percentage != 0:
volume_percentage = resp.dialog_state_out.volume_percentage
logging.info('Setting volume to %s%%', volume_percentage)
self.conversation_stream.volume_percentage = volume_percentage
if resp.dialog_state_out.microphone_mode == DIALOG_FOLLOW_ON:
continue_conversation = True
logging.info('Expecting follow-on query from user.')
elif resp.dialog_state_out.microphone_mode == CLOSE_MICROPHONE:
continue_conversation = False
if resp.device_action.device_request_json:
device_request = json.loads(
resp.device_action.device_request_json
)
fs = self.device_handler(device_request)
if fs:
device_actions_futures.extend(fs)
if self.display and resp.screen_out.data:
system_browser = browser_helpers.system_browser
system_browser.display(resp.screen_out.data)
if len(device_actions_futures):
logging.info('Waiting for device executions to complete.')
concurrent.futures.wait(device_actions_futures)
logging.info('Finished playing assistant response.')
self.conversation_stream.stop_playback()
return continue_conversation
def gen_assist_requests(self):
"""Yields: AssistRequest messages to send to the API."""
config = embedded_assistant_pb2.AssistConfig(
audio_in_config=embedded_assistant_pb2.AudioInConfig(
encoding='LINEAR16',
sample_rate_hertz=self.conversation_stream.sample_rate,
),
audio_out_config=embedded_assistant_pb2.AudioOutConfig(
encoding='LINEAR16',
sample_rate_hertz=self.conversation_stream.sample_rate,
volume_percentage=self.conversation_stream.volume_percentage,
),
dialog_state_in=embedded_assistant_pb2.DialogStateIn(
language_code=self.language_code,
conversation_state=self.conversation_state,
is_new_conversation=self.is_new_conversation,
),
device_config=embedded_assistant_pb2.DeviceConfig(
device_id=self.device_id,
device_model_id=self.device_model_id,
)
)
if self.display:
config.screen_out_config.screen_mode = PLAYING
# Continue current conversation with later requests.
self.is_new_conversation = False
# The first AssistRequest must contain the AssistConfig
# and no audio data.
yield embedded_assistant_pb2.AssistRequest(config=config)
for data in self.conversation_stream:
# Subsequent requests need audio data, but not config.
yield embedded_assistant_pb2.AssistRequest(audio_in=data)
#click.command()
#click.option('--api-endpoint', default=ASSISTANT_API_ENDPOINT,
metavar='<api endpoint>', show_default=True,
help='Address of Google Assistant API service.')
#click.option('--credentials',
metavar='<credentials>', show_default=True,
default=os.path.join(click.get_app_dir('google-oauthlib-tool'),
'credentials.json'),
help='Path to read OAuth2 credentials.')
#click.option('--project-id',
metavar='<project id>',
help=('Google Developer Project ID used for registration '
'if --device-id is not specified'))
#click.option('--device-model-id',
metavar='<device model id>',
help=(('Unique device model identifier, '
'if not specifed, it is read from --device-config')))
#click.option('--device-id',
metavar='<device id>',
help=(('Unique registered device instance identifier, '
'if not specified, it is read from --device-config, '
'if no device_config found: a new device is registered '
'using a unique id and a new device config is saved')))
#click.option('--device-config', show_default=True,
metavar='<device config>',
default=os.path.join(
click.get_app_dir('googlesamples-assistant'),
'device_config.json'),
help='Path to save and restore the device configuration')
#click.option('--lang', show_default=True,
metavar='<language code>',
default='en-US',
help='Language code of the Assistant')
#click.option('--display', is_flag=True, default=False,
help='Enable visual display of Assistant responses in HTML.')
#click.option('--verbose', '-v', is_flag=True, default=False,
help='Verbose logging.')
#click.option('--input-audio-file', '-i',
metavar='<input file>',
help='Path to input audio file. '
'If missing, uses audio capture')
#click.option('--output-audio-file', '-o',
metavar='<output file>',
help='Path to output audio file. '
'If missing, uses audio playback')
#click.option('--audio-sample-rate',
default=audio_helpers.DEFAULT_AUDIO_SAMPLE_RATE,
metavar='<audio sample rate>', show_default=True,
help='Audio sample rate in hertz.')
#click.option('--audio-sample-width',
default=audio_helpers.DEFAULT_AUDIO_SAMPLE_WIDTH,
metavar='<audio sample width>', show_default=True,
help='Audio sample width in bytes.')
#click.option('--audio-iter-size',
default=audio_helpers.DEFAULT_AUDIO_ITER_SIZE,
metavar='<audio iter size>', show_default=True,
help='Size of each read during audio stream iteration in bytes.')
#click.option('--audio-block-size',
default=audio_helpers.DEFAULT_AUDIO_DEVICE_BLOCK_SIZE,
metavar='<audio block size>', show_default=True,
help=('Block size in bytes for each audio device '
'read and write operation.'))
#click.option('--audio-flush-size',
default=audio_helpers.DEFAULT_AUDIO_DEVICE_FLUSH_SIZE,
metavar='<audio flush size>', show_default=True,
help=('Size of silence data in bytes written '
'during flush operation'))
#click.option('--grpc-deadline', default=DEFAULT_GRPC_DEADLINE,
metavar='<grpc deadline>', show_default=True,
help='gRPC deadline in seconds')
#click.option('--once', default=False, is_flag=True,
help='Force termination after a single conversation.')
def main(api_endpoint, credentials, project_id,
device_model_id, device_id, device_config,
lang, display, verbose,
input_audio_file, output_audio_file,
audio_sample_rate, audio_sample_width,
audio_iter_size, audio_block_size, audio_flush_size,
grpc_deadline, once, *args, **kwargs):
# Inserted the following code to set up the snowboy keyword activation using "Hey T3"
src = Source(rate=16000, channels=4, frames_size=320)
ch1 = ChannelPicker(channels=4, pick=1)
kws = KWS()
doa = DOA(rate=16000)
src.link(ch1)
ch1.link(kws)
src.link(doa)
pixels.listen()
pwm.setPWM(0, 0, 370)
pwm.setPWM(1, 0, 640)
# When snowboy detects the custom keyword, set the camera position to near direction of voice
def on_detected(keyword):
position = doa.get_direction()
pixels.wakeup(position)
print('detected {} at direction {}'.format(keyword, position))
if position >= 30 and position <= 180:
pwm.setPWM(0, 0, 175)
pwm.setPWM(1, 0, 500)
elif position > 180 and position <= 330:
pwm.setPWM(0, 0, 560)
pwm.setPWM(1, 0, 500)
elif position > 330 or position < 30:
pwm.setPWM(0, 0, 370)
pwm.setPWM(1, 0, 6200)
else:
pwm.setPWM(0, 0, 370)
pwm.setPWM(1, 0, 640)
# end of stuff I inserted
# Setup logging.
logging.basicConfig(level=logging.DEBUG if verbose else logging.INFO)
# Load OAuth 2.0 credentials.
try:
with open(credentials, 'r') as f:
credentials = google.oauth2.credentials.Credentials(token=None,
**json.load(f))
http_request = google.auth.transport.requests.Request()
credentials.refresh(http_request)
except Exception as e:
logging.error('Error loading credentials: %s', e)
logging.error('Run google-oauthlib-tool to initialize '
'new OAuth 2.0 credentials.')
sys.exit(-1)
# Create an authorized gRPC channel.
grpc_channel = google.auth.transport.grpc.secure_authorized_channel(
credentials, http_request, api_endpoint)
logging.info('Connecting to %s', api_endpoint)
# Configure audio source and sink.
audio_device = None
if input_audio_file:
audio_source = audio_helpers.WaveSource(
open(input_audio_file, 'rb'),
sample_rate=audio_sample_rate,
sample_width=audio_sample_width
)
else:
audio_source = audio_device = (
audio_device or audio_helpers.SoundDeviceStream(
sample_rate=audio_sample_rate,
sample_width=audio_sample_width,
block_size=audio_block_size,
flush_size=audio_flush_size
)
)
if output_audio_file:
audio_sink = audio_helpers.WaveSink(
open(output_audio_file, 'wb'),
sample_rate=audio_sample_rate,
sample_width=audio_sample_width
)
else:
audio_sink = audio_device = (
audio_device or audio_helpers.SoundDeviceStream(
sample_rate=audio_sample_rate,
sample_width=audio_sample_width,
block_size=audio_block_size,
flush_size=audio_flush_size
)
)
# Create conversation stream with the given audio source and sink.
conversation_stream = audio_helpers.ConversationStream(
source=audio_source,
sink=audio_sink,
iter_size=audio_iter_size,
sample_width=audio_sample_width,
)
if not device_id or not device_model_id:
try:
with open(device_config) as f:
device = json.load(f)
device_id = device['id']
device_model_id = device['model_id']
logging.info("Using device model %s and device id %s",
device_model_id,
device_id)
except Exception as e:
logging.warning('Device config not found: %s' % e)
logging.info('Registering device')
if not device_model_id:
logging.error('Option --device-model-id required '
'when registering a device instance.')
sys.exit(-1)
if not project_id:
logging.error('Option --project-id required '
'when registering a device instance.')
sys.exit(-1)
device_base_url = (
'https://%s/v1alpha2/projects/%s/devices' % (api_endpoint,
project_id)
)
device_id = str(uuid.uuid1())
payload = {
'id': device_id,
'model_id': device_model_id,
'client_type': 'SDK_SERVICE'
}
session = google.auth.transport.requests.AuthorizedSession(
credentials
)
r = session.post(device_base_url, data=json.dumps(payload))
if r.status_code != 200:
logging.error('Failed to register device: %s', r.text)
sys.exit(-1)
logging.info('Device registered: %s', device_id)
pathlib.Path(os.path.dirname(device_config)).mkdir(exist_ok=True)
with open(device_config, 'w') as f:
json.dump(payload, f)
device_handler = device_helpers.DeviceRequestHandler(device_id)
#device_handler.command('action.devices.commands.OnOff')
def onoff(on):
if on:
logging.info('Turning device on')
else:
logging.info('Turning device off')
#device_handler.command('com.example.commands.BlinkLight')
def blink(speed, number):
logging.info('Blinking device %s times.' % number)
delay = 1
if speed == "SLOWLY":
delay = 2
elif speed == "QUICKLY":
delay = 0.5
for i in range(int(number)):
logging.info('Device is blinking.')
time.sleep(delay)
with SampleAssistant(lang, device_model_id, device_id,
conversation_stream, display,
grpc_channel, grpc_deadline,
device_handler) as assistant:
# If file arguments are supplied:
# exit after the first turn of the conversation.
if input_audio_file or output_audio_file:
assistant.assist()
return
# changed the wait for keypress to a wait for keyword using the snowboy module
# If no file arguments supplied:
# keep recording voice requests using the microphone
# and playing back assistant response using the speaker.
# When the once flag is set, don't wait for a trigger. Otherwise, wait.
wait_for_user_trigger = not once
while True:
if wait_for_user_trigger:
#click.pause(info='Press Enter to send a new request...
kws.set_callback(on_detected)
continue_conversation = assistant.assist()
# wait for user trigger if there is no follow-up turn in
# the conversation.
wait_for_user_trigger = not continue_conversation
# If we only want one conversation, break.
if once and (not continue_conversation):
break
if __name__ == '__main__':
main()
I get the following error:
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
"main", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/home/pi/T3google.py", line 501, in
main()
File "/home/pi/env/local/lib/python2.7/site-packages/click/core.py", line 722, in call
return self.main(*args, **kwargs)
File "/home/pi/env/local/lib/python2.7/site-packages/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/home/pi/env/local/lib/python2.7/site-packages/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/pi/env/local/lib/python2.7/site-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/home/pi/T3google.py", line 425, in main
device_handler = device_helpers.DeviceRequestHandler(device_id)
AttributeError: 'module' object has no attribute 'DeviceRequestHandler'
I am still new to python, but the sample code from Google works and the code snippet I inserted works stand-alone in another file.
I checked device_helpers.py and DeviceRequestHandler is a class that takes the device_id as input. It works fine if I call it in pushtotalk.py, but not in the modified code.
Any thoughts anyone?
Thanks in advance,
Stephan
I shut down for other reasons, came back and restarted the next day and problem disappeared. Likely something required a reboot to complete install and I missed it. That part is working fine now, haven't been able to completely get this to work as expected.

GUI user input send TCP command

I would like to create a pop up window that queries for input that will route that input as a string to port 9090. What is wrong with my code?
import socket
host = "127.0.0.1"
port = 9090
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
def goto(prompt):
cue = input(prompt)
while cue not in ("exit", "done"):
cue = input(prompt)
byt = cue.encode()
s.send(byt)
return cue
print(goto("cue?"))
from Tkinter import *
root = Tk()
root.title('Name')
e = Entry(root)
e.pack()
e.focus_set()
b = Button(root,text='okay',command=goto())
b.pack(side='bottom')
root.mainloop()

Tornado receive UDP packets from multicast group

I have a server where I want to receive data from multicast group. Is there any inbuilt function that I can use to receive this multicast UDP packets?
Edit: Code implementation
I have implemented the code and that follows like this:
#!/usr/bin/env python
import socket
import struct
import os
import errno
import binascii
import tornado.ioloop
from tornado.ioloop import IOLoop
from tornado.platform.auto import set_close_exec
class UDPHandler():
"""
Connect to multicast group
"""
def __init__(self, ip, port, io_loop):
self.io_loop = io_loop
self._multiIP = ip
self.port = port
self._sock = None
self._socket = {} # fd -> socket object
def conn(self):
"""
Listner to multicast group
"""
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self._sock.settimeout(3)
self._sock.bind(('', self.port))
self._sock.setblocking(0)
group = socket.inet_aton(self._multiIP)
mreq = struct.pack('4sL', group, socket.INADDR_ANY)
self._sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
self._socket[self._sock.fileno()] = self._sock
print("self._sock:", self._sock)
def onRx(self, data, addr):
print("addr, data:", addr, len(str(data)))
print(data)
def r(self):
self.conn()
add_socket_handler(self._sock, self.onRx, self.io_loop)
def add_socket_handler(sock, callback, io_loop):
def accept_handler(fd, events):
while True:
try:
data, address = sock.recvfrom(1024)
except socket.error as e:
if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
callback(None, None)
except Exception as e:
print("except:", e)
callback(None, None)
callback(data, address)
io_loop.add_handler(sock.fileno(), accept_handler, IOLoop.READ)
def periodic():
# print("periodic")
None
def main():
MULTICAST_IP = "224.1.1.10"
RECEIVE_PORT = 10003
udpRx = UDPHandler(MULTICAST_IP, RECEIVE_PORT, tornado.ioloop.IOLoop.current())
udpRx.r()
tornado.ioloop.PeriodicCallback(periodic, 1000).start()
tornado.ioloop.IOLoop.current().start()
if __name__ == "__main__":
main()
Now the problem is is am getting same packet in a loop even if I receive one packet I am receiving the same packet over and over again. Is there something wrong with the code? Especially with add_socket_handler?
Edit 2:
I have added a break statement in the while loop that I had in add_socket_handler and now it seems to be working good.
def add_socket_handler(sock, callback, io_loop):
def accept_handler(fd, events):
while True:
try:
data, address = sock.recvfrom(1024)
callback(data, address)
except socket.error as e:
if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):
raise
except Exception as e:
raise
break ## change in here
io_loop.add_handler(sock.fileno(), accept_handler, io_loop.READ)
Is this how it is suppose to be done ?
The break in your add_socket_handler looks backwards. You want to loop until you get EWOULDBLOCK/EAGAIN. (with the break as written, it will still work, but it will be slightly less efficient and might miss packets).
def add_socket_handler(sock, callback, io_loop):
def read_handler(fd, events):
while True:
try:
data, address = sock.recvfrom(1024)
callback(data, address):
except socket.error as e:
if e.errno in (errno.EWOULDBLOCK, errno.EAGAIN):
return
raise
io_loop.add_handler(sock, read_handler, io_loop.READ)
Other than that, this looks right, although I haven't worked with multicast UDP myself.

Operating Micropython-running WeMos D1 mini (ESP8266) pins with HTTP requests

What I am trying to ultimately achieve is to control my garage door opener with a relay connected to a WeMos D1 Mini, connected to my home WiFi. I am using the openGarageDoor() function. Everything works fine with serial connection.
I have been trying to run HTTP server on a WeMos D1 Mini with this script.
customertagsAction() -- try:
import usocket as socket
except:
import socket
CONTENT = b"""\
HTTP/1.0 200 OK
Hello #%d from MicroPython!
"""
def main(micropython_optimize=False):
s = socket.socket()
# Binding to all interfaces - server will be accessible to other hosts!
ai = socket.getaddrinfo("0.0.0.0", 8080)
print("Bind address info:", ai)
addr = ai[0][-1]
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen(5)
print("Listening, connect your browser to http://<this_host>:8080/")
counter = 0
while True:
res = s.accept()
client_sock = res[0]
client_addr = res[1]
print("Client address:", client_addr)
print("Client socket:", client_sock)
if not micropython_optimize:
# To read line-oriented protocol (like HTTP) from a socket (and
# avoid short read problem), it must be wrapped in a stream (aka
# file-like) object. That's how you do it in CPython:
client_stream = client_sock.makefile("rwb")
else:
# .. but MicroPython socket objects support stream interface
# directly, so calling .makefile() method is not required. If
# you develop application which will run only on MicroPython,
# especially on a resource-constrained embedded device, you
# may take this shortcut to save resources.
client_stream = client_sock
print("Request:")
req = client_stream.readline()
print(req)
while True:
h = client_stream.readline()
if h == b"" or h == b"\r\n":
break
print(h)
client_stream.write(CONTENT % counter)
client_stream.close()
if not micropython_optimize:
client_sock.close()
counter += 1
print()
main()
The requests are received properly and the GET variables are shown on the print(). The best i have been able to do is
req = client_stream.readline()
print(req)
while True:
h = client_stream.readline()
if h == b"" or h == b"\r\n":
break
print(h)
client_stream.write(CONTENT % counter)
//my function here:
if 'opengaragedoor=1' in req:
openGarageDoor()
client_stream.close()
I don't know how to parse the request properly. I only have come up with this dirty solution. This probably causes a timeout on the requesting system, as Postman or such needs to wait for the function to run through.

How to get the Tor ExitNode IP with Python and Stem

I'm trying to get the external IP that Tor uses, as mentioned here. When using something like myip.dnsomatic.com, this is very slow. I tried what was suggested in the aforementioned link (python + stem to control tor through the control port), but all you get is circuit's IPs with no assurance of which one is the one on the exitnode, and, sometimes the real IP is not even among the results.
Any help would be appreciated.
Also, from here, at the bottom, Amine suggests a way to renew the identity in Tor. There is an instruction, controller.get_newnym_wait(), which he uses to wait until the new connection is ready (controller is from Control in steam.control), isn't there any thing like that in Steam (sorry, I checked and double/triple checked and couldn't find nothing) that tells you that Tor is changing its identity?
You can get the exit node ip without calling a geoip site.
This is however on a different stackexchange site here - https://tor.stackexchange.com/questions/3253/how-do-i-trap-circuit-id-none-errors-in-the-stem-script-exit-used-py
As posted by #mirimir his code below essentially attaches a stream event listener function, which is then used to get the circuit id, circuit fingerprint, then finally the exit ip address -
#!/usr/bin/python
import functools
import time
from stem import StreamStatus
from stem.control import EventType, Controller
def main():
print "Tracking requests for tor exits. Press 'enter' to end."
print
with Controller.from_port() as controller:
controller.authenticate()
stream_listener = functools.partial(stream_event, controller)
controller.add_event_listener(stream_listener, EventType.STREAM)
raw_input() # wait for user to press enter
def stream_event(controller, event):
if event.status == StreamStatus.SUCCEEDED and event.circ_id:
circ = controller.get_circuit(event.circ_id)
exit_fingerprint = circ.path[-1][0]
exit_relay = controller.get_network_status(exit_fingerprint)
t = time.localtime()
print "datetime|%d-%02d-%02d %02d:%02d:%02d % (t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec)
print "website|%s" % (event.target)
print "exitip|%s" % (exit_relay.address)
print "exitport|%i" % (exit_relay.or_port)
print "fingerprint|%s" % exit_relay.fingerprint
print "nickname|%s" % exit_relay.nickname
print "locale|%s" % controller.get_info("ip-to-country/%s" % exit_relay.address, 'unknown')
print
You can use this code for check current IP (change SOCKS_PORT value to yours):
import re
import stem.process
import requesocks
SOCKS_PORT = 9053
tor_process = stem.process.launch_tor()
proxy_address = 'socks5://127.0.0.1:{}'.format(SOCKS_PORT)
proxies = {
'http': proxy_address,
'https': proxy_address
}
response = requesocks.get("http://httpbin.org/ip", proxies=proxies)
print re.findall(r'[\d.-]+', response.text)[0]
tor_process.kill()
If you want to use socks you should do:
pip install requests[socks]
Then you can do:
import requests
import json
import stem.process
import stem
SOCKS_PORT = "9999"
tor = stem.process.launch_tor_with_config(
config={
'SocksPort': SOCKS_PORT,
},
tor_cmd= 'absolute_path/to/tor.exe',
)
r = requests.Session()
proxies = {
'http': 'socks5://localhost:' + SOCKS_PORT,
'https': 'socks5://localhost:' + SOCKS_PORT
}
response = r.get("http://httpbin.org/ip", proxies=proxies)
self.current_ip = response.json()['origin']

Resources