Automatically generate list of tor exit nodes - python

I want to automatically generate a list of tor exit nodes that can reach a certain IP address. I scoured the internetfor a while and came across this piece of code from http://sjoerd-hemminga.com/blog/2012/10/block-tor-exit-nodes-using-iptables/
if [[ -z "$1" ]]; then
echo Usage: $0 "<your host's ip>"
exit 1
fi
hostip=$1
for i in $(wget https://check.torproject.org/cgi-bin/TorBulkExitList.py\?ip=$hostip -O- -q |\
grep -E '^[[:digit:]]+(\.[[:digit:]]+){3}$'); do
sudo iptables -A INPUT -s "$i" -j DROP
done
Can someone please help me understand this code better, because every time I try to run it, it produces errors.
Any alternate answers are welcomed but I would like if they are in Python.

import os
import re
import sys
import urllib
if len(sys.argv) != 2:
print "Usage {} <your host's ip>".format(sys.argv[0])
sys.exit(1)
hostip = sys.argv[1]
u = urllib.urlopen('https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=' + hostip)
for ip in u:
ip = ip.strip()
if re.match('\d+(\.\d+){3}$', ip):
#print ip
os.system('sudo iptables -A INPUT -s "{}" -j DROP'.format(ip))
u.close()

If you have configured Tor to have a control port and server descriptors...
ControlPort 9051
CookieAuthentication 1
UseMicrodescriptors 0
... then you can easily enumerate the exits using stem...
from stem.control import Controller
with Controller.from_port(port = 9051) as controller:
controller.authenticate()
for desc in controller.get_server_descriptors():
if desc.exit_policy.is_exiting_allowed():
print desc.address
That said, if your real question is 'how do I do something using every Tor exit' then please don't! Repeatedly making circuits is harmful to the Tor network, for more about about this see stem's FAQ.

Here(https://github.com/RD17/DeTor) is a simple REST API to determine whether a request was made from TOR network or not.
The request is:
curl -X GET http://detor.ambar.cloud/.
The response is
{
"sourceIp": "104.200.20.46",
"destIp": "89.207.89.82",
"destPort": "8080",
"found": true
}

Related

How do I print multiple variables in a line of code?

!/usr/bin/env python3
import random
import socket
import time
import sys
import os
print ('Ping Of Death')
os.system("clear")
print
ip_death = input("ip:")
packetsize = input("size:")
print (ip_death)
os.system("ping ip_death, -s packetsize ")
and the output I get is
ping: ip_death,: Name or service not known
I know the variables are defined because of print (ip_death) that I have tested and always comes out with my input.
I'm new to python and just wondering how I can run both of these variables in the in one command. If wonder I'm trying to run Ping example.com -s "size of packet".
You need to format the string:
os.system("ping {}, -s {}".format(ip_death, packet_size))
You can also verify you're doing the right thing by printing the command before executing it:
command = "ping {}, -s {}".format(ip_death, packet_size)
print(command) # see that its what you wanted to execute
os.system(command)
Currently you just baked the names into the strings. Python doesn't automagically know what it should format and what it shouldn't.
Also - black hat hacking is bad <3
os.system(f"ping {ip_death}, -s {packetsize} ")
You can use f-strings to insert a variable directly into a string. f-strings are defined by f"{variable}"
Note:
os.system(f"ping {ip_death}, -s {packetsize} ")
Will still fail, the comma will throw an error in cmd,
Ping request could not find host 192.168.0.1,. Please check the name and try again.
You need to remove the comma for it to work;
os.system(f"ping {ip_death} -s {packetsize} ")
ping 192.168.0.1 -s 1
Pinging 192.168.0.1 with 32 bytes of data:
Reply from 192.168.0.1: bytes=32 time<1ms TTL=255
Timestamp: 192.168.0.1 : 4742664

How to grab string(ip) from netstat pipe the string(ip) to whois command, grab a string(country) from whois output. And use iptables to ban the ip

What I'm trying to do is use netstat -an | grep ESTABLISHED to check all IP addresses in my system from a whois search and ban any belonging to china.
So I'm wondering how I could achieve this? Possibly by piping the strings into each other command? but how could I do this?
(trying to ban china without adding ssh security, I'm looking to achieve this in either bash or python)
code I have so far:
#!/bin/bash
netstat -an | grep ESTABLISHED > log.txt;
myvar=$(awk -F"|" '{print $NF}' log.txt)
whois $myvar
I am struggling to automate the process that checks if the country is china and bans the ip.
Here is an example written in bash,
#!/bin/bash
# shellcheck disable=SC2155
# Automatically ban IP from country
# Copyright (C) 2019 Lucas Ramage <ramage.lucas#protonmail.com>
# SPDX-License-Identifier: MIT
set -euo pipefail
IFS=$'\n\t'
# netstat output:
# Proto Recv-Q Send-Q Local Address Foreign Address State
get_ip_addr() {
# Awk splits the 5th column, Foreign Address, to get the IP
echo "${1}" | awk '{ split($5, a, ":"); print a[1] }'
}
# whois output:
# OrgName: Internet Assigned Numbers Authority
# OrgId: IANA
# Address: 12025 Waterfront Drive
# Address: Suite 300
# City: Los Angeles
# StateProv: CA
# PostalCode: 90292
# Country: US <-- We want this one
# RegDate:
# Updated: 2012-08-31
# Ref: https://rdap.arin.net/registry/entity/IANA
get_country() {
# Returns nothing if Country not set
whois "${1}" | awk '/Country/ { print $NF }'
}
check_country() {
# Implements a whitelist, instead of a blacklist
local COUNTRIES="US"
# Iterate through whitelist
for country in $COUNTRIES; do
# Check entry to see if its in the whitelist
if [ "${country}" == "${1}" ]; then
echo 1 # true
fi
done
}
block_ip() {
# Remove the `echo` in order to apply command; must have proper privileges, i.e sudo
echo sudo iptables -A INPUT -s "${1}" -j "${2}"
}
main() {
# Established Connections
local ESTCON=$(netstat -an | grep ESTABLISHED)
for entry in $ESTCON; do
local ip=$(get_ip_addr "${entry}")
local country=$(get_country "${ip}")
local is_allowed=$(check_country "${country}")
local policy='DROP' # or REJECT
if [ ! "${is_allowed}" -eq "1" ]; then
block_ip "${ip}" "${policy}"
fi
done
}
main
I'd personally run shellcheck on it, and test it further.
Also, you might want to look into fail2ban or something like that.
Thanks for asking.
Your quest is a product scope. People are making living from it.
See here.
The problem involved few unrelated practices.
Geolocate connection.
Maintain lists of black-list and white-list sources.
Implement list update policies.
Implement logging and notification.
Task 1 and 2 are served as web service (research google).
Many commercial DRM solution also implement your request and maintain the functionality.
I suggest to research the quest cost/effort before getting into technical design.

how to omit "connect: network is unreachable" message

i created a script which runs on boot which checks if there's an internet connection on my raspberry pi, and at the same time updates the time (care of ntp) - via os.system().
import datetime, os, socket, subprocess
from time import sleep
dir_path = os.path.dirname(os.path.abspath(__file__))
def internet(host="8.8.8.8"):
result = subprocess.call("ping -c 1 "+host, stdout=open(os.devnull,'w'), shell=True)
if result == 0:
return True
else:
return False
timestr = time.strftime("%Y-%m-%d--%H:%M:%S")
netstatus = internet()
while netstatus == False:
sleep(30)
netstatus = internet()
if netstatus == True:
print "successfully connected! updating time . . . "
os.system("sudo bash "+dir_path+"/updatetime.sh")
print "time updated! time check %s"%datetime.datetime.now()
where updatetime.sh contains the following:
service ntp stop
ntpd -q -g
service ntp start
this script runs at reboot/boot and i'm running this in our workplace, 24/7. also, outputs from scripts like these are saved in a log file. it's working fine, but is there a way how NOT to output connect: Network is unreachable
if there's no internet connection? thanks.
edit
i run this script via a shell script i named launch.sh which runs check_net.py (this script's name), and other preliminary scripts, and i placed launch.sh in my crontab to run on boot/reboot:
#reboot sh /home/pi/launch.sh > /home/pi/logs/cronlog 2>&1
from what i've read in this thread: what does '>/dev/null/ 2>&1' mean, 2 handles stderr where as 1 handles stdout.
i am new to this. I wish to see my stdout - but not the stderrs (in this case, the connect: Network is unreachable messages (only)..
/ogs
As per #shellter 's link suggestion in the comments, i restructured my cron to:
#reboot sh /home/pi/launch.sh 2>&1 > /home/pi/logs/cronlog | grep "connect: Network is unreachable"
alternatively, i also came up of an alternative solution, which involves a different way of checking an internet connection with the use urllib2.urlopen():
def internet_init():
try:
urllib2.urlopen('https://www.google.com', timeout=1)
return True
except urllib2.URLError as err:
return False
either of the two methods above omitted any connect: Network is unreachable error output in my logs.
thanks!
/ogs

Fortigate automation with perl or python

Goal
I'm trying to automate a fortigate configuration change for a couple dozen routers and am not winning. Have tried Python's paramiko library, Python fabric and Perl's expect and Rex interfaces/libraries.
Other info
* Routers: Fortigate 60D
* Firmware: v5.0,build0252 (GA Patch 5)
* SSH enabled: True
I can log in over SSH and run these commands manually!
I used the perl expect library with Fortigate 60B's in the past but it no longer works. Before I share the code I want to ask:
Is there some new feature in Fortigate's that prevents this type of automation?
A simple and harmless command to test [ list current dhcp leases ]:
execute dhcp lease-list wifi
Code
Perl/Expect:
my $timeout = 10;
$ssh->expect($timeout, [ qr/password: /i ]);
$ssh->send("$passwd\r\n");
$ssh->expect($timeout, [ qr/#/i ]);
$ssh->send("execute dhcp lease-list wifi\r");
$ssh->expect($timeout, [ qr/#/i ]);
$ssh->send("exit\r");
$ssh->soft_close();
Output: none
Perl/Rex:
desc "List all dhcp leases";
task "leases", group => "forti", sub {
my $output = run "execute dhcp lease-list wifi";
say $output;
};
Output:
[2014-02-11 13:14:48] (30011) - INFO - Running task: leases
[2014-02-11 13:14:48] (30022) - INFO - Connecting to 10.10.10.2 (admin)
[2014-02-11 13:14:49] (30022) - INFO - Connected to 10.10.10.2, trying to authenticate.
Fortigate # Unknown action 0
Fortigate #
Python/paramiko:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('10.10.10.2',username='fake_root',password='fake_pass')
stdin, stdout, stderr=ssh.exec_command("execute dhcp lease-list wifi")
stdout.readlines()
ssh.close()
Output: none
Python/Fabric:
def view_dhcp_leases():
print("Viewing dhcp leases")
run("execute dhcp lease-list wifi")
Output:
[10.10.10.2] Executing task 'view_dhcp_leases'
Viewing dhcp leases
[10.10.10.2] run: execute dhcp lease-list wifi
[10.10.10.2] out: Fortigate # Unknown action 0
[10.10.10.2] out:
[10.10.10.2] out: Fortigate #
Done.
Disconnecting from 10.10.10.2 ... done.
Conclusions ...so far
Unknown action 0 means, "I don't know this command [ in this context ]". This command can be run manually at the first prompt. Also, as you can see in the fabric and rex examples: it does authenticate and connect! I conclude that this is by design for security reasons ...and more likely to sell their proprietary management crap.
This works for me on a FortiNet Mail Appliance.
from Exscript.util.interact import Account
from Exscript.protocols import SSH2
account = Account('USERNAME', 'PASSWORD')
conn = SSH2()
conn.connect('IP')
conn.login(account)
conn.execute('COMMAND')
conn.send('exit \r')
conn.close()
https://github.com/knipknap/exscript
The following script worked for me against a FortiGate (5.2.4) with Python/Paramiko:
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('1.1.1.254',username='admin',password='password')
stdin, stdout, stderr=ssh.exec_command("get system status")
type(stdin)
stdout.readlines()
Andy
I have 60B.
Please try to run this command from linux terminal.
If you don't have sshpass - you can install it.
sshpass -p 'adminpassword' ssh ip_of_fw -l admin execute dhcp lease-list
If you want to use fabric to run commands on fortigates you need to disable the shell wrapping used by fabric when connecting via SSH:
from fabric.api import run
def get_sys():
run("get sys status",shell=False)
Youc can upgrade an OS version and then use API with P

how to edit hostname file using fabric

I have change my hosts file,so how to change hostname.my system is ubuntu.
eg my hosts file:
192.168.0.100 host1.mydomain.com
192.168.0.101 host2.mydomain.com
I wanna the hostname file under /etc/hostname of host1 to host1.mydomain.com,the hostname file of host2 to host2.mydomain.com
how to do that using fabric?
I have to ssh every host and edit the hostname file,does fabric can do this?
I didn't mean to use hostname command but to edit the /etc/hostname file.
I mean how to use fabric to do that:
such as:
def update_hostname():
get("/etc/hosts","hosts")
hosts_content = file("hosts")
**hostname = ·get the hostname corespond to ip·**
get("/etc/hostname","hostname")
update `hostname file`
put("hostname","/etc/hostname")
how get the ip? because fabric do the job on every host, and the hostname is correspond to each host. I need to know the which host the job is working and then get the ip back,then get the hostname correspond the the ip,and final update the hostname file.
Fabric is just a SSH wrapper, so what you're looking at is LINUX specific, not frabric or python specific.
from fabric.api import run
run('hostname your-new-name')
run('echo your-new-hostname > /etc/hostname')
And just do a run(..edit..) according to your linux dist?
Or just do:
from subprocess import Popen, PIPE
hosts = open('/etc/networking/hosts', 'rb')
for hostline in hosts.readlines():
ip, name = hostline.split(' ')
command = ['ssh', '-t', 'root#' + host.strip('\r\n ,;), ' ', "echo " + name.strip('\r\n ,;) + " > /etc/hostname",]
stdout, stderr = Popen(command, stdout=PIPE, stderr=PIPE).communicate()
hosts.close()
Note: /etc/networking/hosts might be placed somewhere else for you.
The important part here is that you loop through the /hosts file, and ssh to each machine echoing the given hostname to that machine.
def hostname():
'''
function to change the hostname of the ubuntu server
'''
server_hostname = prompt ("The Hostname for the server is :")
sed ("/etc/hostname", before='current hostname', after='%s' % (server_hostname), use_sudo=True,backup='')
sudo ("init 6")
This will change the hostname according to your choice.
in your fabric script you'll need to...
ssh into the machine as a user permitted to edit the hosts file ( via permissions or groups ). if you need to sudo into a user, search StackOverflow for issues regarding sudo and Fabric -- you'll need to tweak your fabfile to not prompt for a password.
fabric can have an awkward way to deal with reading/writing/opening files. you'll may be best off by cd into the right directory. something like...
with cd('/etc/')
run('echo new_hostname hostname')

Categories

Resources