diff --git a/5000.py b/bots/5000.py similarity index 100% rename from 5000.py rename to bots/5000.py diff --git a/bots/hateserv/api.py b/bots/hateserv/api.py new file mode 100644 index 0000000..a39085f --- /dev/null +++ b/bots/hateserv/api.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +# hateserv irc bot - developed by acidvegas in python (https://git.acid.vegas/hateserv) + +import http.client +import json +import re + +def between(source, start, stop): + data = re.compile(start + '(.*?)' + stop, re.IGNORECASE|re.MULTILINE).search(source) + return data.group(1) if data else False + +def geoip(ip: str): + api = geturl('api.ipapi.is', '?q='+ip) + data = json.loads(api) + LOCATION = '{0}, {1}, {2}'.format(data['location']['city'], data['location']['state'], data['location']['country_code']) + ASN = 'AS{0} {1}'.format(data['asn']['asn'], data['asn']['descr']) + RIR = data['rir'] + return {'location': LOCATION, 'asn': ASN, 'rir': RIR} + +def geturl(url, endpoint, headers={}): + conn = http.client.HTTPSConnection(url, timeout=15) + conn.request('GET', endpoint, headers=headers) + response = conn.getresponse().read() + conn.close() + return response + +def google(query): + service = build('customsearch', 'v1', developerKey=google_api_key, cache_discovery=False).cse() + results = service.list(q=query, cx=google_cse_id, num=10).execute() + return results['items'] if results else False + +def github(option, query): + if option == 'search': + data = json.loads(geturl('api.github.com', '/search/repositories?q='+query, headers={'Accept':'application/vnd.github.v3+json','User-Agent':'HateServ/1.0'})) + return data['items'] if data['items'] else False + elif option == 'repo': + return json.loads(geturl('api.github.com', '/repos/'+query, headers={'Accept':'application/vnd.github.v3+json','User-Agent':'HateServ/1.0'})) + elif option == 'user': + return json.loads(geturl('api.github.com', '/users/'+query, headers={'Accept':'application/vnd.github.v3+json','User-Agent':'HateServ/1.0'})) + +def imdb(query): + ''' https://www.omdbapi.com ''' + year = query.split()[-1] + query = query.replace(' ','%20') + search = 'i' if query.startswith('tt') else 't' + if search == 't' and len(year) == 4 and year.isdigit(): + endpoint = f'/?{search}={query[:-5]}&y={year}&apikey={api_key}' + else: + endpoint = f'/?{search}={query}&apikey={api_key}' + conn = http.client.HTTPSConnection('omdbapi.com', timeout=15) + conn.request('GET', endpoint, headers={'Accept':'application/json'}) + response = json.loads(conn.getresponse().read()) + conn.close() + return response if response['Response'] == 'True' else False + +def reddit(option, subreddit, id=None): + if option == 'post': + data = json.loads(geturl('reddit.com', f'/r/{subreddit}/comments/{id}.json', headers={'Accept':'application/json','User-Agent':'HateServ/1.0'})) + return data[0]['data']['children'][0]['data'] if 'error' not in data else False + elif option == 'subreddit': + data = json.loads(geturl('reddit.com', f'/r/{subreddit}.json?limit=20', headers={'Accept':'application/json','User-Agent':'HateServ/1.0'})) + posts = [item['data'] for item in data['data']['children'] if not item['data']['stickied']] + return posts if posts else None + +def youtube(option, query, api_key): + if option == 'video': + api = httplib.get_json(f'https://www.googleapis.com/youtube/v3/videos?key={config.api.google_api_key}&part=snippet,statistics&id={id}') + if api['items']: + api = api['items'][0] + data = {} + data['channel'] = api['snippet']['channelTitle'] + data['description'] = ' '.join(api['snippet']['description'].split()) + data['dislikes'] = api['statistics']['dislikeCount'] + data['likes'] = api['statistics']['likeCount'] + data['title'] = api['snippet']['title'] + data['views'] = api['statistics']['viewCount'] + return data + else: + return False + elif option == 'search': + service = build('youtube', 'v3', developerKey=api_key).search() + results = service.list(part='id', type='video', q=query, maxResults=10).execute() + return results['items'] if results else False + +def twitter(data): +# auth = tweepy.OAuthHandler(twitter_consumer_key, twitter_consumer_secret) +# auth.set_access_token(twitter_access_token, twitter_access_secret) +# api = tweepy.API(auth) +# api.update_status(data) + pass + +def unreal(): + pass + +def anope(): + pass + + +''' +elif args[0] == '.imdb' and len(args) >= 2: + query = ' '.join(args[1:]) + api = imdb.search(query, config.api.omdbapi_key) + if api: + Commands.sendmsg(chan, '{0} {1} {2} {3}'.format(color('Title :', white), api['Title'], api['Year'], color(api['Rated'], grey))) + Commands.sendmsg(chan, '{0} {1}{2}'.format(color('Link :', white), underline, color('https://imdb.com/title/' + api['imdbID'], light_blue))) + Commands.sendmsg(chan, '{0} {1}'.format(color('Genre :', white), api['Genre'])) + if api['imdbRating'] == 'N/A': + Commands.sendmsg(chan, '{0} {1} N/A'.format(color('Rating :', white), color('★★★★★★★★★★', grey))) + else: + Commands.sendmsg(chan, '{0} {1}{2} {3}'.format(color('Rating :', white), color('★'*round(float(api['imdbRating'])), yellow), color('★'*(10-round(float(api['imdbRating']))), grey), a +pi['imdbRating'])) + Commands.sendmsg(chan, '{0} {1}'.format(color('Plot :', white), api['Plot'])) + else: + Commands.error(chan, 'no results found') +''' \ No newline at end of file diff --git a/bots/hateserv/commands.py b/bots/hateserv/commands.py new file mode 100644 index 0000000..b6ab079 --- /dev/null +++ b/bots/hateserv/commands.py @@ -0,0 +1,143 @@ +import csv +import io +import json +import urllib.request +import sys +import time + +def download_file(url: str, dest_filename: str, chunk_size: int = 1024*1024): + ''' + Download a file from a given URL in chunks and save to a destination filename. + + :param url: The URL of the file to download + :param dest_filename: The destination filename to save the downloaded file + :param chunk_size: Size of chunks to download. Default is set to 1MB. + ''' + with urllib.request.urlopen(url) as response: + total_size = int(response.getheader('Content-Length').strip()) + downloaded_size = 0 + with open(dest_filename, 'wb') as out_file: + while True: + start_time = time.time() + chunk = response.read(chunk_size) + if not chunk: + break + downloaded_size += len(chunk) + out_file.write(chunk) + end_time = time.time() + speed = len(chunk) / (end_time - start_time) + progress = (downloaded_size / total_size) * 100 + sys.stdout.write(f'\rDownloaded {downloaded_size} of {total_size} bytes ({progress:.2f}%) at {speed/1024:.2f} KB/s\r') + sys.stdout.flush() + print() + +def get_url(url: str, sent_headers: dict = {}, reader: bool = True): + ''' + Retrieve a URL with custom headers. + + :param url: The URL to retrieve + :param data: The headers to send + :param reader: Return the reader object instead of the decoded data + ''' + req = urllib.request.Request(url, headers=sent_headers) + if reader: + return urllib.request.urlopen(req, timeout=10).read().decode() + else: + return urllib.request.urlopen(req, timeout=10) + +def setup_user_agent(user_agent: str = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'): + ''' + Set up urllib.request user agent. + + :param user_agent: The user agent to use + ''' + handler = urllib.request.HTTPHandler() + opener = urllib.request.build_opener(handler) + opener.addheaders = [('User-agent', user_agent)] + urllib.request.install_opener(opener) + + +# -------------------------------------------------------------------------------- # + +def asn_seach(query: str): + ''' + Search for an ASN by string. + + :param query: The string to search + ''' + return json.loads(get_url('https://api.bgpview.io/search?query_term='+query)) + +def cve_search(query: str, limit: str = '25'): + ''' + Search for a CVE by string. + + :param query: The string to search + :param limit: The number of results to return + ''' + return json.loads(get_url(f'https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch={query}&resultsPerPage={limit}')) + +def geoip(ip: str): + ''' + Get the geolocation of an IP address. + + :param ip: The IP address to geolocate + ''' + return json.loads(get_url('https://api.ipapi.is/?q='+ip)) + +def github(option: str, query: str): + ''' + Search for a GitHub repository or user. + + :param option: The option to search for (search, repo, user) + :param query: The query to search + ''' + header = {'Accept': 'application/vnd.github.v3+json'} + if option == 'search': + url = 'https://api.github.com/search/repositories?q=' + query + data = json.loads(get_url(url, header)) # Changed this line + return data['items'] if data['items'] else False + elif option == 'repo': + url = 'https://api.github.com/repos/' + query + return json.loads(get_url(url, header)) # And this one + elif option == 'user': + url = 'https://api.github.com/users/' + query + return json.loads(get_url(url, header)) # And this one + +def librex(query: str): + ''' + Search on the SuperNETs running LibreX. + + :param query: The query to search + ''' + return json.loads(get_url(f'https://librex.supernets.org/api.php?q={query}&t=0')) + +def reddit(option, subreddit, id=None): + ''' + Search for a Reddit post or subreddit. + + :param option: The option to search for (post, subreddit) + :param subreddit: The subreddit to search + :param id: The post ID to search + ''' + header = {'Accept':'application/json'} + if option == 'post': + data = json.loads(get_url('https://reddit.com', f'/r/{subreddit}/comments/{id}.json', header)) + return data[0]['data']['children'][0]['data'] if 'error' not in data else False + elif option == 'subreddit': + data = json.loads(get_url('https://reddit.com', f'/r/{subreddit}.json?limit=20', header)) + posts = [item['data'] for item in data['data']['children'] if not item['data']['stickied']] + return posts if posts else None + +def exploitdb(query: str): + ''' + Search for an exploit or shellcode on ExploitDB. + + :param query: The query to search + ''' + exploits = get_url('https://git.supernets.org/mirrors/exploitdb/raw/branch/main/files_exploits.csv') + shellcodes = get_url('https://git.supernets.org/mirrors/exploitdb/raw/branch/main/files_shellcodes.csv') + results = [] + for database in (exploits, shellcodes): + reader = csv.DictReader(io.StringIO(database)) + results += [row for row in reader if query.lower() in row['description'].lower()] + return results \ No newline at end of file diff --git a/hateserv/hateserv.py b/bots/hateserv/hateserv.py similarity index 77% rename from hateserv/hateserv.py rename to bots/hateserv/hateserv.py index abedb43..e4d7cc5 100644 --- a/hateserv/hateserv.py +++ b/bots/hateserv/hateserv.py @@ -1,21 +1,19 @@ #!/usr/bin/env python # hateserv irc bot - developed by acidvegas in python (https://git.acid.vegas/hateserv) -import json -import random import re import socket import ssl import time import urllib.request -import api +import commands # Config admin = 'acidvegas!~stillfree@most.dangerous.motherfuck' server = 'irc.supernets.org' channel = '#dev' -nickname = 'HateServ' +nickname = '[dev]HateServ' username = 'H' realname = 'SuperNETs HATE Services' nickserv_password = 'simps0nsfan22' @@ -70,18 +68,18 @@ def urlcheck(msg): url = url[0] try: if (check := re.match('^.*?github.com\/([0-9A-Za-z]+\/[0-9A-Za-z]+).*?', url, re.IGNORECASE)): - data = api.github('repo', check.group(1)) + data = commands.github('repo', check.group(1)) if data: if not data['description']: data['description'] = 'no description available' sendmsg(channel, '{0} {1} {2} [{3}:{4}|{5}:{6}|{7}:{8}]'.format(color(' GitHub ', black, grey), data['full_name'], color('('+data['description']+')', grey), color('Stars', purple), data['stargazers_count'], color('Watch', purple), data['watchers'], color('Forks', purple), data['forks'])) elif (check := re.match('^.*?github.com\/([0-9A-Za-z]+)', url, re.IGNORECASE)): - data = api.github('user', check.group(1)) + data = commands.github('user', check.group(1)) if data: data['bio'] = data['bio'].replace('\r\n','') if data['bio'] else '' sendmsg(channel, '{0} {1} {2} {3} [{4}:{5}|{6}:{7}]'.format(color(' GitHub ', black, grey), data['login'], color('('+data['name']+')', grey), data['bio'], color('Repos', purple), data['public_repos'], color('Followers', purple), data['followers'])) elif (check := re.match('^.*?reddit.com\/r\/(.*?)\/comments\/([0-9A-Za-z]+).*$', url, re.IGNORECASE)): - data = api.reddit('post', check.group(1), check.group(2)) + data = commands.reddit('post', check.group(1), check.group(2)) sendmsg(channel, '[{0}] - {1} [{2}/{3}|{4}]'.format(color('reddit', cyan), color(trim(data['title'], 300), white), color('+' + str(data['ups']), green), color('-' + str(data['downs']), red), color(str(data['num_comments']), white))) elif (check := re.match('^.*?youtu(be)?\.([a-z])+\/(watch(.*?)(\?|\&)v=)?(.*?)(&(.)*)*$', url, re.IGNORECASE)): pass @@ -109,67 +107,50 @@ def event_message(chan, nick, ident, msg): if ident == admin: if msg == '.massjoin': raw('WHO * n%nc') - elif args[0] == '.t': - content = msg[3:] - if len(content) < 240: - api.twitter('tweet', content) - sendmsg(chan, '\x01ACTION whispers "{content}" into Elon Musks ear...\x01') - else: - irc_error(chan, 'tweet too long (max: 240)') - if msg == '.talent': - if random.randint(1,5000) == 1337: - for i in range(100): - sendmsg(chan, nick + ': ' + color(' RIP-DIDDLE-DIP-DIP-DIP-DIP IT\'S YOUR BIRTHDAY !!! ', random.randint(2,13), random.randint(2,13))) - else: - sendmsg(chan, color('(^)', random.randint(2,13))) - elif args[0] == '.g': + if args[0] in ('.g','.s'): query = ' '.join(args[1:]) - results = api.google(query) + results = commands.librex(query) if results: for item in results: sendmsg(chan, '[{0}] {1}'.format(color(str(results.index(item)+1).zfill(2), pink), trim(item['title'], 300))) sendmsg(chan, ' '*5 + underline + color(item['link'], light_blue)) else: irc_error(chan, 'no results found') + elif args[0] == '.cve': + data = commands.cve_search(' '.join(args[1:])) + for item in data['vulnerabilities']: + id = item['cve']['id'] + desc = item['cve']['descriptions'][0]['value'] + sendmsg(chan, '[{0}] {1} - {2}'.format(color(str(data['vulnerabilities'].index(item)+1).zfill(2), pink), color(id, cyan), trim(desc, 300))) + elif args[0] == '.ip': + data = commands.geoip(args[1]) + location = '{0}, {1}, {2}'.format(data['location']['city'], data['location']['state'], data['location']['country_code']) + asn = 'AS{0} ({1})'.format(data['asn']['asn'], data['asn']['descr']) + sendmsg(chan, '[{0}] {1} under {2} controlled by {3}'.format(color('geoip', light_blue), color(location, yellow), color(asn, cyan), color(data['rir'], pink))) elif args[0] == '.gh': query = ' '.join(args[1:]).replace(' ','%20') - results = api.github('search',query) + results = commands.github('search',query) if results: for item in results: if not item['description']: item['description'] = 'no description' sendmsg(chan, '[{0}] {1}/{2}{3}{4} {5}'.format(color(str(results.index(item)+1).zfill(2), pink), item['owner']['login'], bold, item['name'], reset, color('('+item['description']+')', grey))) sendmsg(chan, ' '*5 + underline + color(item['html_url'], light_blue)) - elif args[0] == '.netsplit' and len(args) >= 2: - query = ' '.join(args[1:]) - results = api.netsplit('channels', query) - if results: - for item in results: - sendmsg(chan, '[{0}] {1} on {2} {3}'.format(color(str(results.index(item)+1).zfill(2), pink), color(item['channel'], purple), color(item['network'], yellow), color('('+item['users']+')', grey))) - sendmsg(chan, ' '*5 + color(trim(item['topic'], 300), light_blue)) - else: - irc_error(chan, 'no results found') elif args[0] == '.r' and len(args) == 2: query = args[1] - results = api.reddit('subreddit', query) + results = commands.reddit('subreddit', query) if results: for item in results: sendmsg(chan, '[{0}] {1} [{2}/{3}|{4}]'.format(color(str(results.index(item)+1).zfill(2), pink), trim(item['title'], 300), color('+' + str(item['ups']), green), color('-' + str(item['downs']), red), color(item['num_comments'], white))) sendmsg(chan, ' '*5 + underline + color(item['url'], light_blue)) else: irc_error(chan, 'no results found') - elif args[0] == '.yt': - query = ' '.join(args[1:]) - results = api.youtube('search', query) - if results: - for result in results: - sendmsg(chan, '[{0}] {1}'.format(color(str(results.index(item)+1).zfill(2), pink), trim(item['snippet']['title'], 300))) - sendmsg(chan, ' '*5 + underline + color('https://www.youtube.com/watch?v='+item['id']['videoId'], light_blue)) while True: - try: - sock = ssl.wrap_socket(socket.socket()) - sock.connect((server, 6697)) + #try: + #sock = ssl.wrap_socket(socket.socket()) + sock = socket.socket() + sock.connect((server, 6667)) raw(f'USER {username} 0 * :{realname}') raw('NICK ' + nickname) while True: @@ -201,16 +182,16 @@ while True: nick = args[0].split('!')[0][1:].lower() msg = ' '.join(args[3:])[1:] if chan == channel: - try: + #try: event_message(chan, nick, ident, msg) - except Exception as ex: - irc_error(chan, 'unknown error occured', ex) + #except Exception as ex: + # irc_error(chan, 'unknown error occured', ex) elif chan == nickname and ident == admin and msg.startswith('.raw '): raw(msg[5:]) except (UnicodeDecodeError, UnicodeEncodeError): pass - except Exception as ex: - error('fatal error occured', ex) - sock.close() - finally: - time.sleep(15) \ No newline at end of file + #except Exception as ex: + # error('fatal error occured', ex) + # sock.close() + #finally: + # time.sleep(15) \ No newline at end of file diff --git a/deploy/gitea b/deploy/gitea deleted file mode 100755 index d19cf93..0000000 --- a/deploy/gitea +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh -# gitea deployment helper - developed by acidvegas (https://git.acid.vegas) - -# Tranfser your Gitea backup file prior to using this script. -# Backup your previous instance with: gitea dump -c /etc/gitea/app.ini - -adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git - -# Grab the latest version of Gitea -wget -O gitea https://dl.gitea.com/gitea/1.21.4/gitea-1.21.4-linux-amd64 && chmod +x gitea -wget -O gitea.asc https://dl.gitea.com/gitea/1.21.4/gitea-1.21.4-linux-amd64.asc -gpg --keyserver keys.openpgp.org --recv 7C9E68152594688862D62AF62D9AE806EC1592E2 -gpg --verify gitea.asc gitea -rm gitea.asc -cp gitea /usr/local/bin/gitea - -# Prepair Gitea directories & permissions -mkdir -p /var/lib/gitea/{custom,data,log} -chown -R git:git /var/lib/gitea/ -chmod -R 750 /var/lib/gitea/ -mkdir /etc/gitea -chown root:git /etc/gitea -chmod 770 /etc/gitea - -# Extract the backup file -unzip gitea-dump-*.zip -cd gitea-dump-* -mv app.ini /etc/gitea/conf/app.ini -mv data/* /var/lib/gitea/data/ -mv log/* /var/lib/gitea/log/ -mv repos/* /var/lib/gitea/gitea-repositories/ - -# Finalize permissions -chown -R gitea:gitea /etc/gitea/conf/app.ini /var/lib/gitea -chmod 750 /etc/gitea -chmod 640 /etc/gitea/app.ini - -# Grab completions and service file -wget -O /usr/share/bash-completion/completions/gitea https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/autocompletion/bash_autocomplete -wget -O /etc/systemd/system/gitea.service https://raw.githubusercontent.com/go-gitea/gitea/release/v1.21/contrib/systemd/gitea.service - -# LET ER RIP !! -systemctl enable gitea && systemctl start gitea diff --git a/discordrelay.py b/discordrelay.py deleted file mode 100644 index 30e6b91..0000000 --- a/discordrelay.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# Discord IRC Relay - Developed by acidvegas in Python (https://git.acid.vegas/tools) - -import asyncio -import ssl - -class IRC: - def __init__(self): - self.options = {'host':'irc.supernets.org','port':6697,'limit':1024,'ssl':self.ssl_ctx(),'family':2,'local_addr':None} - self.reader, self.writer = (None, None) - - def ssl_ctx(self): - ctx = ssl.create_default_context() - ctx.check_hostname = False - ctx.verify_mode = ssl.CERT_NONE - #ctx.load_cert_chain(config.cert.file, password=config.cert.password) - return ctx - - def raw(self, data): - self.writer.write(data[:510].encode('utf-8') + b'\r\n') - - async def connect(self): - try: - self.reader, self.writer = await asyncio.open_connection(**self.options) - self.raw(f'USER relay 0 * :Discord Relay Bot') - self.raw('NICK DISCORD') - except Exception as ex: - print(f'[!] - Failed to connect to IRC server! ({ex!s})') - else: - while not self.reader.at_eof(): - try: - line = await self.reader.readline() - line = line.decode('utf-8').strip() - print('[IRC] ' + line) - args = line.split() - if args[0] == 'PING': - self.raw('PONG ' + args[1][1:]) - elif args[1] == '001': #RPL_WELCOME - self.raw('MODE DISCORD +BD') - self.raw('PRIVMSG NickServ :IDENTIFY DISCORD REDACTED') - self.raw('JOIN #superbowl') - elif args[1] == 'PRIVMSG': - nick = args[0].split('!')[0][1:] - chan = args[2] - msg = ' '.join(args[3:])[1:] - if chan == '#superbowl' and nick not in ('DISCORD','EliManning','CANCER','scroll','DickServ','AMBERALERT'): - if '\x02' not in msg and '\x03' not in msg and '\x1D' not in msg and '\x1F' not in msg and '\x16' not in msg: - DiscordBot.queue.append(f'{nick}: {msg}') - except (UnicodeDecodeError, UnicodeEncodeError): - pass - except Exception as ex: - print(f'[!] - Unknown error has occured! ({ex!s})') - -Bot_IRC = IRC() - -# ---------------------------------------------------------------------------------------------------- # - -try: - import discord -except ImportError: - raise SystemExit('missing discord modules (https://pypi.org/project/discord.py/)') - -class Discord(discord.Client): - server_id = 'CHANGEME' - channel_id = 'CHANGEME' - admin_id = 'CHANGEME' - queue = list() - - async def queue_loop(self): - while True: # 5 every 5 minutes? - if self.queue: - message = '\n'.join(self.queue)[:2000] - await self.channel_id.send(message) - self.queue = list() - await asyncio.sleep(1) - - async def on_message(self, message): - if message.author == self.user or message.channel != self.channel_id: - return - content = message.clean_content - if len(message.attachments) > 0: - content += ' ' + message.attachments[0].url - print(f'[Discord] {message.author.name}: {content}') - Bot_IRC.raw(f'PRIVMSG #superbowl :{message.author.name}: {content}') - - async def on_ready(self): - print(f'[Discord] Client: {self.user.name} ({self.user.id!s})') - self.server_id = [x for x in self.guilds if str(x.id) == self.server_id][0] - self.channel_id = [x for x in self.server_id.channels if str(x.id) == self.channel_id and x.type == discord.ChannelType.text][0] - print(f'[Discord] Server: {self.server_id} ({self.channel_id!s})') - asyncio.create_task(self.queue_loop()) - asyncio.create_task(Bot_IRC.connect()) - -DiscordBot = Discord() -DiscordBot.run('CHANGEME') \ No newline at end of file diff --git a/hateserv/api.py b/hateserv/api.py deleted file mode 100644 index 349e71d..0000000 --- a/hateserv/api.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python -# hateserv irc bot - developed by acidvegas in python (https://git.acid.vegas/hateserv) - -import http.client -import json -import re -import urllib.parse - -from googleapiclient.discovery import build # https://pypi.org/project/google-api-python-client/ -#import tweepy # https://pypi.org/project/tweepy/ - -# API Keys -google_api_key = 'redacted' # https://console.developers.google.com/ -google_cse_id = 'redacted' # https://cse.google.com/ -twitter_bearer_token = 'redacted' -twitter_access_token = 'redacted' -twitter_access_token_secret = 'redacted' -twitter_client_id = 'redacted' -twitter_client_secret = 'redacted' -twitter_api_key = 'redacted' -twitter_api_secret = 'redacted' - -def between(source, start, stop): - data = re.compile(start + '(.*?)' + stop, re.IGNORECASE|re.MULTILINE).search(source) - return data.group(1) if data else False - -def geturl(url, endpoint, headers={}): - conn = http.client.HTTPSConnection(url, timeout=15) - conn.request('GET', endpoint, headers=headers) - response = conn.getresponse().read() - conn.close() - return response - -def google(query): - service = build('customsearch', 'v1', developerKey=google_api_key, cache_discovery=False).cse() - results = service.list(q=query, cx=google_cse_id, num=10).execute() - return results['items'] if results else False - -def netsplit(option, query): - if option == 'channels': - data = str(geturl('netsplit.de', '/channels/?chat='+query)) - for i in ('​','','','','','',''): - data = data.replace(i, '') - results = re.findall('
(.*?)
', data, re.IGNORECASE|re.MULTILINE) - if results: - channels = list() - for item in results: - channel = between(item, '', '') - network = between(item, '', '') - users = between(item, ' - ', ' users - ') - if 'current topic:' in item: - topic = between(item, 'current topic: ', '
').replace('
','') - else: - topic = 'no topic set for channel' - channels.append({'channel':channel, 'network':network, 'users':users, 'topic':topic}) - return channels - else: - return False - elif option == 'networks': - data = str(geturl('netsplit.de', '/networks/')) - results = re.findall(' /etc/resolv.conf + chattr +i /etc/resolv.conf + + # Update & Install Packages + apt-get update && apt-get upgrade + apt-get install bridge-utils dirmngr htop gpg lxc man net-tools uidmap screen unattended-upgrades + + # Wipe the journal and only use RAM storage + journalctl --vacuum-time=1d + printf "[Journal]\nStorage=volatile\nSplitMode=none\nRuntimeMaxUse=500K\n" > /etc/systemd/journald.conf + systemctl restart systemd-journald + + # Install & setup dropbear + apt-get install -y dropbear + printf 'NO_START=0\nDROPBEAR_PORT=$SSH_PORT\nDROPBEAR_EXTRA_ARGS=\nDROPBEAR_BANNER=\"\"\nDROPBEAR_ED25519KEY=\"/etc/dropbear/dropbear_ed25519_host_key\"\nDROPBEAR_RECEIVE_WINDOW=65536\n' > /etc/default/dropbear + systemctl restart dropbear && systemctl enable dropbear + + # Remove OpenSSH + apt remove openssh-server && apt remove openssh-client + apt purge openssh-server && apt purge openssh-client + apt autoremove && apt autoclean + systemctl stop ssh && systemctl disable ssh + + # Disable history, logs, & IPv6 + printf "\nHISTSIZE=0\nHISTFILESIZE=0\nunset HISTFILE\n" >> /etc/bash.bashrc + >/var/log/lastlog && chattr +i /var/log/lastlog + sed -i 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="ipv6.disable=1"/' /etc/default/grub && update-grub + + # Set locales + echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen + + # Add a new user + useradd -m -s /bin/bash $USER_NAME && passwd $USER_NAME + + # Change hostname + nano /etc/hostname + + # Enable user-level services + loginctl enable-linger $USER_NAME + + # Configure NAT + iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE + echo "1" > /proc/sys/net/ipv4/ip_forward + printf "\nnet.ipv4.ip_forward=1\n" > /etc/sysctl.conf + + # Create a runtime directory with the correct permissions + mkdir -p /run/user/$(id -u $USER_NAME) + chown $USER_NAME:$USER_NAME /run/user/$(id -u $USER_NAME) + chmod 700 /run/user/$(id -u $USER_NAME) + + # Set the subordinate UID/GID + echo "$USER_NAME:100000:65536" > /etc/subuid + echo "$USER_NAME:100000:65536" > /etc/subgid + + # Create bridge (usually done automatically, see `ip addr` output for lxcbr0) + #brctl addbr lxcbr0 + #ip addr add 192.168.1.10/24 dev lxcbr0 + #ip link set dev lxcbr0 up + + # Restart the LXC service + systemctl restart lxc +} + +setup_user() { + # Add dropbear public key + mkdir -p $HOME/.ssh + printf "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBgw6zK6LghGq/6fdMGFKfH9fr+qCOASlD+Xi7Zoe7Ps acidvegas@blackhole" > $HOME/.ssh/authorized_keys + chmod 700 $HOME/.ssh + chown -R $USER $HOME/.ssh + chmod 400 $HOME/.ssh/authorized_keys + chattr +i $HOME/.ssh + chattr +i $HOME/.ssh/authorized_keys + + # Setup LXC configuration + mkdir -p ~/.config/lxc + printf "lxc.idmap = u 0 100000 65536\nlxc.idmap = g 0 100000 65536\nlxc.net.0.type = veth\nlxc.net.0.link = lxcbr0\nlxc.net.0.flags = up\nlxc.start.auto = 1\nlxc.start.delay = 5\n" > $HOME/.config/lxc/default.conf + + # Setup runtime directory + echo 'export XDG_RUNTIME_DIR=/run/user/$(id -u $USER)' >> ~/.bashrc + export XDG_RUNTIME_DIR=/run/user/$(id -u $USER) + + # Create a systemd user service + mkdir -p $HOME/.config/systemd/user + printf "[Unit]\nDescription=LXC Container %I\nAfter=network.target\n\n[Service]\nType=forking\nExecStart=/usr/bin/lxc-start -n %i\nExecStop=/usr/bin/lxc-stop -n %i\nRestart=on-failure\n\n[Install]\nWantedBy=default.target\n" > $HOME/.config/systemd/user/lxc-container@.service + + # Create a container + lxc-create -n $container -t download -- --dist debian --release bullseye --arch amd64 + + # Start & enable the service + systemctl --user enable lxc-container@${container}.service + systemctl --user start lxc-container@${container}.service +} + +setup_container() { + # TODO: Provision container for services + return +} + +#setup_root +#setup_user diff --git a/help/ircwall b/help/ircwall new file mode 100644 index 0000000..b04b3a8 --- /dev/null +++ b/help/ircwall @@ -0,0 +1,70 @@ +#!/bin/sh +# IRCd Firewall - Developed by acidvegas (https://git.acid.vegas/supertools) + +# nano /etc/default/grub +# Add ipv6.disable=1 to GRUB_CMDLINE_LINUX_DEFAULT then run update-grub + +# Configuration +IP_MAIN="10.0.0.1" # Change this to your IP +IP_HUB="10.0.0.2" # Change this to your hub IP +PORT_SSH=22 # Default 22 +PORT_HUB=5900 # Default 5900 + +# Kernel hardening settings +mkdir -p /etc/sysctl.d +{ + printf "net.ipv4.conf.all.accept_source_route = 0\n" + printf "net.ipv6.conf.all.accept_source_route = 0\n" + printf "net.ipv4.conf.all.rp_filter = 1\n" + printf "net.ipv4.conf.default.rp_filter = 1\n" + printf "net.ipv4.conf.all.accept_redirects = 0\n" + printf "net.ipv6.conf.all.accept_redirects = 0\n" + printf "net.ipv4.conf.default.accept_redirects = 0\n" + printf "net.ipv6.conf.default.accept_redirects = 0\n" + printf "net.ipv4.conf.all.log_martians = 1\n" + printf "kernel.randomize_va_space = 2\n" + printf "fs.suid_dumpable = 0\n" +} > /etc/sysctl.d/99-custom-hardening.conf + +# Apply hardening settings +sysctl -p /etc/sysctl.d/99-custom-hardening.conf + +# Flush existing rules +iptables -F +iptables -X +iptables -t nat -F +iptables -t nat -X +iptables -t mangle -F +iptables -t mangle -X + +# Default chain policies +iptables -P INPUT DROP +iptables -P FORWARD DROP +iptables -P OUTPUT ACCEPT + +# Common Firewall rules +iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +iptables -A INPUT -p icmp --icmp-type echo-request -j DROP +iptables -A INPUT -i lo -j ACCEPT + +# Allow SSH +iptables -A INPUT -p tcp -s $IP_MAIN --dport $PORT_SSH -j ACCEPT + +# Allow IRCd Hub +iptables -A INPUT -p tcp -s $IP_HUB --dport $PORT_HUB -j ACCEPT + +# Allow IRCd Ports +iptables -A INPUT -p tcp --dport 6660:6669 -j ACCEPT +iptables -A INPUT -p tcp --dport 7000 -j ACCEPT + +# Allow IRCd TLS Ports +iptables -A INPUT -p tcp --dport 6697 -j ACCEPT +iptables -A INPUT -p tcp --dport 9999 -j ACCEPT + +# Save rules +apt-get install -y iptables-persistent +netfilter-persistent save +systemctl enable netfilter-persistent && systemctl start netfilter-persistent + +# Show rules +iptables -L -v -n diff --git a/monitor b/help/monitor similarity index 100% rename from monitor rename to help/monitor diff --git a/nc.py b/help/namecheap.py similarity index 87% rename from nc.py rename to help/namecheap.py index 402aff3..e836709 100644 --- a/nc.py +++ b/help/namecheap.py @@ -1,9 +1,6 @@ #!/usr/bin/env python # supernets namecheap api tool - developed by acidvegas in python (https://git.acid.vegas/supertools) -''' tool for automatically renewing positivessl certificates ''' -''' this is still a work in progress...good thing i have a year to finish ''' - import re import requests import xml.etree.ElementTree as et @@ -35,11 +32,11 @@ class domains: def setHosts(type, address): payload = { - 'SLD' : 'supernets' - 'TLD' : 'org' + 'SLD' : 'supernets', + 'TLD' : 'org', 'HostName' : 'irc', 'RecordType' : type, - 'Address' : address + 'Address' : address, 'TTL' : '60' } data = api('namecheap.domains.dns.setHosts', payload) @@ -72,7 +69,7 @@ class ssl: def renew(id): '''https://www.namecheap.com/support/api/methods/ssl/renew/''' payload = { - 'CertificateID':id. + 'CertificateID':id, 'SSLType': 'PositiveSSL', 'years': '1' # or 5 } diff --git a/startbots b/help/startbots similarity index 100% rename from startbots rename to help/startbots