keepalived + nginx Load balancing, cannot access VIP - nginx

server A(master): nginx 1.9.9 + keepalived 1.2.19, IP: 9.110.95.90
server B(backup): nginx 1.9.9 + keepalived 1.2.19, IP: 9.110.95.91
VIP(virtual IP): 9.110.95.95
nginx bind on all interfaces.
iptables configuration:
iptables -I INPUT -i eth1 -d 224.0.0.0/8 -p vrrp -j ACCEPT
iptables -I OUTPUT -o eth1 -d 224.0.0.0/8 -p vrrp -j ACCEPT
Keepalived configuration:
server A
global_defs {
router_id LVS_MASTER
}
vrrp_script chk_nginx {
script "killall -0 nginx"
interval 2
}
vrrp_instance VI_1 {
state MASTER
interface eth1
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass my_pass
}
virtual_ipaddress {
9.110.95.95
}
track_script {
chk_nginx
}
}
server B
global_defs {
router_id LVS_BACKUP
}
vrrp_script chk_nginx {
script "killall -0 nginx"
interval 2
}
vrrp_instance VI_1 {
state BACKUP
interface eth1
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass my_pass
}
virtual_ipaddress {
9.110.95.95
}
track_script {
chk_nginx
}
}
It works fine at beginning when accessing the VIP (9.110.95.95), and it also failover to backup node successfully, if stopped keepalived on master node.
Everything seems to be fine, BUT the client failed to access the VIP after some time later, probably several minutes. and if access the server A/B IP(9.110.95.90, 9.110.95.91) it works.
Not sure what's the issue, any ideas?
Thanks

Related

How do I update the connection chain (appsetting.json) in a docker command for a Blazor app?

I would like to know how to update the connection chain from a docker command.
Example for Wordpress:
docker run --name myWordpress -d -p 8080:80 -e WORDPRESS_DB_HOST=123.123.123.123:3306 -e WORDPRESS_DB_USER=rootUser -e WORDPRESS_DB_PASSWORD=password ....
I have a blazor server application that needs to connect to a MySQL database, here's the connection chain (appsetting.json)
"ConnectionStrings": {
"MySqlConnection": "server=YourDatabase;user id=username;password=YourPassword;database=yourDb"
},
I'd like to be able to do a docker command:
docker run -d -e server=123.123.123.123 -e uid=UserName -e password=MyPass ...
and update the file appsetting.json, but How ?
Thanks for help.
I found a solution.
My appsetting.json
"ConnectionStrings": {
"MySqlConnection": "server=YOURDATABASE;user id=USERNAME;password=YOURPASSWORD;database=YOURDB"
}
In my Startup.cs
public void ConfigureServices(IServiceCollection services)
{
string connectionDb = Configuration.GetConnectionString("MySqlConnection");
string databaseAddress = Environment.GetEnvironmentVariable("DB_HOST");
string login = Environment.GetEnvironmentVariable("LOGIN_DB");
string mdp = Environment.GetEnvironmentVariable("PASSWORD_DB");
string dbName = Environment.GetEnvironmentVariable("DB_NAME");
connectionDb = connectionDb.Replace("USERNAME", login)
.Replace("YOURPASSWORD", mdp)
.Replace("YOURDB", dbName)
.Replace("YOURDATABASE", databaseAddress);
services.AddDbContext<ApplicationDbContext>(options => options.UseMySql(connectionDb, ServerVersion.AutoDetect(connectionDb)));
// Service SQL de AccessData.
services.AddSingleton(new SqlContextAccess(connectionDb));
...
My Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
ENV DB_HOST="YourAddressdatabase"
ENV LOGIN_DB="YourLogin"
ENV PASSWORD_DB="YourPassword"
ENV DB_NAME="YourDbName"
...
and my docker command :
docker run -d -p 3030:80 \
-e LOGIN_DB=myLogin \
-e PASSWORD_DB=SuperPassword \
-e DB_NAME=nameOfMydb \
-e DB_HOST=123.123.123.123 \
--name test myImage:latest

Two Mikrotik site's behind NAT to Strongswan with public ip

I am trying to reproduce the schema like in strongswan test net2net-gw, but with "moon" and "sun" behind NAT (see https://www.strongswan.org/testing/testresults/swanctl/net2net-gw/). So far CA configured, certs issued, mikrotik's configured, i can establish tunnels and have SA set, but i can't ping one site from another.
Carol config :
connections {
gw-base {
local {
auth = pubkey
certs = carol.crt
id = carol
}
remote {
auth = pubkey
}
children {
net {
esp_proposals = aes128-sha1-modp2048,aes256-sha256-modp2048
}
}
version = 2
mobike = no
proposals = aes128-sha1-modp2048,aes256-sha256-modp2048
pools = pool-ipv4
}
gw-moon : connections.gw-base{
remote {
id = moon
}
children {
net {
local_ts = 192.168.3.0/24
remote_ts = 192.168.1.0/24
updown = /usr/libexec/strongswan/_updown iptables
}
}
}
gw-sun : connections.gw-base {
remote {
id = sun
}
children {
net {
local_ts = 192.168.1.0/24
remote_ts = 192.168.3.0/24
updown = /usr/libexec/strongswan/_updown iptables
}
}
}
}
pools {
pool-ipv4 {
addrs = 192.168.99.0/24
}
}
here is "moon" mikrotik config local subnet 192.168.1.0/24 :
/ip ipsec mode-config
add name=ike2 responder=no
/ip ipsec policy group
add name=ike2
/ip ipsec profile
set [ find default=yes ] enc-algorithm=aes-128
add dh-group=modp2048 enc-algorithm=aes-128 name=ike2
/ip ipsec peer
add address=carol exchange-mode=ike2 name=ike2 profile=ike2
/ip ipsec proposal
add enc-algorithms=aes-128-cbc name=ike2 pfs-group=modp2048
/ip ipsec identity
add auth-method=digital-signature certificate=moon.p12_0 generate-policy=port-strict mode-config=ike2 notrack-chain=prerouting peer=ike2 policy-template-group=ike2
/ip ipsec policy
add dst-address=192.168.3.0/24 group=ike2 proposal=ike2 src-address=192.168.1.0/24 template=yes
/ip ipsec settings
set accounting=no
here is "sun" mikrotik config local subnet 192.168.3.0/24 :
/ip ipsec mode-config
add name=ike2 responder=no
/ip ipsec policy group
add name=ike2
/ip ipsec profile
set [ find default=yes ] enc-algorithm=aes-128
add dh-group=modp2048 enc-algorithm=aes-128 name=ike2
/ip ipsec peer
add address=carol exchange-mode=ike2 name=ike2 profile=ike2
/ip ipsec proposal
add enc-algorithms=aes-128-cbc name=ike2 pfs-group=modp2048
/ip ipsec identity
add auth-method=digital-signature certificate=sun.p12_0 generate-policy=port-strict mode-config=ike2 notrack-chain=prerouting peer=ike2 policy-template-group=ike2
/ip ipsec policy
add dst-address=192.168.1.0/24 group=ike2 proposal=ike2 src-address=192.168.3.0/24 template=yes
/ip ipsec settings
set accounting=no
"carol" output for swanctl -l
gw-moon: #12, ESTABLISHED, IKEv2, 278ded8c94f60a25_i dc1ea6a863cbbc3f_r*
local 'carol' # PUBLICIP[4500]
remote 'moon' # NATIP[9860] [192.168.99.1]
AES_CBC-128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_2048
established 1938s ago, rekeying in 11168s
net: #11, reqid 8, INSTALLED, TUNNEL-in-UDP, ESP:AES_CBC-128/HMAC_SHA1_96/MODP_2048
installed 498s ago, rekeying in 2840s, expires in 3462s
in cb0314bb, 0 bytes, 0 packets
out 0159b817, 0 bytes, 0 packets
local 192.168.3.0/24
remote 192.168.1.0/24
gw-sun: #11, ESTABLISHED, IKEv2, b972f69efe68b876_i 1c57914f302e627b_r*
local 'carol' # PUBLICIP[4500]
remote 'sun' # NATIP[4500] [192.168.99.2]
AES_CBC-128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_2048
established 1962s ago, rekeying in 11975s
net: #10, reqid 7, INSTALLED, TUNNEL-in-UDP, ESP:AES_CBC-128/HMAC_SHA1_96/MODP_2048
installed 519s ago, rekeying in 2890s, expires in 3441s
in c3a515f5, 2856 bytes, 34 packets, 0s ago
out 0b5614c6, 0 bytes, 0 packets
local 192.168.1.0/24
remote 192.168.3.0/24
"carol" iptables have :
-A FORWARD -s 192.168.1.0/24 -d 192.168.3.0/24 -i eth0 -m policy --dir in --pol ipsec --reqid 8 --proto esp -j ACCEPT
-A FORWARD -s 192.168.3.0/24 -d 192.168.1.0/24 -o eth0 -m policy --dir out --pol ipsec --reqid 8 --proto esp -j ACCEPT
-A FORWARD -s 192.168.3.0/24 -d 192.168.1.0/24 -i eth0 -m policy --dir in --pol ipsec --reqid 7 --proto esp -j ACCEPT
-A FORWARD -s 192.168.1.0/24 -d 192.168.3.0/24 -o eth0 -m policy --dir out --pol ipsec --reqid 7 --proto esp -j ACCEPT
"carol" has sysctl
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
"carol" tcpdump net 192.168.0.0/16 when i run ping from one of workstations 192.168.3.254 behind "sun" :
08:46:57.820968 IP 192.168.3.254 > 192.168.1.1: ICMP echo request, id 30901, seq 357, length 64
08:46:57.821075 IP PUBLICIP > 192.168.1.1: ICMP echo request, id 30901, seq 357, length 64
PUBLICIP = carols public internet ip
NATIP = sun & moon nat ip
whet i try to ping 192.168.1.1 from "sun" i see that packet counter for increases, but no reply,
the same as if i ping 192.168.3.1 from "moon". BUT if i disconnect "sun" and add virtual ip address 192.168.3.1 to carol ip addr add 192.168.3.1/24 dev eth0 ping from "moon" to 192.168.3.1 succeeds, but strange thing - i cant ping "moon" from carol...
Thank's for any advice in advance :)

WireGuard could not connect to the internet except server side

I am using wireguard,this is my server config in /etc/wireguard/wireguard.conf :
[Interface]
Address = 0.0.0.0
# server private key
PrivateKey = GL7AIArkhGTKkz3vSn/ONifC7SKJtspYDDZEtAybyVE=
ListenPort = 51820
[Peer]
# windows client public key
PublicKey = 3omwALzVoZhaqdu6dwL9vpRFlv+1omznmtuQKdwODFE=
AllowedIPs = 192.168.3.0/24
This is my client config:
[Interface]
PrivateKey = f4e60OIQXMdny6+hBDwddHB6tGS6a4WKYpG89ERQK+Tk=
Address = 192.168.3.1/24
[Peer]
PublicKey = 72Gix3UR/coszkazkVp3ieRrlMTOK8ia2TISnaD1Az4=
Endpoint = 14.80.12.186:51820
AllowedIPs = 0.0.0.0/0
The client using tunsafe,and connect successful.The question is:after connect to wireguard,I could not access the internet exception the wireguard server,this is the server ipv4 forward config:
[root#dolphin-xiaoqiang ~]# sysctl -a |grep net.ipv4.ip_forward
sysctl: reading key "net.ipv6.conf.all.stable_secret"
sysctl: reading key "net.ipv6.conf.default.stable_secret"
sysctl: reading key "net.ipv6.conf.eth0.stable_secret"
sysctl: reading key "net.ipv6.conf.lo.stable_secret"
net.ipv4.ip_forward = 1
net.ipv4.ip_forward_use_pmtu = 0
Add iptables rule on server side:
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Simple UDP server OCaml/Async

I'm trying to do a simple UDP server using OCaml and the Async API but I'm stuck. I can't make this simple example work.
let wait_for_datagram () : unit Deferred.t =
let port = 9999 in
let addr = Socket.Address.Inet.create Unix.Inet_addr.localhost ~port in
let%bind socket = Udp.bind addr in
let socket = Socket.fd socket in
let stop = never () in
let config = Udp.Config.create ~stop () in
let callback buf _ : unit = failwith "got a datagram" in
Udp.recvfrom_loop ~config socket callback
I test it with:
echo -n "hello goodbye" > /dev/udp/localhost/9999
Nothing happens in my program. I tried to investigate with other tools.
I see a destination unreachable packet with Wireshark and lsof shows me this:
> lsof -i :9999
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
main.exe 77564 nemo 5u IPv4 0x25251bcc3485235f 0t0 UDP localhost:distinct
What am I doing wrong here?
The code looks ok to me. I think localhost is resolved to IPv6 address by default, and you just send it there.
Try to force using IPv4 protocol
echo -n "hello goodbye" | nc -4 -u -w0 localhost 9999
or specify explicit IPv4 address
echo -n "hello goodbye" > /dev/udp/127.0.0.1/9999

Production Thin Best Practices

I'm using Thin as a server for Faye. To do that, I use something like this:
require 'faye'
bayeux = Faye::RackAdapter.new(:mount => '/faye', :timeout => 25)
bayeux.listen(9292)
The Thin process is monitored by God and all is well in Development.
However, I'm not sure if this is the right setup for a production configuration. What I would like to know is how is this setup (with no Nginx or HAProxy at the front) is going to perform in a production environment.
this is my god config.
#Faye
ports = [9292, 9293, 9294, 9295]
ports.each_with_index do |port, id|
God.watch do |w|
w.dir = "#{rails_root}"
w.name = "faye-#{port}"
w.group = "faye"
w.interval = 30.seconds
w.start = "thin start -R #{rails_root}/faye.ru -e production -p #{port} -P #{rails_root}tmp/pids/faye-#{port}.pid"
w.stop = "thin stop -P #{rails_root}tmp/pids/faye-#{port}.pid"
w.log = "#{rails_root}/log/god_node.log"
#w.uid = 'server'
#w.gid = 'server'
# restart if memory usage is > 500mb
w.transition(:up, :restart) do |on|
on.condition(:memory_usage) do |c|
c.above = 500.megabytes
c.times = 2
end
end
# determine the state on startup
w.transition(:init, { true => :up, false => :start }) do |on|
on.condition(:process_running) do |c|
c.running = true
end
end
# determine when process has finished starting
w.transition([:start, :restart], :up) do |on|
on.condition(:process_running) do |c|
c.running = true
c.interval = 10.seconds
end
# failsafe
on.condition(:tries) do |c|
c.times = 5
c.transition = :start
c.interval = 10.seconds
end
end
# start if process is not running
w.transition(:up, :start) do |on|
on.condition(:process_running) do |c|
c.running = false
end
end
end
end
and i'm using nginx to load balancing.
I have been using thin to run faye with redis. making sure to set
Faye::WebSocket.load_adapter('thin')
all traffic goes through haproxy (the first one is named proxied as I redirect all traffic to https)
frontend proxied
bind 127.0.0.1:81 accept-proxy
timeout client 86400000
default_backend nginx_backend
acl is_websocket hdr(Upgrade) -i WebSocket
acl is_websocket hdr_beg(Host) -i ws
use_backend socket_backend if is_websocket
backend nginx_backend
balance roundrobin
option forwardfor #except 127.0.0.1 # This sets X-Forwarded-For
timeout server 30000
timeout connect 4000
server nginx1 localhost:8081 weight 1 maxconn 20000 check
backend socket_backend
balance roundrobin
option forwardfor except 127.0.0.1 # This sets X-Forwarded-For
timeout queue 5000
timeout server 86400000
timeout connect 86400000
server socket1 localhost:3100 weight 1 maxconn 20000 check
server socket2 localhost:3101 weight 1 maxconn 20000 check
server socket3 localhost:3102 weight 1 maxconn 20000 check
server socket4 localhost:3103 weight 1 maxconn 20000 check
...
if it is http traffic I route it through nginx which forwards to the same set of thin instances if it includes the /faye path.
I am not an haproxy expert but this is working for websocket and long poll connections.

Resources