summaryrefslogtreecommitdiffstats
path: root/fog-client.sh
diff options
context:
space:
mode:
Diffstat (limited to 'fog-client.sh')
-rw-r--r--fog-client.sh349
1 files changed, 349 insertions, 0 deletions
diff --git a/fog-client.sh b/fog-client.sh
new file mode 100644
index 0000000..92d4327
--- /dev/null
+++ b/fog-client.sh
@@ -0,0 +1,349 @@
+#!/bin/bash
+# fog-client.sh - Interactive SMTP client for fog network
+# Selects random entry node and sends message
+
+VERSION="1.0"
+
+# Colors
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+CYAN='\033[0;36m'
+BLUE='\033[0;34m'
+MAGENTA='\033[0;35m'
+NC='\033[0m'
+
+# fog network nodes (onion addresses)
+NODES=(
+ "ej5dj774rkmfxvo3jexcmyotkq6bwgmr45dmwrbmk366lcvalnrgolad.onion:2525" # kvara
+ "iycr4wfrdzieogdfeo7uxrj77w2vjlrhlrv3jg2ve62oe5aceqsqu7ad.onion:2525" # dries
+ "66ehoz4ir6beuovmgt4gbpdfpmy43iuouj36dylqvkwgyp2dwpcbvjqd.onion:2525" # mct8
+ "y3lozzcvvxgorgfofupvfmn4j2fuu3sz2sw7ha3ifpcsxjkuafllzvyd.onion:2525" # news
+ "ejdrw3ka2mjhvsuz7uxjnzjircsdpoiu3a33g2xoywlafqetptjpqryd.onion:2525" # pietro
+)
+
+NODE_NAMES=("kvara" "dries" "mct8" "news" "pietro")
+
+# Tor SOCKS proxy
+TOR_PROXY="127.0.0.1:9050"
+
+# Functions
+print_header() {
+ echo -e "${CYAN}"
+ echo "╔═══════════════════════════════════════════════════════════╗"
+ echo "║ 🌫️ fog Network Client v${VERSION} ║"
+ echo "║ Anonymous SMTP Relay - Sphinx Mixnet ║"
+ echo "╚═══════════════════════════════════════════════════════════╝"
+ echo -e "${NC}"
+}
+
+check_dependencies() {
+ local missing=0
+
+ # Check nc (netcat)
+ if ! command -v nc &> /dev/null; then
+ echo -e "${RED}✗ netcat not found${NC}"
+ echo " Install: sudo apt install netcat-openbsd"
+ missing=1
+ fi
+
+ # Check torify
+ if ! command -v torify &> /dev/null; then
+ echo -e "${RED}✗ torify not found${NC}"
+ echo " Install: sudo apt install tor"
+ missing=1
+ fi
+
+ # Check if Tor is running
+ if ! pgrep -x tor > /dev/null; then
+ echo -e "${RED}✗ Tor is not running${NC}"
+ echo " Start: sudo systemctl start tor"
+ missing=1
+ fi
+
+ if [ $missing -eq 1 ]; then
+ echo ""
+ echo -e "${RED}Please install missing dependencies and try again.${NC}"
+ exit 1
+ fi
+
+ echo -e "${GREEN}✓ All dependencies installed${NC}"
+ echo ""
+}
+
+select_random_node() {
+ local random_index=$((RANDOM % ${#NODES[@]}))
+ SELECTED_NODE="${NODES[$random_index]}"
+ SELECTED_NAME="${NODE_NAMES[$random_index]}"
+
+ echo -e "${CYAN}Entry Node:${NC} ${MAGENTA}${SELECTED_NAME}${NC}"
+ echo -e "${CYAN}Address:${NC} ${SELECTED_NODE}"
+ echo ""
+}
+
+read_multiline() {
+ local prompt="$1"
+ local varname="$2"
+
+ echo -e "${YELLOW}${prompt}${NC}"
+ echo -e "${CYAN}(Press Ctrl+D when done, or enter a dot '.' on a line by itself)${NC}"
+
+ local input=""
+ local line
+
+ while IFS= read -r line; do
+ if [ "$line" = "." ]; then
+ break
+ fi
+ input="${input}${line}"$'\n'
+ done
+
+ eval "$varname=\$input"
+}
+
+generate_message_id() {
+ echo "<$(cat /dev/urandom | tr -dc 'a-f0-9' | fold -w 32 | head -n 1)@fog-client>"
+}
+
+send_message() {
+ local from="$1"
+ local to="$2"
+ local subject="$3"
+ local body="$4"
+
+ echo -e "${CYAN}Connecting to ${SELECTED_NAME} via Tor...${NC}"
+
+ local msgid=$(generate_message_id)
+ local date=$(date -R)
+
+ # Build SMTP conversation
+ {
+ sleep 1
+ echo "EHLO fog-client"
+ sleep 0.5
+ echo "MAIL FROM:<${from}>"
+ sleep 0.5
+ echo "RCPT TO:<${to}>"
+ sleep 0.5
+ echo "DATA"
+ sleep 0.5
+ echo "From: ${from}"
+ echo "To: ${to}"
+ echo "Subject: ${subject}"
+ echo "Message-ID: ${msgid}"
+ echo "Date: ${date}"
+ echo "Content-Type: text/plain; charset=utf-8"
+ echo ""
+ echo -e "${body}"
+ echo "."
+ sleep 0.5
+ echo "QUIT"
+ } | torify nc ${SELECTED_NODE/:/ } 2>&1 | while IFS= read -r line; do
+ if [[ $line =~ ^[0-9]{3} ]]; then
+ echo -e "${BLUE}← ${line}${NC}"
+ else
+ echo -e "${CYAN} ${line}${NC}"
+ fi
+ done
+
+ local exit_code=${PIPESTATUS[0]}
+
+ echo ""
+
+ if [ $exit_code -eq 0 ]; then
+ echo -e "${GREEN}✓ Message sent successfully!${NC}"
+ echo -e "${CYAN}Message-ID: ${msgid}${NC}"
+ else
+ echo -e "${RED}✗ Failed to send message${NC}"
+ return 1
+ fi
+}
+
+show_summary() {
+ local from="$1"
+ local to="$2"
+ local subject="$3"
+
+ echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
+ echo -e "${CYAN}Message Summary:${NC}"
+ echo -e " ${BLUE}From:${NC} ${from}"
+ echo -e " ${BLUE}To:${NC} ${to}"
+ echo -e " ${BLUE}Subject:${NC} ${subject}"
+ echo -e " ${BLUE}Via:${NC} ${SELECTED_NAME} (random entry node)"
+ echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
+ echo ""
+}
+
+interactive_mode() {
+ echo -e "${CYAN}Enter message details:${NC}"
+ echo ""
+
+ # From
+ read -p "$(echo -e ${YELLOW}From email address: ${NC})" from
+ if [ -z "$from" ]; then
+ echo -e "${RED}Error: From address required${NC}"
+ exit 1
+ fi
+
+ # To
+ read -p "$(echo -e ${YELLOW}To email address: ${NC})" to
+ if [ -z "$to" ]; then
+ echo -e "${RED}Error: To address required${NC}"
+ exit 1
+ fi
+
+ # Subject
+ read -p "$(echo -e ${YELLOW}Subject: ${NC})" subject
+ if [ -z "$subject" ]; then
+ subject="(no subject)"
+ fi
+
+ echo ""
+
+ # Body (multiline)
+ local body
+ read_multiline "Message body:" body
+
+ if [ -z "$body" ]; then
+ echo -e "${RED}Error: Message body required${NC}"
+ exit 1
+ fi
+
+ echo ""
+ show_summary "$from" "$to" "$subject"
+
+ # Confirm
+ read -p "$(echo -e ${YELLOW}Send message? [y/N]: ${NC})" confirm
+
+ if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
+ echo -e "${CYAN}Cancelled${NC}"
+ exit 0
+ fi
+
+ echo ""
+ send_message "$from" "$to" "$subject" "$body"
+}
+
+usenet_helper() {
+ echo -e "${CYAN}Usenet Posting Helper${NC}"
+ echo ""
+
+ # From
+ read -p "$(echo -e ${YELLOW}From (display name): ${NC})" from_name
+ if [ -z "$from_name" ]; then
+ from_name="Anonymous"
+ fi
+ from="${from_name} <noreply@example.com>"
+
+ # Newsgroups
+ read -p "$(echo -e ${YELLOW}Newsgroups (e.g., alt.test): ${NC})" newsgroups
+ if [ -z "$newsgroups" ]; then
+ echo -e "${RED}Error: Newsgroups required${NC}"
+ exit 1
+ fi
+
+ # Subject
+ read -p "$(echo -e ${YELLOW}Subject: ${NC})" subject
+ if [ -z "$subject" ]; then
+ subject="(no subject)"
+ fi
+
+ echo ""
+
+ # Body
+ local body
+ read_multiline "Post body:" body
+
+ if [ -z "$body" ]; then
+ echo -e "${RED}Error: Post body required${NC}"
+ exit 1
+ fi
+
+ # Add Newsgroups header to body
+ local full_body="Newsgroups: ${newsgroups}"$'\n'"${body}"
+
+ # Use mail2news gateway
+ local to="mail2news@mail2news.tcpreset.net"
+
+ echo ""
+ echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
+ echo -e "${CYAN}Usenet Post Summary:${NC}"
+ echo -e " ${BLUE}From:${NC} ${from}"
+ echo -e " ${BLUE}Newsgroups:${NC} ${newsgroups}"
+ echo -e " ${BLUE}Subject:${NC} ${subject}"
+ echo -e " ${BLUE}Gateway:${NC} ${to}"
+ echo -e " ${BLUE}Via:${NC} ${SELECTED_NAME} (random entry node)"
+ echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
+ echo ""
+
+ # Confirm
+ read -p "$(echo -e ${YELLOW}Post to Usenet? [y/N]: ${NC})" confirm
+
+ if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
+ echo -e "${CYAN}Cancelled${NC}"
+ exit 0
+ fi
+
+ echo ""
+ send_message "$from" "$to" "$subject" "$full_body"
+}
+
+show_help() {
+ echo "Usage: $0 [OPTIONS]"
+ echo ""
+ echo "Options:"
+ echo " -h, --help Show this help message"
+ echo " -u, --usenet Usenet posting mode"
+ echo " -v, --version Show version"
+ echo ""
+ echo "Interactive mode (default):"
+ echo " Prompts for From, To, Subject, and Body"
+ echo " Selects random entry node from fog network"
+ echo " Sends message via Tor"
+ echo ""
+ echo "Examples:"
+ echo " $0 # Interactive email mode"
+ echo " $0 --usenet # Interactive Usenet posting mode"
+ echo ""
+}
+
+# Main
+main() {
+ local mode="email"
+
+ # Parse arguments
+ while [[ $# -gt 0 ]]; do
+ case $1 in
+ -h|--help)
+ show_help
+ exit 0
+ ;;
+ -u|--usenet)
+ mode="usenet"
+ shift
+ ;;
+ -v|--version)
+ echo "fog-client v${VERSION}"
+ exit 0
+ ;;
+ *)
+ echo "Unknown option: $1"
+ show_help
+ exit 1
+ ;;
+ esac
+ done
+
+ print_header
+ check_dependencies
+ select_random_node
+
+ if [ "$mode" = "usenet" ]; then
+ usenet_helper
+ else
+ interactive_mode
+ fi
+}
+
+# Run
+main "$@"