Untested base implementation

This commit is contained in:
Kumi 2023-11-05 10:47:50 +01:00
commit 5c05f01fd5
Signed by: kumi
GPG key ID: ECBCC9082395383F
4 changed files with 104 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
__pycache__/
*.py[cod]

19
LICENSE Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) 2023 Private.coffee Team <support@private.coffee>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

19
README.md Normal file
View file

@ -0,0 +1,19 @@
# IPv6 Rotator
This is a simple IPv6 rotator script that will assign a new random IPv6 address to a given interface and use it for requests to given subnets.
## Usage
```bash
python3 rotator.py
```
The script will automatically detect the interface with the default route and use it for the requests, and select a random IPv6 address from the /64 subnet of the default IP address. It will then add the IP to the network interface and create the required routes for the given subnets.
## Note
This script is not complete and is not intended to be used in production. It is currently only a PoC to show how to rotate IPv6 addresses on a Linux machine. Running it may cause your machine to lose IPv6 connectivity altogether. Don't run it on a machine you don't have physical access to.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

64
rotator.py Normal file
View file

@ -0,0 +1,64 @@
import socket
import random
import os
import subprocess
import ipaddress
# Google subnets to route through the random IP
SUBNETS = [
"2001:4860:4000::/36",
"2404:6800:4000::/36",
"2607:f8b0:4000::/36",
"2800:3f0:4000::/36",
"2a00:1450:4000::/36",
"2c0f:fb50:4000::/36",
]
TEST_IP_EXTERNAL = "2a0d:f302:111:38cc::1" # A public IPv6 NOT in the subnet
# 1) Get the machine's current primary IPv6 address
def get_current_ipv6():
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
s.connect((TEST_IP_EXTERNAL, 80))
current_ip = s.getsockname()[0]
return current_ip
# 2) Generate a random IP address within the /64 subnet of the current primary IPv6
def generate_random_ipv6(ipv6):
# Parse the original IP address and network
original = ipaddress.ip_interface(ipv6)
# Generate a random interface identifier
random_int = random.randint(1, 2**64 - 1)
new_ip = ipaddress.IPv6Interface((int(original.network.network_address) | random_int, original.network.prefixlen))
return str(new_ip.ip)
def main():
current_ipv6 = get_current_ipv6()
# Get network interface and gateway
default_route = subprocess.check_output("ip -6 route show default", shell=True).decode('utf-8')
iface = default_route.split("dev ")[1].split()[0]
current_gateway = default_route.split("via ")[1].split()[0]
random_ipv6 = generate_random_ipv6(current_ipv6)
# 2.5) Remove any existing non-given IPv6 addresses from previous runs of the scripts
prev_ips_raw_output = subprocess.check_output(f"ip -6 addr show {iface} scope global", shell=True).decode('utf-8')
prev_ips = [line.strip().split(" ")[1].split("/")[0] for line in prev_ips_raw_output.split("\n") if "inet6" in line]
for ip in prev_ips:
if ip != current_ipv6:
os.popen(f"sudo ip -6 addr del {ip} dev {iface}")
# 3) Add new IP to the interface
os.popen(f"sudo ip -6 addr add {random_ipv6} dev {iface}")
# 4) Set up routes such that the random IP address is now used as the source address for requests to given IPv6 subnets
for subnet in SUBNETS:
os.popen(f"sudo ip -6 route add {subnet} from {random_ipv6} dev {iface} via {current_gateway}")
if __name__ == "__main__":
main()