diff --git a/README.md b/README.md new file mode 100644 index 0000000..56bbd8b --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# Chrome's Hammer + +A Chrome App that runs a local SOCKS5 proxy on `127.0.0.1:1080`, routing traffic through Chrome's networking stack. + +## Installation + +1. Go to `chrome://extensions/` +2. Enable "Developer mode" +3. Click "Load unpacked" +4. Select this folder + +## Usage Examples + +### curl +```bash +curl --socks5 127.0.0.1:1080 https://httpbin.org/ip +``` + +### ssh +```bash +ssh -o ProxyCommand="nc -X 5 -x 127.0.0.1:1080 %h %p" user@host +``` + +### perl +```perl +use IO::Socket::SOCKS; +my $sock = IO::Socket::SOCKS->new( + ProxyAddr => '127.0.0.1', + ProxyPort => 1080, + ConnectAddr => 'httpbin.org', + ConnectPort => 80 +); +``` + +### nodejs +```bash +npm install socks-proxy-agent +``` + +```javascript +const { SocksProxyAgent } = require('socks-proxy-agent'); +const agent = new SocksProxyAgent('socks5://127.0.0.1:1080'); + +fetch('https://httpbin.org/ip', { agent }) + .then(r => r.json()) + .then(console.log); +``` + +## How It Works + +Chrome's Hammer acts as a true SOCKS5 proxy server, creating bidirectional TCP tunnels between your applications and destination servers through Chrome's networking. diff --git a/background.js b/background.js index 0445880..daf9d40 100644 --- a/background.js +++ b/background.js @@ -1,5 +1,5 @@ /** - * Chrome App - SOCKS5 Proxy with Bidirectional Tunneling + * Chrome's Hammer - SOCKS5 Proxy with Bidirectional Tunneling * Supports both HTTP and HTTPS through true SOCKS5 tunneling */ @@ -367,7 +367,7 @@ function handleDestinationData(destSocketId, data) { function setupConnectionHandlers() { // Handle new connections from clients chrome.sockets.tcpServer.onAccept.addListener(function(acceptInfo) { - console.log('[Proxy] New client connected: ' + acceptInfo.clientSocketId); + console.log('[Hammer] New client connected: ' + acceptInfo.clientSocketId); // Initialize SOCKS state for this connection initConnection(acceptInfo.clientSocketId); @@ -378,7 +378,7 @@ function setupConnectionHandlers() { // Handle accept errors chrome.sockets.tcpServer.onAcceptError.addListener(function(errorInfo) { - console.error('[Proxy] Accept error:', errorInfo); + console.error('[Hammer] Accept error:', errorInfo); }); // Handle receive errors @@ -388,9 +388,9 @@ function setupConnectionHandlers() { // Error code -100 is ERR_CONNECTION_CLOSED - normal disconnect, not an error if (resultCode === -100) { - console.log('[Proxy] Socket ' + socketId + ' connection closed'); + console.log('[Hammer] Socket ' + socketId + ' connection closed'); } else { - console.error('[Proxy] Receive error on socket ' + socketId + ': ' + resultCode); + console.error('[Hammer] Receive error on socket ' + socketId + ': ' + resultCode); } // Clean up connections @@ -405,7 +405,7 @@ function setupConnectionHandlers() { chrome.sockets.tcp.onReceive.addListener(function(receiveInfo) { if (receiveInfo.data.byteLength === 0) { var socketId = receiveInfo.socketId; - console.log('[Proxy] Socket ' + socketId + ' disconnected (EOF)'); + console.log('[Hammer] Socket ' + socketId + ' disconnected (EOF)'); if (connections[socketId]) { closeConnection(socketId); } else if (reverseConnections[socketId]) { @@ -420,13 +420,13 @@ function setupConnectionHandlers() { // Check if this is data from a client or destination if (connections[socketId]) { // Data from client - console.log('[Proxy] Received from client ' + socketId + ': ' + receiveInfo.data.byteLength + ' bytes'); + console.log('[Hammer] Received from client ' + socketId + ': ' + receiveInfo.data.byteLength + ' bytes'); handleSocksData(socketId, receiveInfo.data); } else if (reverseConnections[socketId]) { // Data from destination handleDestinationData(socketId, receiveInfo.data); } else { - console.warn('[Proxy] Received data from unknown socket: ' + socketId); + console.warn('[Hammer] Received data from unknown socket: ' + socketId); } }); } @@ -434,21 +434,21 @@ function setupConnectionHandlers() { function initializeProxy() { // Prevent double initialization if (isInitialized) { - console.log('[Proxy] Already initialized or initializing...'); + console.log('[Hammer] Already initialized or initializing...'); return; } isInitialized = true; - console.log('[Proxy] Initializing Chrome SOCKS Proxy (with tunneling)...'); + console.log('[Hammer] Initializing Chrome\'s Hammer (with tunneling)...'); createServer(PROXY_HOST, PROXY_PORT, function(error, socketId) { if (error) { - console.error('[Proxy] Failed to initialize:', error); + console.error('[Hammer] Failed to initialize:', error); isInitialized = false; // Allow retry on failure return; } - console.log('[Proxy] SOCKS proxy is running on ' + PROXY_HOST + ':' + PROXY_PORT); + console.log('[Hammer] Chrome\'s Hammer is running on ' + PROXY_HOST + ':' + PROXY_PORT); // Setup handlers only once if (!handlersSetup) { @@ -460,13 +460,13 @@ function initializeProxy() { // Chrome App lifecycle events chrome.app.runtime.onLaunched.addListener(function() { - console.log('[Proxy] App launched'); + console.log('[Hammer] App launched'); initializeProxy(); }); // Chrome App lifecycle - restart when app is restarted chrome.app.runtime.onRestarted.addListener(function() { - console.log('[Proxy] App restarted'); + console.log('[Hammer] App restarted'); // Reset state and reinitialize isListening = false; isInitialized = false; @@ -476,7 +476,7 @@ chrome.app.runtime.onRestarted.addListener(function() { // Handle the app window being closed chrome.app.window.onClosed.addListener(function() { - console.log('[Proxy] App window closed'); + console.log('[Hammer] App window closed'); // Clean up connections for (var socketId in connections) { try { @@ -510,11 +510,11 @@ chrome.alarms.create('keepAlive', { periodInMinutes: 1 }); chrome.alarms.onAlarm.addListener(function(alarm) { if (alarm.name === 'keepAlive') { // Heartbeat: log activity to keep the app alive - console.log('[Proxy] Heartbeat - Proxy is ' + (isListening ? 'active' : 'inactive')); + console.log('[Hammer] Heartbeat - Proxy is ' + (isListening ? 'active' : 'inactive')); // Check if server is still listening, restart if needed if (!isListening && !isInitialized) { - console.log('[Proxy] Server not listening, reinitializing...'); + console.log('[Hammer] Server not listening, reinitializing...'); initializeProxy(); } @@ -525,18 +525,18 @@ chrome.alarms.onAlarm.addListener(function(alarm) { // Handle when app is suspended and resumed chrome.runtime.onSuspend.addListener(function() { - console.log('[Proxy] App being suspended...'); + console.log('[Hammer] App being suspended...'); }); chrome.runtime.onSuspendCanceled.addListener(function() { - console.log('[Proxy] Suspend canceled - app is active again'); + console.log('[Hammer] Suspend canceled - app is active again'); // Reinitialize if needed after unsuspend if (!isListening) { - console.log('[Proxy] Reinitializing after unsuspend...'); + console.log('[Hammer] Reinitializing after unsuspend...'); isInitialized = false; initializeProxy(); } }); -console.log('[Proxy] Background script loaded'); +console.log('[Hammer] Chrome\'s Hammer background script loaded'); diff --git a/icon-128.png b/icon-128.png new file mode 100644 index 0000000..95877bd Binary files /dev/null and b/icon-128.png differ diff --git a/icon-16.png b/icon-16.png new file mode 100644 index 0000000..82594c9 Binary files /dev/null and b/icon-16.png differ diff --git a/icon-48.png b/icon-48.png new file mode 100644 index 0000000..c907eb9 Binary files /dev/null and b/icon-48.png differ diff --git a/icon.html b/icon.html new file mode 100644 index 0000000..574a7a7 --- /dev/null +++ b/icon.html @@ -0,0 +1,114 @@ + + + + Chrome's Hammer Icon + + + +

Chrome's Hammer - Icon Generator

+ +
+

How to save the icon:

+
    +
  1. Right-click on one of the icons below
  2. +
  3. Select "Save image as..." or take a screenshot
  4. +
  5. Save as icon.png in the chrome_hammer folder
  6. +
  7. For best quality, use the 256x256 size and let Chrome resize it
  8. +
+
+ +
+

128x128 (Standard)

+ + + + + + + + + + + + + + + + + +
+ +
+

256x256 (High Quality)

+ + + + + + + + + + + + + + + + + +
+ +
+

48x48 (Small)

+ + + + + + + + + + + + + + + + + +
+ + \ No newline at end of file diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..37a7266 Binary files /dev/null and b/icon.png differ diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..a3344c8 --- /dev/null +++ b/icon.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/manifest.json b/manifest.json index 479c970..100c1eb 100644 --- a/manifest.json +++ b/manifest.json @@ -1,8 +1,13 @@ { "manifest_version": 2, - "name": "Chrome SOCKS Proxy", + "name": "Chrome's Hammer", "version": "1.0.0", - "description": "Local SOCKS5 proxy that routes requests through Chrome browser", + "description": "Local SOCKS5 proxy - routes requests through Chrome's networking", + "icons": { + "16": "icon-16.png", + "48": "icon-48.png", + "128": "icon-128.png" + }, "app": { "background": { "scripts": ["background.js"]