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