Skip to content

Commit

Permalink
refactor: transition from DNS server to hosts file modification
Browse files Browse the repository at this point in the history
Updated main.go to change the functionality:
- Removed DNS server setup.
- Added code to modify the hosts file on Windows.
- Incorporated testing connection functionality using 'ping'.
- Enhanced logging for better clarity.
  • Loading branch information
BadEnd777 committed Jan 21, 2024
1 parent f37d219 commit 74233b4
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 113 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ VRConnectivity-Shield
*.log

# Ignore the Go Modules cache
/go.sum
/go.mod
go.sum
go.mod

# Ignore system and temporary files
.DS_Store
Expand Down
40 changes: 28 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
<img src="https://img.shields.io/github/v/release/Onyx-Innovators/VRConnectivity-Shield" alt="Release">
</div>

VRConnectivity Shield is a DNS blocking utility implemented in Go, designed to block specific hosts by responding to DNS requests with 0.0.0.0. This can be useful for preventing unwanted connections to analytics services, telemetry servers, etc.

> [!NOTE]
> This project is focused on blocking hosts related to VRChat. If you are looking for a more general purpose DNS blocking utility, check out [HostsMan](https://www.abelhadigital.com/hostsman/). It is a great tool for managing your hosts file.
VRConnectivity Shield is a simple DNS blocking utility for Windows. It is designed to block hosts related to VRChat analytics. This utility is intended to be used in conjunction with a VPN to prevent VRChat from collecting analytics data while playing the game.

## Usage

Expand All @@ -22,24 +19,43 @@ VRConnectivity Shield is a DNS blocking utility implemented in Go, designed to b
To use VRConnectivity Shield, follow these simple steps:

1. **Download:** Obtain the executable file for your platform from the [Releases](https://github.com/Onyx-Innovators/VRConnectivity-Shield/releases) page.

2. **Run:** Execute the VRConnectivity-Shield.exe executable to start the DNS blocking utility.

### Configuration
## Development

To build the project from source, follow these steps:

1. **Clone:** Clone the repository to your local machine.
```bash
git clone https://github.com/Onyx-Innovators/VRConnectivity-Shield.git
```
2. **Navigate:** Navigate to the project directory.
```bash
cd VRConnectivity-Shield/src
```

3. **Build:** Build the project using the Go compiler.
```bash
go build -o VRConnectivity-Shield.exe
```
4. **Run:** Execute the VRConnectivity-Shield.exe executable to start the DNS blocking utility.

## Configuration

The list of blocked hosts is sourced from [VRChat-Analytics-Blocker](https://github.com/DubyaDude/VRChat-Analytics-Blocker). The blocked hosts are defined in the utils/blockedHosts map in the utils package. You can modify this map to include or exclude specific hosts as needed.
The list of blocked hosts is sourced from [VRChat-Analytics-Blocker](https://github.com/DubyaDude/VRChat-Analytics-Blocker). The blocked hosts are defined in the `main.go` map in the utils package. You can modify this map to include or exclude specific hosts as needed.

```go
var blockedHosts = map[string]struct{}{
"api.amplitude.com": {},
"api2.amplitude.com": {},
// Add or remove hosts as necessary
var hostsToAdd = []string{
"api.amplitude.com",
"api2.amplitude.com",
// Add specific hosts here
}
```

## How it works

The program sets up a DNS server listening on UDP port 53. When a DNS request is received, it checks if the requested host is in the list of blocked hosts. If it is, the request is blocked by responding with 0.0.0.0. Otherwise, the request is allowed to proceed.
The program will add the specified hosts to the hosts file located at `C:\Windows\System32\drivers\etc\hosts`. The hosts file is a text file that maps hostnames to IP addresses. When a DNS request is made for a hostname that is defined in the hosts file, the DNS resolver will use the IP address specified in the hosts file instead of querying a DNS server.

## License

Expand Down
31 changes: 0 additions & 31 deletions main.go

This file was deleted.

83 changes: 83 additions & 0 deletions src/file_operations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package main

import (
"bufio"
"fmt"
"os"
"os/exec"
"strings"
)

func createBackups(filePath string) ([]string, error) {
var backups []string
for i := 0; ; i++ {
backupPath := fmt.Sprintf("%s.backup-%d", filePath, i)
if _, err := os.Stat(backupPath); os.IsNotExist(err) {
err := exec.Command("cmd", "/C", "copy", filePath, backupPath).Run()
if err != nil {
return nil, err
}
backups = append(backups, backupPath)
break
}
}
return backups, nil
}

func readHostsFile(filePath string) ([]string, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, err
}
defer file.Close()

var hosts []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if len(line) > 0 && !strings.HasPrefix(line, "#") {
fields := strings.Fields(line)
if len(fields) >= 2 {
hosts = append(hosts, fields[1])
}
}
}

if err := scanner.Err(); err != nil {
return nil, err
}

return hosts, nil
}

func addHostToHostsFile(filePath, host string) error {
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY, os.ModeAppend) // Open file in append mode
if err != nil {
return err
}
defer file.Close()

if _, err := file.WriteString(fmt.Sprintf("0.0.0.0 %s\n", host)); err != nil {
return err
}

return nil
}

func contains(slice []string, item string) bool {
for _, s := range slice {
if s == item {
return true
}
}
return false
}

func flushDNSCache() error {
cmd := exec.Command("ipconfig", "/flushdns")
err := cmd.Run()
if err != nil {
return err
}
return nil
}
11 changes: 9 additions & 2 deletions logger/logger.go → src/logger.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package logger
package main

import (
"fmt"
Expand Down Expand Up @@ -46,7 +46,7 @@ func (l *Logger) Debug(message ...interface{}) {
}

func (l *Logger) Info(message ...interface{}) {
l.log(InfoLevel, color.New(color.FgBlue).SprintFunc(), message...)
l.log(InfoLevel, color.New(color.FgCyan).SprintFunc(), message...)
}

func (l *Logger) Warn(message ...interface{}) {
Expand All @@ -66,6 +66,13 @@ func (l *Logger) Success(message ...interface{}) {
l.log(SuccessLevel, color.New(color.FgGreen).SprintFunc(), message...)
}

func (l *Logger) Prompt(message string) string {
fmt.Printf("[%s] %s", time.Now().Format("15:04:05"), message)
var input string
fmt.Scanln(&input)
return input
}

func (l *Logger) SetEnableColors(enableColors bool) {
l.enableColors = enableColors
}
91 changes: 91 additions & 0 deletions src/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package main

import (
"fmt"
"os/exec"
"strings"
)

var hostsToAdd = []string{
"api.amplitude.com",
"api2.amplitude.com",
"api.lab.amplitude.com",
"api.eu.amplitude.com",
"regionconfig.amplitude.com",
"regionconfig.eu.amplitude.com",
"o1125869.ingest.sentry.io",
"api3.amplitude.com",
"cdn.amplitude.com",
"info.amplitude.com",
"static.amplitude.com",
"api.uca.cloud.unity3d.com",
"config.uca.cloud.unity3d.com",
"perf-events.cloud.unity3d.com",
"public.cloud.unity3d.com",
"cdp.cloud.unity3d.com",
"data-optout-service.uca.cloud.unity3d.com",
"ecommerce.iap.unity3d.com",
}

func main() {
// Get logger
log := GetLogger()

const hostsFilePath = "C:\\Windows\\System32\\drivers\\etc\\hosts" // C:\Windows\System32\drivers\etc\hosts
existingHosts, err := readHostsFile(hostsFilePath)
if err != nil {
log.Error("Error reading hosts file in readHostsFile:", err)
return
}

backups, err := createBackups(hostsFilePath)
if err != nil {
log.Error(fmt.Sprintf("Error creating backups: %s", err))
} else {
log.Success(fmt.Sprintf("Successfully created backups: %s", strings.Join(backups, ", ")))
}

for _, host := range hostsToAdd {
if contains(existingHosts, host) {
log.Warn(fmt.Sprintf("Host %s already exists in hosts file", host))
} else {
err := addHostToHostsFile(hostsFilePath, host)
if err != nil {
log.Error(fmt.Sprintf("Error adding host %s to hosts file: %s", host, err))
} else {
log.Success(fmt.Sprintf("Successfully added host %s to hosts file", host))
}
}
}

// Flush DNS cache
err = flushDNSCache()
if err != nil {
log.Error(fmt.Sprintf("Error flushing DNS cache: %s", err))
} else {
log.Success("Successfully flushed DNS cache")
}

comfirmation := log.Prompt("Do you want to test the connection? (y/n): ")
for comfirmation != "y" && comfirmation != "n" {
comfirmation = log.Prompt("Please enter y or n: ")
}

if comfirmation == "y" {
// Test connection
log.Info("Testing connection...")
for _, host := range hostsToAdd {
cmd := exec.Command("ping", host, "-n", "1", "-w", "1000") // Ping host once with 1 second timeout
err := cmd.Run()
if err != nil {
log.Error(fmt.Sprintf("Error pinging host %s: %s", host, err))
} else {
log.Success(fmt.Sprintf("Successfully pinged host %s", host))
}
}

log.Info("This program will block the a VRChat analytics and telemetry servers.")
log.Info("If it works, you should see a lot of \"Error pinging host\" messages.")
log.Info("Because the program blocks the servers, it will not be able to connect to them.")
}
}
66 changes: 0 additions & 66 deletions utils/utils.go

This file was deleted.

0 comments on commit 74233b4

Please sign in to comment.