initial commit

master
vaninpetr 3 years ago
commit ef74b1c529
  1. 33
      README.md
  2. 8
      config.yml
  3. 135
      src/main.go

@ -0,0 +1,33 @@
# Regela ARP proxy
### Very simple, lazy method to configure arp tables
#### Written for our Virtuozzo's Community OS servers by Elizar [@Regela](https://sources.krechet.tech/Regela)
#### Include example config file in .yml, where is:
- name: *interfacename*
- addresses: *list of ips on interfacename*
#### Usage: move config.yum in folder /etc/RegelaArpProxy/ and run binary
```
~# RegelaArpProxy --help
Usage of RegelaArpProxy:
-example
-i string
Config File (default "/etc/RegelaArpProxy/config.yml")
~# RegelaArpProxy -example
interfaces:
- name: br0
addresses:
- 10.10.100.10
- 10.10.100.11
- 10.10.100.12
- 10.10.100.13
- name: br1
addresses:
- 10.10.101.10
- 10.10.101.11
- 10.10.101.12
- 10.10.101.13
```

@ -0,0 +1,8 @@
interfaces:
- name: vlan101
addresses:
- 10.10.3.2
- 10.10.3.5
- name: vlan102
addresses:
- 10.10.116.11

@ -0,0 +1,135 @@
package main
import (
"bytes"
"flag"
"fmt"
"github.com/goccy/go-yaml"
"github.com/mdlayher/arp"
"github.com/mdlayher/ethernet"
"io"
"io/ioutil"
"log"
"net"
"os"
"time"
)
type Interface struct{
Name string
Addresses []net.IP
}
type Settings struct {
Interfaces []Interface
}
var (
configFile = flag.String("i", "/etc/RegelaArpProxy/config.yml", "Config File")
printExampleFlag = flag.Bool("example",false,"")
)
func task(iface Interface){
ifi, err := net.InterfaceByName(iface.Name)
if err != nil {
log.Fatal(err)
}
client, err := arp.Dial(ifi)
if err != nil {
log.Fatalf("couldn't create ARP client: %s", err)
}
// Handle ARP requests bound for designated IPv4 address, using proxy ARP
// to indicate that the address belongs to this machine
for {
pkt, eth, err := client.Read()
if err != nil {
if err == io.EOF {
log.Println("EOF")
break
}
log.Fatalf("error processing ARP requests: %s", err)
}
// Ignore ARP replies
if pkt.Operation != arp.OperationRequest {
continue
}
// Ignore ARP requests which are not broadcast or bound directly for
// this machine
if !bytes.Equal(eth.Destination, ethernet.Broadcast) /*&& !bytes.Equal(eth.Destination, ifi.HardwareAddr)*/ {
continue
}
log.Printf("request: who-has %s? tell %s (%s)", pkt.TargetIP, pkt.SenderIP, pkt.SenderHardwareAddr)
// Ignore ARP requests which do not indicate the target IP
for _, ip := range iface.Addresses {
if pkt.TargetIP.Equal(ip) {
log.Printf(" reply: %s is-at %s", ip, ifi.HardwareAddr)
if err := client.Reply(pkt, ifi.HardwareAddr, ip); err != nil {
log.Fatal(err)
}
}
}
}
}
func printExample() {
settings := Settings{
Interfaces: []Interface{
{
Name: "br0",
Addresses: []net.IP{
net.ParseIP("10.10.100.10"),
net.ParseIP("10.10.100.11"),
net.ParseIP("10.10.100.12"),
net.ParseIP("10.10.100.13"),
},
},
{
Name: "br1",
Addresses: []net.IP{
net.ParseIP("10.10.101.10"),
net.ParseIP("10.10.101.11"),
net.ParseIP("10.10.101.12"),
net.ParseIP("10.10.101.13"),
},
},
},
}
out, _ := yaml.Marshal(settings)
fmt.Printf("%s",out)
}
func main() {
flag.Parse()
if *printExampleFlag{
printExample()
os.Exit(0)
}
cf, err := ioutil.ReadFile(*configFile)
if err != nil {
log.Fatalf("Read configuration error: %s", err.Error())
}
settings := Settings{}
err = yaml.Unmarshal(cf,&settings)
for _, iface := range settings.Interfaces {
go task(iface)
}
for {
time.Sleep(time.Hour)
}
// Ensure valid interface and IPv4 address
}
Loading…
Cancel
Save