commit
ef74b1c529
@ -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…
Reference in new issue