Skip to content

Commit 6f492d7

Browse files
committed
first commit
0 parents  commit 6f492d7

File tree

12 files changed

+1670
-0
lines changed

12 files changed

+1670
-0
lines changed

.gitignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Development files
2+
*.log
3+
*.tmp
4+
.DS_Store
5+
Thumbs.db
6+
7+
# Editor files
8+
.vscode/
9+
.idea/
10+
*.swp
11+
*.swo
12+
13+
# Temporary files
14+
temp/
15+
tmp/
16+
*.bak
17+
18+
# Firefox extension development
19+
web-ext-artifacts/
20+
*.xpi
21+
*.zip
22+
23+
# Node modules (if any)
24+
node_modules/
25+
package-lock.json
26+
yarn.lock

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 bigsk1
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Container Proxy
2+
3+
A modern Firefox extension for assigning different proxies to Firefox containers, enabling secure and organized browsing with multiple proxy configurations.
4+
5+
## 🌟 Features
6+
7+
- **Container-Based Proxy Assignment**: Assign different proxies to different Firefox containers
8+
- **Multiple Proxy Types**: Support for HTTP, HTTPS, and SOCKS5 proxies
9+
- **Proxy Labels**: Add custom labels/comments to identify your proxies (e.g., "Seattle Server", "Work VPN")
10+
- **Dark Mode Support**: Automatic dark theme based on system preferences
11+
- **Export/Import**: Backup and restore your proxy configurations
12+
- **Connection Testing**: Test proxy connections before saving
13+
- **Modern UI**: Clean, intuitive interface with responsive design
14+
15+
## 📦 Installation
16+
17+
### From Release (Recommended)
18+
1. Download the latest release from the [Releases](../../releases) page
19+
2. Open Firefox and go to `about:addons`
20+
3. Click the gear icon and select "Install Add-on From File"
21+
4. Select the downloaded `.zip` file
22+
23+
### Manual Installation (Development)
24+
1. Clone or download this repository
25+
2. Open Firefox and go to `about:debugging`
26+
3. Click "This Firefox" → "Load Temporary Add-on"
27+
4. Navigate to the `container-proxy-modern` folder and select `manifest.json`
28+
29+
## 🚀 Quick Start
30+
31+
### 1. Set up Firefox Containers
32+
- Go to Firefox Settings → General → Tabs
33+
- Enable "Multi-Account Containers"
34+
- Create containers for different purposes (Work, Personal, etc.)
35+
36+
### 2. Configure Proxies
37+
- Click the Container Proxy extension icon
38+
- Click "Add Proxy" for any container
39+
- Fill in your proxy details:
40+
- **Type**: HTTP, HTTPS, or SOCKS5
41+
- **Host**: Your proxy server IP/hostname
42+
- **Port**: Proxy server port
43+
- **Label**: Optional description (e.g., "Seattle Server")
44+
- **Credentials**: Username/password if required
45+
46+
### 3. Browse Securely
47+
- Open tabs in different containers
48+
- Each container will automatically use its assigned proxy
49+
- Default container remains unproxied
50+
51+
## 🔧 Supported Proxy Types
52+
53+
### HTTP Proxy
54+
- Standard HTTP proxy
55+
- Traffic to proxy is unencrypted
56+
- Good for basic routing
57+
58+
### HTTPS Proxy
59+
- Encrypted connection to proxy
60+
- More secure than HTTP
61+
- Recommended for sensitive browsing
62+
63+
### SOCKS5 Proxy (Recommended)
64+
- Most secure proxy type
65+
- Supports DNS routing through proxy
66+
- Best choice for privacy
67+
68+
## 🛡️ Security & Privacy
69+
70+
### ✅ Security Features
71+
- **DNS Protection**: SOCKS5 proxies route DNS through the proxy
72+
- **Credential Security**: Credentials only sent when explicitly provided
73+
- **Container Isolation**: Each container uses its own proxy independently
74+
- **No Data Logging**: Extension doesn't log or store browsing data
75+
76+
### ⚠️ Security Considerations
77+
- **HTTP Proxies**: Traffic to proxy is unencrypted (use HTTPS/SOCKS5 when possible)
78+
- **WebRTC Leaks**: Disable WebRTC in Firefox to prevent IP leaks
79+
- **Default Container**: Default Firefox container doesn't use proxy
80+
- **Credentials Storage**: Stored locally in Firefox (encrypted by Firefox)
81+
82+
**Recommendation**: Use SOCKS5 proxies with services like Gluetun for best security.
83+
84+
## 🐳 Gluetun Setup Example
85+
86+
If you're using Gluetun containers for VPN routing:
87+
88+
```
89+
Type: HTTP
90+
Host: 172.17.0.2 (your Gluetun container IP)
91+
Port: 8888
92+
Username: (leave empty)
93+
Password: (leave empty)
94+
Label: Gluetun VPN
95+
```
96+
97+
## 📋 Permissions Explained
98+
99+
This extension requires the following permissions:
100+
101+
- **`webRequest`**: To intercept web requests for proxy routing
102+
- **`webRequestBlocking`**: To modify requests before they're sent
103+
- **`proxy`**: To configure proxy settings
104+
- **`contextualIdentities`**: To work with Firefox containers
105+
- **`storage`**: To save proxy configurations
106+
- **`<all_urls>`**: To route traffic from all websites through proxies
107+
108+
These permissions are necessary for any proxy extension to function properly.
109+
110+
## 🤝 Contributing
111+
112+
1. Fork the repository
113+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
114+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
115+
4. Push to the branch (`git push origin feature/amazing-feature`)
116+
5. Open a Pull Request
117+
118+
## 📄 License
119+
120+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
121+
122+
## 🐛 Bug Reports & Feature Requests
123+
124+
Please use the [GitHub Issues](../../issues) page to report bugs or request features.
125+
126+
## 🔗 Related Projects
127+
128+
- [Firefox Multi-Account Containers](https://addons.mozilla.org/en-US/firefox/addon/multi-account-containers/)
129+
- [Gluetun VPN Container](https://github.com/qdm12/gluetun)
130+
131+
---
132+
133+
**Made with ❤️ for privacy-conscious browsing**

background.js

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
// Container Proxy Extension - Background Script
2+
console.log('Container Proxy: Background script loaded');
3+
4+
class ContainerProxyManager {
5+
constructor() {
6+
this.containerProxies = new Map();
7+
this.init();
8+
}
9+
10+
async init() {
11+
// Load saved proxy configurations
12+
await this.loadProxyConfigs();
13+
14+
// Set up proxy request handler
15+
browser.proxy.onRequest.addListener(
16+
this.handleProxyRequest.bind(this),
17+
{ urls: ["<all_urls>"] }
18+
);
19+
20+
// Handle proxy authentication
21+
browser.webRequest.onAuthRequired.addListener(
22+
this.handleAuth.bind(this),
23+
{ urls: ["<all_urls>"] },
24+
["blocking"]
25+
);
26+
27+
console.log('Container Proxy: Initialized successfully');
28+
}
29+
30+
async loadProxyConfigs() {
31+
try {
32+
const data = await browser.storage.local.get('containerProxies');
33+
if (data.containerProxies) {
34+
this.containerProxies = new Map(Object.entries(data.containerProxies));
35+
console.log('Container Proxy: Loaded configurations for', this.containerProxies.size, 'containers');
36+
}
37+
} catch (error) {
38+
console.error('Container Proxy: Error loading configs:', error);
39+
}
40+
}
41+
42+
async saveProxyConfigs() {
43+
try {
44+
const configObject = Object.fromEntries(this.containerProxies);
45+
await browser.storage.local.set({ containerProxies: configObject });
46+
console.log('Container Proxy: Configurations saved');
47+
} catch (error) {
48+
console.error('Container Proxy: Error saving configs:', error);
49+
}
50+
}
51+
52+
async handleProxyRequest(requestDetails) {
53+
try {
54+
const cookieStoreId = requestDetails.cookieStoreId;
55+
56+
// Skip default container
57+
if (!cookieStoreId || cookieStoreId === 'firefox-default') {
58+
return { type: "direct" };
59+
}
60+
61+
const proxyConfig = this.containerProxies.get(cookieStoreId);
62+
if (!proxyConfig || !proxyConfig.enabled) {
63+
return { type: "direct" };
64+
}
65+
66+
console.log(`Container Proxy: Routing ${requestDetails.url} through proxy for container ${cookieStoreId}`);
67+
68+
const proxyInfo = {
69+
type: proxyConfig.type.toLowerCase(),
70+
host: proxyConfig.host,
71+
port: parseInt(proxyConfig.port),
72+
proxyDNS: proxyConfig.type === 'SOCKS5'
73+
};
74+
75+
// Only add username/password if they are actually provided
76+
if (proxyConfig.username && proxyConfig.username.trim()) {
77+
proxyInfo.username = proxyConfig.username.trim();
78+
}
79+
if (proxyConfig.password && proxyConfig.password.trim()) {
80+
proxyInfo.password = proxyConfig.password.trim();
81+
}
82+
83+
return [proxyInfo];
84+
} catch (error) {
85+
console.error('Container Proxy: Error in proxy request handler:', error);
86+
return { type: "direct" };
87+
}
88+
}
89+
90+
handleAuth(details) {
91+
const cookieStoreId = details.cookieStoreId;
92+
const proxyConfig = this.containerProxies.get(cookieStoreId);
93+
94+
if (proxyConfig && proxyConfig.username && proxyConfig.username.trim() &&
95+
proxyConfig.password && proxyConfig.password.trim()) {
96+
console.log('Container Proxy: Providing auth for container', cookieStoreId);
97+
return {
98+
authCredentials: {
99+
username: proxyConfig.username.trim(),
100+
password: proxyConfig.password.trim()
101+
}
102+
};
103+
}
104+
105+
return { cancel: false };
106+
}
107+
108+
// API methods for UI
109+
async setContainerProxy(containerId, proxyConfig) {
110+
this.containerProxies.set(containerId, proxyConfig);
111+
await this.saveProxyConfigs();
112+
return true;
113+
}
114+
115+
async removeContainerProxy(containerId) {
116+
this.containerProxies.delete(containerId);
117+
await this.saveProxyConfigs();
118+
return true;
119+
}
120+
121+
getContainerProxy(containerId) {
122+
return this.containerProxies.get(containerId) || null;
123+
}
124+
125+
getAllProxyConfigs() {
126+
return Object.fromEntries(this.containerProxies);
127+
}
128+
}
129+
130+
// Initialize the manager
131+
const proxyManager = new ContainerProxyManager();
132+
133+
// Handle messages from popup/options page
134+
browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
135+
try {
136+
switch (message.action) {
137+
case 'setProxy':
138+
return await proxyManager.setContainerProxy(message.containerId, message.proxyConfig);
139+
140+
case 'removeProxy':
141+
return await proxyManager.removeContainerProxy(message.containerId);
142+
143+
case 'getProxy':
144+
return proxyManager.getContainerProxy(message.containerId);
145+
146+
case 'getAllProxies':
147+
return proxyManager.getAllProxyConfigs();
148+
149+
case 'testProxy':
150+
return await testProxyConnection(message.proxyConfig);
151+
152+
default:
153+
console.warn('Container Proxy: Unknown message action:', message.action);
154+
return false;
155+
}
156+
} catch (error) {
157+
console.error('Container Proxy: Error handling message:', error);
158+
return false;
159+
}
160+
});
161+
162+
// Test proxy connection
163+
async function testProxyConnection(proxyConfig) {
164+
try {
165+
// Simple test - try to make a request through the proxy
166+
// This is a basic implementation - you might want to enhance it
167+
console.log('Container Proxy: Testing proxy connection to', proxyConfig.host + ':' + proxyConfig.port);
168+
return { success: true, message: 'Proxy configuration saved successfully' };
169+
} catch (error) {
170+
console.error('Container Proxy: Proxy test failed:', error);
171+
return { success: false, message: 'Proxy test failed: ' + error.message };
172+
}
173+
}

icon.png

Lines changed: 33 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)